<?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>Vendor on Tarragon</title><link>https://tarrragon.github.io/blog/tags/vendor/</link><description>Recent content in Vendor on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Tue, 23 Jun 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/tags/vendor/index.xml" rel="self" type="application/rss+xml"/><item><title>Chaos Mesh：Workflow、Scope Control 與 Steady State Probe</title><link>https://tarrragon.github.io/blog/backend/06-reliability/vendors/chaos-mesh/workflow-experiment-scope-and-steady-state-probe/</link><pubDate>Tue, 23 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/06-reliability/vendors/chaos-mesh/workflow-experiment-scope-and-steady-state-probe/</guid><description>&lt;h2 id="問題情境">問題情境&lt;/h2>
&lt;p>單一 ChaosExperiment（PodChaos pod-kill、NetworkChaos delay）只能驗證一個故障面向。真實的可靠性驗證需要多步驟編排：先注入依賴延遲，觀察 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/steady-state/" data-link-title="Steady State" data-link-desc="說明可靠性實驗與事故恢復如何定義系統應維持的可接受狀態">steady state&lt;/a> 是否維持，再注入節點失效，最後驗證恢復路徑。Chaos Workflow 提供這個編排能力，把多個 fault injection 與 health check 組成可重播的驗證流程。&lt;/p>
&lt;p>experiment scope 的精準控制同樣關鍵。selector 選到 production 全部 pod 的 chaos experiment 會變成真實事故。scope control 的責任是讓 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/blast-radius/" data-link-title="Blast Radius" data-link-desc="說明事故影響面如何估算與隔離">blast radius&lt;/a> 從最小範圍開始，逐步放大，每一步都有停止條件。&lt;/p>
&lt;h2 id="chaos-workflow-設計">Chaos Workflow 設計&lt;/h2>
&lt;p>Chaos Workflow 是多個 ChaosExperiment 與 StatusCheck 組成的 DAG（有向無環圖），用 YAML 定義步驟順序與分支條件。&lt;/p>
&lt;h3 id="步驟類型">步驟類型&lt;/h3>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>類型&lt;/th>
 &lt;th>責任&lt;/th>
 &lt;th>適用場景&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Serial&lt;/td>
 &lt;td>順序執行，前一步完成才進下一步&lt;/td>
 &lt;td>依賴故障 → 觀察 → 節點故障&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Parallel&lt;/td>
 &lt;td>平行執行多個注入&lt;/td>
 &lt;td>同時打多個依賴驗證交叉影響&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Suspend&lt;/td>
 &lt;td>暫停等待人工確認後再繼續&lt;/td>
 &lt;td>高風險步驟前的 approval gate&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>StatusCheck&lt;/td>
 &lt;td>對 HTTP / gRPC / custom script 做 probe&lt;/td>
 &lt;td>注入前後的 steady state 驗證&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>StatusCheck 是 workflow 的核心控制面。它在故障注入前後對目標 endpoint 做 health check，pass/fail 決定 workflow 是否繼續。StatusCheck 的 success condition 對應 &lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/steady-state-definition/" data-link-title="6.22 Steady State Definition" data-link-desc="在 chaos 與 failover 前先定義系統應維持的穩定狀態與可接受退化">6.22 steady state definition&lt;/a> 的穩態門檻：success rate、latency、queue lag 都能作為 probe 判準。&lt;/p>
&lt;p>典型 workflow 編排：NetworkChaos(delay 200ms) → StatusCheck(api-latency-ok) → PodChaos(pod-kill) → StatusCheck(recovery-within-30s)。第一個 StatusCheck 驗證延遲注入後服務仍可用；第二個 StatusCheck 驗證節點失效後恢復時間可接受。&lt;/p>
&lt;h3 id="suspend-的使用時機">Suspend 的使用時機&lt;/h3>
&lt;p>Suspend 步驟適合放在 blast radius 擴大之前。例如先在 canary namespace 跑完 chaos + StatusCheck，通過後 Suspend 等待值班工程師確認，再擴大到 production namespace。Suspend 讓自動化 workflow 在關鍵決策點保留人工判斷。&lt;/p>
&lt;h2 id="experiment-scope-control">Experiment Scope Control&lt;/h2>
&lt;p>Scope control 的責任是讓每個 ChaosExperiment 的影響面可預測、可限制。Chaos Mesh 用 selector + mode 兩層控制。&lt;/p>
&lt;h3 id="selector">Selector&lt;/h3>
&lt;p>Selector 決定哪些 pod 是實驗目標。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Selector 類型&lt;/th>
 &lt;th>作用&lt;/th>
 &lt;th>範例&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>namespace&lt;/td>
 &lt;td>限制在特定 namespace&lt;/td>
 &lt;td>&lt;code>namespaces: [canary]&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>labelSelector&lt;/td>
 &lt;td>按 label 篩選&lt;/td>
 &lt;td>&lt;code>app: checkout, tier: backend&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>annotationSelector&lt;/td>
 &lt;td>按 annotation 篩選&lt;/td>
 &lt;td>&lt;code>chaos-eligible: &amp;quot;true&amp;quot;&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>fieldSelector&lt;/td>
 &lt;td>按 field 篩選（如 node name）&lt;/td>
 &lt;td>&lt;code>spec.nodeName: node-3&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>podPhase&lt;/td>
 &lt;td>只選特定狀態的 pod&lt;/td>
 &lt;td>&lt;code>Running&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>最安全的起點是 namespace + labelSelector + annotation 三層組合：只在 canary namespace、只選帶 &lt;code>chaos-eligible&lt;/code> annotation 的特定服務 pod。annotation-based opt-in 讓團隊明確標記哪些 pod 可以被 chaos 觸及。&lt;/p></description><content:encoded><![CDATA[<h2 id="問題情境">問題情境</h2>
<p>單一 ChaosExperiment（PodChaos pod-kill、NetworkChaos delay）只能驗證一個故障面向。真實的可靠性驗證需要多步驟編排：先注入依賴延遲，觀察 <a href="/blog/backend/knowledge-cards/steady-state/" data-link-title="Steady State" data-link-desc="說明可靠性實驗與事故恢復如何定義系統應維持的可接受狀態">steady state</a> 是否維持，再注入節點失效，最後驗證恢復路徑。Chaos Workflow 提供這個編排能力，把多個 fault injection 與 health check 組成可重播的驗證流程。</p>
<p>experiment scope 的精準控制同樣關鍵。selector 選到 production 全部 pod 的 chaos experiment 會變成真實事故。scope control 的責任是讓 <a href="/blog/backend/knowledge-cards/blast-radius/" data-link-title="Blast Radius" data-link-desc="說明事故影響面如何估算與隔離">blast radius</a> 從最小範圍開始，逐步放大，每一步都有停止條件。</p>
<h2 id="chaos-workflow-設計">Chaos Workflow 設計</h2>
<p>Chaos Workflow 是多個 ChaosExperiment 與 StatusCheck 組成的 DAG（有向無環圖），用 YAML 定義步驟順序與分支條件。</p>
<h3 id="步驟類型">步驟類型</h3>
<table>
  <thead>
      <tr>
          <th>類型</th>
          <th>責任</th>
          <th>適用場景</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Serial</td>
          <td>順序執行，前一步完成才進下一步</td>
          <td>依賴故障 → 觀察 → 節點故障</td>
      </tr>
      <tr>
          <td>Parallel</td>
          <td>平行執行多個注入</td>
          <td>同時打多個依賴驗證交叉影響</td>
      </tr>
      <tr>
          <td>Suspend</td>
          <td>暫停等待人工確認後再繼續</td>
          <td>高風險步驟前的 approval gate</td>
      </tr>
      <tr>
          <td>StatusCheck</td>
          <td>對 HTTP / gRPC / custom script 做 probe</td>
          <td>注入前後的 steady state 驗證</td>
      </tr>
  </tbody>
</table>
<p>StatusCheck 是 workflow 的核心控制面。它在故障注入前後對目標 endpoint 做 health check，pass/fail 決定 workflow 是否繼續。StatusCheck 的 success condition 對應 <a href="/blog/backend/06-reliability/steady-state-definition/" data-link-title="6.22 Steady State Definition" data-link-desc="在 chaos 與 failover 前先定義系統應維持的穩定狀態與可接受退化">6.22 steady state definition</a> 的穩態門檻：success rate、latency、queue lag 都能作為 probe 判準。</p>
<p>典型 workflow 編排：NetworkChaos(delay 200ms) → StatusCheck(api-latency-ok) → PodChaos(pod-kill) → StatusCheck(recovery-within-30s)。第一個 StatusCheck 驗證延遲注入後服務仍可用；第二個 StatusCheck 驗證節點失效後恢復時間可接受。</p>
<h3 id="suspend-的使用時機">Suspend 的使用時機</h3>
<p>Suspend 步驟適合放在 blast radius 擴大之前。例如先在 canary namespace 跑完 chaos + StatusCheck，通過後 Suspend 等待值班工程師確認，再擴大到 production namespace。Suspend 讓自動化 workflow 在關鍵決策點保留人工判斷。</p>
<h2 id="experiment-scope-control">Experiment Scope Control</h2>
<p>Scope control 的責任是讓每個 ChaosExperiment 的影響面可預測、可限制。Chaos Mesh 用 selector + mode 兩層控制。</p>
<h3 id="selector">Selector</h3>
<p>Selector 決定哪些 pod 是實驗目標。</p>
<table>
  <thead>
      <tr>
          <th>Selector 類型</th>
          <th>作用</th>
          <th>範例</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>namespace</td>
          <td>限制在特定 namespace</td>
          <td><code>namespaces: [canary]</code></td>
      </tr>
      <tr>
          <td>labelSelector</td>
          <td>按 label 篩選</td>
          <td><code>app: checkout, tier: backend</code></td>
      </tr>
      <tr>
          <td>annotationSelector</td>
          <td>按 annotation 篩選</td>
          <td><code>chaos-eligible: &quot;true&quot;</code></td>
      </tr>
      <tr>
          <td>fieldSelector</td>
          <td>按 field 篩選（如 node name）</td>
          <td><code>spec.nodeName: node-3</code></td>
      </tr>
      <tr>
          <td>podPhase</td>
          <td>只選特定狀態的 pod</td>
          <td><code>Running</code></td>
      </tr>
  </tbody>
</table>
<p>最安全的起點是 namespace + labelSelector + annotation 三層組合：只在 canary namespace、只選帶 <code>chaos-eligible</code> annotation 的特定服務 pod。annotation-based opt-in 讓團隊明確標記哪些 pod 可以被 chaos 觸及。</p>
<h3 id="mode">Mode</h3>
<p>Mode 決定在 selector 命中的 pod 中選多少個。</p>
<table>
  <thead>
      <tr>
          <th>Mode</th>
          <th>行為</th>
          <th>Blast radius</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>one</td>
          <td>隨機選 1 個</td>
          <td>最小</td>
      </tr>
      <tr>
          <td>fixed</td>
          <td>固定選 N 個</td>
          <td>可控</td>
      </tr>
      <tr>
          <td>fixed-percent</td>
          <td>選命中 pod 的 N%</td>
          <td>比例控制</td>
      </tr>
      <tr>
          <td>random-max-percent</td>
          <td>隨機選最多 N%</td>
          <td>有隨機性</td>
      </tr>
      <tr>
          <td>all</td>
          <td>選全部命中的 pod</td>
          <td>最大</td>
      </tr>
  </tbody>
</table>
<p>從 <code>mode: one</code> 開始驗證基礎假設，確認 StatusCheck 通過後，逐步升級到 <code>fixed-percent: 25</code> → <code>fixed-percent: 50</code>。每一步放大前檢查 steady state 是否仍維持，這個節奏對應 <a href="/blog/backend/06-reliability/experiment-safety-boundary/" data-link-title="6.20 Experiment Safety Boundary" data-link-desc="定義 chaos、load test、DR drill 的 [blast radius](/backend/knowledge-cards/blast-radius/)、停止條件與權限約束">6.20 experiment safety boundary</a> 的漸進放大原則。</p>
<h3 id="duration-與-schedule">Duration 與 Schedule</h3>
<p>duration 控制單次故障注入持續多久，schedule 控制實驗重複頻率。duration 太短可能看不到系統完整的退化與恢復循環；太長則增加實際風險。初始建議：duration 設為 recovery SLA 的 2-3 倍（例如 RTO 30s 則 duration 設 60-90s），讓觀測窗涵蓋完整恢復。</p>
<h2 id="實作範例">實作範例</h2>
<p>一個完整的 Chaos Workflow：先對 checkout 服務注入網路延遲，驗證 API 仍可用，再 kill pod 驗證恢復。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">chaos-mesh.org/v1alpha1</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="w"></span><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">Workflow</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="w"></span><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">checkout-resilience-验证</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="w">  </span><span class="nt">namespace</span><span class="p">:</span><span class="w"> </span><span class="l">chaos-testing</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="w"></span><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="w">  </span><span class="nt">entry</span><span class="p">:</span><span class="w"> </span><span class="l">main</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="w">  </span><span class="nt">templates</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="w">    </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">main</span><span class="w">
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="w">      </span><span class="nt">templateType</span><span class="p">:</span><span class="w"> </span><span class="l">Serial</span><span class="w">
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="w">      </span><span class="nt">children</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="w">        </span>- <span class="l">network-delay</span><span class="w">
</span></span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="w">        </span>- <span class="l">check-api-health</span><span class="w">
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="w">        </span>- <span class="l">pod-kill</span><span class="w">
</span></span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="w">        </span>- <span class="l">check-recovery</span><span class="w">
</span></span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="w">    </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">network-delay</span><span class="w">
</span></span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="w">      </span><span class="nt">templateType</span><span class="p">:</span><span class="w"> </span><span class="l">NetworkChaos</span><span class="w">
</span></span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="w">      </span><span class="nt">networkChaos</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="w">        </span><span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="l">delay</span><span class="w">
</span></span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="w">        </span><span class="nt">delay</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="w">          </span><span class="nt">latency</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;200ms&#34;</span><span class="w">
</span></span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="w">        </span><span class="nt">selector</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">23</span><span class="cl"><span class="w">          </span><span class="nt">namespaces</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="l">canary]</span><span class="w">
</span></span></span><span class="line"><span class="ln">24</span><span class="cl"><span class="w">          </span><span class="nt">labelSelectors</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">25</span><span class="cl"><span class="w">            </span><span class="nt">app</span><span class="p">:</span><span class="w"> </span><span class="l">checkout</span><span class="w">
</span></span></span><span class="line"><span class="ln">26</span><span class="cl"><span class="w">        </span><span class="nt">mode</span><span class="p">:</span><span class="w"> </span><span class="l">one</span><span class="w">
</span></span></span><span class="line"><span class="ln">27</span><span class="cl"><span class="w">        </span><span class="nt">duration</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;60s&#34;</span><span class="w">
</span></span></span><span class="line"><span class="ln">28</span><span class="cl"><span class="w">    </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">check-api-health</span><span class="w">
</span></span></span><span class="line"><span class="ln">29</span><span class="cl"><span class="w">      </span><span class="nt">templateType</span><span class="p">:</span><span class="w"> </span><span class="l">StatusCheck</span><span class="w">
</span></span></span><span class="line"><span class="ln">30</span><span class="cl"><span class="w">      </span><span class="nt">statusCheck</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">31</span><span class="cl"><span class="w">        </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">HTTP</span><span class="w">
</span></span></span><span class="line"><span class="ln">32</span><span class="cl"><span class="w">        </span><span class="nt">http</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">33</span><span class="cl"><span class="w">          </span><span class="nt">url</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;http://checkout.canary/health&#34;</span><span class="w">
</span></span></span><span class="line"><span class="ln">34</span><span class="cl"><span class="w">          </span><span class="nt">criteria</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">35</span><span class="cl"><span class="w">            </span><span class="nt">statusCode</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;200&#34;</span><span class="w">
</span></span></span><span class="line"><span class="ln">36</span><span class="cl"><span class="w">        </span><span class="nt">timeoutSeconds</span><span class="p">:</span><span class="w"> </span><span class="m">30</span><span class="w">
</span></span></span><span class="line"><span class="ln">37</span><span class="cl"><span class="w">        </span><span class="nt">failureThreshold</span><span class="p">:</span><span class="w"> </span><span class="m">3</span><span class="w">
</span></span></span><span class="line"><span class="ln">38</span><span class="cl"><span class="w">    </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">pod-kill</span><span class="w">
</span></span></span><span class="line"><span class="ln">39</span><span class="cl"><span class="w">      </span><span class="nt">templateType</span><span class="p">:</span><span class="w"> </span><span class="l">PodChaos</span><span class="w">
</span></span></span><span class="line"><span class="ln">40</span><span class="cl"><span class="w">      </span><span class="nt">podChaos</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">41</span><span class="cl"><span class="w">        </span><span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="l">pod-kill</span><span class="w">
</span></span></span><span class="line"><span class="ln">42</span><span class="cl"><span class="w">        </span><span class="nt">selector</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">43</span><span class="cl"><span class="w">          </span><span class="nt">namespaces</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="l">canary]</span><span class="w">
</span></span></span><span class="line"><span class="ln">44</span><span class="cl"><span class="w">          </span><span class="nt">labelSelectors</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">45</span><span class="cl"><span class="w">            </span><span class="nt">app</span><span class="p">:</span><span class="w"> </span><span class="l">checkout</span><span class="w">
</span></span></span><span class="line"><span class="ln">46</span><span class="cl"><span class="w">        </span><span class="nt">mode</span><span class="p">:</span><span class="w"> </span><span class="l">one</span><span class="w">
</span></span></span><span class="line"><span class="ln">47</span><span class="cl"><span class="w">    </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">check-recovery</span><span class="w">
</span></span></span><span class="line"><span class="ln">48</span><span class="cl"><span class="w">      </span><span class="nt">templateType</span><span class="p">:</span><span class="w"> </span><span class="l">StatusCheck</span><span class="w">
</span></span></span><span class="line"><span class="ln">49</span><span class="cl"><span class="w">      </span><span class="nt">statusCheck</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">50</span><span class="cl"><span class="w">        </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">HTTP</span><span class="w">
</span></span></span><span class="line"><span class="ln">51</span><span class="cl"><span class="w">        </span><span class="nt">http</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">52</span><span class="cl"><span class="w">          </span><span class="nt">url</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;http://checkout.canary/health&#34;</span><span class="w">
</span></span></span><span class="line"><span class="ln">53</span><span class="cl"><span class="w">          </span><span class="nt">criteria</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">54</span><span class="cl"><span class="w">            </span><span class="nt">statusCode</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;200&#34;</span><span class="w">
</span></span></span><span class="line"><span class="ln">55</span><span class="cl"><span class="w">        </span><span class="nt">timeoutSeconds</span><span class="p">:</span><span class="w"> </span><span class="m">60</span><span class="w">
</span></span></span><span class="line"><span class="ln">56</span><span class="cl"><span class="w">        </span><span class="nt">failureThreshold</span><span class="p">:</span><span class="w"> </span><span class="m">5</span></span></span></code></pre></div><h3 id="gitops-整合">GitOps 整合</h3>
<p>Workflow 定義存在 git repo，用 ArgoCD 或 Flux sync 到 cluster。變更 chaos experiment 走 PR review，跟 code 變更同樣的 approval 流程。這讓 experiment 的修改歷史可追蹤、可審計。</p>
<h3 id="rbac-約束">RBAC 約束</h3>
<p>Chaos Mesh 的 ServiceAccount 權限需要最小化。production namespace 的 chaos experiment 應使用獨立 ServiceAccount，只授予目標 namespace 的 ChaosExperiment create/get/list 權限。避免使用 cluster-admin 角色跑 chaos — 權限過大會讓 selector 誤配時的影響面不可控。</p>
<h2 id="邊界與陷阱">邊界與陷阱</h2>
<p><strong>StatusCheck timeout 太短</strong>：服務在 pod-kill 後需要 readiness probe 通過、load balancer 更新、cache 預熱。若 StatusCheck 的 timeoutSeconds 設太短，服務還在恢復中就被判失敗，產生 false negative。初始 timeout 建議設為預期恢復時間的 2 倍。</p>
<p><strong>Selector 太寬</strong>：namespace-level selector 不加 labelSelector 會命中該 namespace 所有 pod，包含 sidecar、monitoring agent 等非目標 pod。永遠用 labelSelector 或 annotationSelector 收窄範圍。</p>
<p><strong>Privilege 需求</strong>：Chaos Mesh 的 IOChaos 和 StressChaos 需要 container 的 SYS_ADMIN / SYS_PTRACE capability。安全團隊可能限制這些 capability 的使用。若無法取得 privilege，可以先用 PodChaos + NetworkChaos（不需額外 capability）建立 chaos 習慣，再逐步推進。</p>
<p><strong>K8s-only 限制</strong>：Chaos Mesh 只能注入 Kubernetes 上的故障。非 K8s 環境的依賴（外部 SaaS、bare-metal DB、第三方 API）需要用 <a href="/blog/backend/06-reliability/vendors/toxiproxy/" data-link-title="Toxiproxy" data-link-desc="TCP-level fault injection proxy（Shopify 開源）">Toxiproxy</a>（TCP-level fault）或 <a href="/blog/backend/06-reliability/vendors/gremlin/" data-link-title="Gremlin" data-link-desc="商業 chaos engineering 平台、跨平台與 GameDay">Gremlin</a>（跨平台 SaaS）補充。</p>
<h2 id="整合路由">整合路由</h2>
<ul>
<li>上游概念：<a href="/blog/backend/06-reliability/experiment-safety-boundary/" data-link-title="6.20 Experiment Safety Boundary" data-link-desc="定義 chaos、load test、DR drill 的 [blast radius](/backend/knowledge-cards/blast-radius/)、停止條件與權限約束">6.20 Experiment Safety Boundary</a> — selector + mode 對應 blast radius 設計</li>
<li>上游概念：<a href="/blog/backend/06-reliability/steady-state-definition/" data-link-title="6.22 Steady State Definition" data-link-desc="在 chaos 與 failover 前先定義系統應維持的穩定狀態與可接受退化">6.22 Steady State Definition</a> — StatusCheck 對應穩態門檻</li>
<li>下游交接：<a href="/blog/backend/06-reliability/verification-evidence-handoff/" data-link-title="6.23 Verification Evidence Handoff" data-link-desc="把 SLO、load、chaos、DR 與 readiness 結果包成 release / incident 可用證據">6.23 Verification Evidence Handoff</a> — Workflow 結果作為 release gate 證據</li>
<li>平行 vendor：<a href="/blog/backend/06-reliability/vendors/litmuschaos/" data-link-title="LitmusChaos" data-link-desc="Kubernetes chaos engineering 平台（CNCF graduated）">LitmusChaos</a>、<a href="/blog/backend/06-reliability/vendors/gremlin/" data-link-title="Gremlin" data-link-desc="商業 chaos engineering 平台、跨平台與 GameDay">Gremlin</a>、<a href="/blog/backend/06-reliability/vendors/toxiproxy/" data-link-title="Toxiproxy" data-link-desc="TCP-level fault injection proxy（Shopify 開源）">Toxiproxy</a></li>
<li>案例回寫：<a href="/blog/backend/06-reliability/cases/netflix/steady-state-chaos-and-fit/" data-link-title="Netflix：Steady State、Chaos 與 FIT 的驗證路徑" data-link-desc="把故障注入從工具操作升級成可驗證流程：先定義穩態，再設計注入與回復條件。">Netflix N1</a>（steady state hypothesis）、<a href="/blog/backend/06-reliability/cases/netflix/chaos-monkey-business-hours-guardrails/" data-link-title="Netflix：Business-Hours Chaos 與 Guardrails" data-link-desc="Chaos Monkey 為何刻意在 business hours 執行：把即時應變能力納入驗證，並用 guardrails 限制實驗風險。">Netflix N2</a>（business-hours guardrails 對應 scope control）</li>
</ul>
]]></content:encoded></item><item><title>k6：Threshold CI Gate 與 Scenario 設計</title><link>https://tarrragon.github.io/blog/backend/06-reliability/vendors/k6/threshold-ci-gate-and-scenario-design/</link><pubDate>Tue, 23 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/06-reliability/vendors/k6/threshold-ci-gate-and-scenario-design/</guid><description>&lt;h2 id="問題情境">問題情境&lt;/h2>
&lt;p>Load test 跑完會產生大量指標，但 CI pipeline 需要的是 pass/fail 訊號。若沒有 threshold 把指標轉成判讀結論，效能退化只能靠人工看 dashboard 發現，等到看見時通常已經累積數個版本。&lt;/p>
&lt;p>另一面，threshold 的判讀品質取決於 workload model 的真實度。用 &lt;code>--vus 10 --duration 30s&lt;/code> 跑出來的結果跟 production 流量結構差距太大時，threshold 通過也無法證明 production 安全。&lt;/p>
&lt;p>這篇處理兩個問題：怎麼設 threshold 讓 CI gate 可靠，怎麼設 scenario 讓 workload 接近真實。&lt;/p>
&lt;h2 id="threshold-設計">Threshold 設計&lt;/h2>
&lt;p>Threshold 的責任是把 load test 指標轉成 CI 的 pass/fail 訊號。k6 在所有 threshold 都通過時回傳 exit code 0，任一 threshold 失敗就回傳非零 — CI pipeline 直接用 exit code 判斷。&lt;/p>
&lt;h3 id="多指標-threshold">多指標 threshold&lt;/h3>
&lt;p>單一指標 threshold 容易漏風險。latency 正常但 error rate 偏高代表系統在丟請求；throughput 正常但 latency 偏高代表排隊開始堆積。完整的 threshold 至少涵蓋三個面向：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-javascript" data-lang="javascript">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="kr">export&lt;/span> &lt;span class="kr">const&lt;/span> &lt;span class="nx">options&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> &lt;span class="nx">thresholds&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl"> &lt;span class="nx">http_req_duration&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;p(95)&amp;lt;500&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;p(99)&amp;lt;1000&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"> &lt;span class="nx">http_req_failed&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;rate&amp;lt;0.01&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl"> &lt;span class="nx">http_reqs&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;rate&amp;gt;100&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">&lt;span class="p">};&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>latency threshold 用 percentile 而不是 average — average 會被長尾稀釋，p95/p99 更接近使用者感知的最差體驗。&lt;/p>
&lt;h3 id="門檻來源">門檻來源&lt;/h3>
&lt;p>Threshold 的門檻從 production baseline 出發。先從 observability 系統（Grafana / Datadog）取最近 7-30 天的 p95/p99 latency 與 error rate，加上可接受退化幅度（通常 10-20%）作為 threshold。門檻太緊會讓 CI 環境噪音觸發 false positive；門檻太寬會讓真退化滑過去。&lt;/p>
&lt;p>校準節奏：每月或每次重大架構變更後重新對齊 production baseline，避免 threshold 跟真實系統漂移。&lt;/p>
&lt;h3 id="path-level-threshold">Path-level threshold&lt;/h3>
&lt;p>不同 API path 的效能特徵不同。checkout 路徑的 latency 容忍度可能比 listing 路徑低很多。k6 的 group + tag 機制讓 threshold 可以按 path 設定：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-javascript" data-lang="javascript">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="kr">import&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="nx">group&lt;/span> &lt;span class="p">}&lt;/span> &lt;span class="nx">from&lt;/span> &lt;span class="s1">&amp;#39;k6&amp;#39;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="kr">export&lt;/span> &lt;span class="k">default&lt;/span> &lt;span class="kd">function&lt;/span> &lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl"> &lt;span class="nx">group&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;checkout&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kd">function&lt;/span> &lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl"> &lt;span class="c1">// checkout 請求
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">});&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl"> &lt;span class="nx">group&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;listing&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kd">function&lt;/span> &lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl"> &lt;span class="c1">// listing 請求
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">});&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">&lt;span class="kr">export&lt;/span> &lt;span class="kr">const&lt;/span> &lt;span class="nx">options&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl"> &lt;span class="nx">thresholds&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl"> &lt;span class="s1">&amp;#39;http_req_duration{group:::checkout}&amp;#39;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;p(95)&amp;lt;300&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl"> &lt;span class="s1">&amp;#39;http_req_duration{group:::listing}&amp;#39;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;p(95)&amp;lt;800&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl">&lt;span class="p">};&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>path-level threshold 讓 gate 的判讀粒度從「整體效能」細化到「關鍵路徑效能」。&lt;/p>
&lt;h2 id="scenario-設計">Scenario 設計&lt;/h2>
&lt;p>Scenario 的責任是讓壓測的流量結構接近 production。k6 提供五種 scenario executor，選擇取決於要控制什麼變量。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Executor&lt;/th>
 &lt;th>控制變量&lt;/th>
 &lt;th>適用場景&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>constant-vus&lt;/td>
 &lt;td>並發使用者數&lt;/td>
 &lt;td>簡單 smoke test&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>ramping-vus&lt;/td>
 &lt;td>並發使用者數&lt;/td>
 &lt;td>階梯式升壓找 saturation&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>constant-arrival-rate&lt;/td>
 &lt;td>固定 RPS&lt;/td>
 &lt;td>CI regression（穩定輸入）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>ramping-arrival-rate&lt;/td>
 &lt;td>變化 RPS&lt;/td>
 &lt;td>模擬 production peak/off-peak&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>externally-controlled&lt;/td>
 &lt;td>外部 API&lt;/td>
 &lt;td>結合 production 流量 replay&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h3 id="executor-選擇判準">Executor 選擇判準&lt;/h3>
&lt;p>constant-vus 最簡單，但 throughput 會隨 response time 波動 — 伺服器變慢時 RPS 自動下降，掩蓋了真正的壓力。constant-arrival-rate 控制 RPS 穩定，能讓 threshold 的判讀基準一致，但需要設定足夠的 preAllocatedVUs 避免 k6 因為 VU 不足而主動降速。&lt;/p></description><content:encoded><![CDATA[<h2 id="問題情境">問題情境</h2>
<p>Load test 跑完會產生大量指標，但 CI pipeline 需要的是 pass/fail 訊號。若沒有 threshold 把指標轉成判讀結論，效能退化只能靠人工看 dashboard 發現，等到看見時通常已經累積數個版本。</p>
<p>另一面，threshold 的判讀品質取決於 workload model 的真實度。用 <code>--vus 10 --duration 30s</code> 跑出來的結果跟 production 流量結構差距太大時，threshold 通過也無法證明 production 安全。</p>
<p>這篇處理兩個問題：怎麼設 threshold 讓 CI gate 可靠，怎麼設 scenario 讓 workload 接近真實。</p>
<h2 id="threshold-設計">Threshold 設計</h2>
<p>Threshold 的責任是把 load test 指標轉成 CI 的 pass/fail 訊號。k6 在所有 threshold 都通過時回傳 exit code 0，任一 threshold 失敗就回傳非零 — CI pipeline 直接用 exit code 判斷。</p>
<h3 id="多指標-threshold">多指標 threshold</h3>
<p>單一指標 threshold 容易漏風險。latency 正常但 error rate 偏高代表系統在丟請求；throughput 正常但 latency 偏高代表排隊開始堆積。完整的 threshold 至少涵蓋三個面向：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="ln">1</span><span class="cl"><span class="kr">export</span> <span class="kr">const</span> <span class="nx">options</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">  <span class="nx">thresholds</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">    <span class="nx">http_req_duration</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;p(95)&lt;500&#39;</span><span class="p">,</span> <span class="s1">&#39;p(99)&lt;1000&#39;</span><span class="p">],</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">    <span class="nx">http_req_failed</span><span class="o">:</span>   <span class="p">[</span><span class="s1">&#39;rate&lt;0.01&#39;</span><span class="p">],</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">    <span class="nx">http_reqs</span><span class="o">:</span>         <span class="p">[</span><span class="s1">&#39;rate&gt;100&#39;</span><span class="p">],</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="p">};</span></span></span></code></pre></div><p>latency threshold 用 percentile 而不是 average — average 會被長尾稀釋，p95/p99 更接近使用者感知的最差體驗。</p>
<h3 id="門檻來源">門檻來源</h3>
<p>Threshold 的門檻從 production baseline 出發。先從 observability 系統（Grafana / Datadog）取最近 7-30 天的 p95/p99 latency 與 error rate，加上可接受退化幅度（通常 10-20%）作為 threshold。門檻太緊會讓 CI 環境噪音觸發 false positive；門檻太寬會讓真退化滑過去。</p>
<p>校準節奏：每月或每次重大架構變更後重新對齊 production baseline，避免 threshold 跟真實系統漂移。</p>
<h3 id="path-level-threshold">Path-level threshold</h3>
<p>不同 API path 的效能特徵不同。checkout 路徑的 latency 容忍度可能比 listing 路徑低很多。k6 的 group + tag 機制讓 threshold 可以按 path 設定：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">group</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;k6&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="kr">export</span> <span class="k">default</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">  <span class="nx">group</span><span class="p">(</span><span class="s1">&#39;checkout&#39;</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="c1">// checkout 請求
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="c1"></span>  <span class="p">});</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">  <span class="nx">group</span><span class="p">(</span><span class="s1">&#39;listing&#39;</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="c1">// listing 請求
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="c1"></span>  <span class="p">});</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="kr">export</span> <span class="kr">const</span> <span class="nx">options</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">  <span class="nx">thresholds</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">    <span class="s1">&#39;http_req_duration{group:::checkout}&#39;</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;p(95)&lt;300&#39;</span><span class="p">],</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="s1">&#39;http_req_duration{group:::listing}&#39;</span><span class="o">:</span>  <span class="p">[</span><span class="s1">&#39;p(95)&lt;800&#39;</span><span class="p">],</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="p">};</span></span></span></code></pre></div><p>path-level threshold 讓 gate 的判讀粒度從「整體效能」細化到「關鍵路徑效能」。</p>
<h2 id="scenario-設計">Scenario 設計</h2>
<p>Scenario 的責任是讓壓測的流量結構接近 production。k6 提供五種 scenario executor，選擇取決於要控制什麼變量。</p>
<table>
  <thead>
      <tr>
          <th>Executor</th>
          <th>控制變量</th>
          <th>適用場景</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>constant-vus</td>
          <td>並發使用者數</td>
          <td>簡單 smoke test</td>
      </tr>
      <tr>
          <td>ramping-vus</td>
          <td>並發使用者數</td>
          <td>階梯式升壓找 saturation</td>
      </tr>
      <tr>
          <td>constant-arrival-rate</td>
          <td>固定 RPS</td>
          <td>CI regression（穩定輸入）</td>
      </tr>
      <tr>
          <td>ramping-arrival-rate</td>
          <td>變化 RPS</td>
          <td>模擬 production peak/off-peak</td>
      </tr>
      <tr>
          <td>externally-controlled</td>
          <td>外部 API</td>
          <td>結合 production 流量 replay</td>
      </tr>
  </tbody>
</table>
<h3 id="executor-選擇判準">Executor 選擇判準</h3>
<p>constant-vus 最簡單，但 throughput 會隨 response time 波動 — 伺服器變慢時 RPS 自動下降，掩蓋了真正的壓力。constant-arrival-rate 控制 RPS 穩定，能讓 threshold 的判讀基準一致，但需要設定足夠的 preAllocatedVUs 避免 k6 因為 VU 不足而主動降速。</p>
<p>CI regression 測試建議用 constant-arrival-rate：輸入固定、輸出可比較、版本間的差異才有意義。</p>
<h3 id="production-traffic-shape-對齊">Production traffic shape 對齊</h3>
<p>用 ramping-arrival-rate 模擬 production 的流量形狀：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kr">export</span> <span class="kr">const</span> <span class="nx">options</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">  <span class="nx">scenarios</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">    <span class="nx">peak_simulation</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">      <span class="nx">executor</span><span class="o">:</span> <span class="s1">&#39;ramping-arrival-rate&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">      <span class="nx">startRate</span><span class="o">:</span> <span class="mi">50</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">      <span class="nx">stages</span><span class="o">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">        <span class="p">{</span> <span class="nx">target</span><span class="o">:</span> <span class="mi">200</span><span class="p">,</span> <span class="nx">duration</span><span class="o">:</span> <span class="s1">&#39;2m&#39;</span> <span class="p">},</span>  <span class="c1">// ramp up
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="c1"></span>        <span class="p">{</span> <span class="nx">target</span><span class="o">:</span> <span class="mi">200</span><span class="p">,</span> <span class="nx">duration</span><span class="o">:</span> <span class="s1">&#39;5m&#39;</span> <span class="p">},</span>  <span class="c1">// sustain peak
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="c1"></span>        <span class="p">{</span> <span class="nx">target</span><span class="o">:</span> <span class="mi">50</span><span class="p">,</span>  <span class="nx">duration</span><span class="o">:</span> <span class="s1">&#39;1m&#39;</span> <span class="p">},</span>  <span class="c1">// ramp down
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="c1"></span>      <span class="p">],</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">      <span class="nx">preAllocatedVUs</span><span class="o">:</span> <span class="mi">300</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="p">};</span></span></span></code></pre></div><p>流量形狀的參數（startRate / target / duration）從 production access log 的 peak 時段推算。Shopify 的 BFCM 準備流程把 game day 的 load test scenario 跟實際峰值形狀對齊 — 短時間爆量加高寫入比例需要特別設計 scenario 來覆蓋。</p>
<h3 id="cohort-模擬">Cohort 模擬</h3>
<p>Production 流量不是單一類型。用多 scenario 並行模擬不同 cohort：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kr">export</span> <span class="kr">const</span> <span class="nx">options</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">  <span class="nx">scenarios</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">    <span class="nx">read_traffic</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">      <span class="nx">executor</span><span class="o">:</span> <span class="s1">&#39;constant-arrival-rate&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">      <span class="nx">rate</span><span class="o">:</span> <span class="mi">150</span><span class="p">,</span> <span class="nx">exec</span><span class="o">:</span> <span class="s1">&#39;readFlow&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">      <span class="nx">preAllocatedVUs</span><span class="o">:</span> <span class="mi">200</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">      <span class="nx">duration</span><span class="o">:</span> <span class="s1">&#39;5m&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="nx">write_traffic</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">      <span class="nx">executor</span><span class="o">:</span> <span class="s1">&#39;constant-arrival-rate&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">      <span class="nx">rate</span><span class="o">:</span> <span class="mi">30</span><span class="p">,</span> <span class="nx">exec</span><span class="o">:</span> <span class="s1">&#39;writeFlow&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">      <span class="nx">preAllocatedVUs</span><span class="o">:</span> <span class="mi">50</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">      <span class="nx">duration</span><span class="o">:</span> <span class="s1">&#39;5m&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">
</span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="kr">export</span> <span class="kd">function</span> <span class="nx">readFlow</span><span class="p">()</span> <span class="p">{</span> <span class="cm">/* GET 請求 */</span> <span class="p">}</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="kr">export</span> <span class="kd">function</span> <span class="nx">writeFlow</span><span class="p">()</span> <span class="p">{</span> <span class="cm">/* POST 請求 */</span> <span class="p">}</span></span></span></code></pre></div><p>讀寫比例從 production 的 access log 或 APM 資料推算。比例偏差會讓瓶頸位置失真 — 讀為主的模型抓不到寫入引起的 lock contention。</p>
<h3 id="資料驅動">資料驅動</h3>
<p>測試資料用 SharedArray 載入，避免每個 VU 各自載入造成記憶體浪費：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="ln">1</span><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">SharedArray</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;k6/data&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="kr">const</span> <span class="nx">users</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">SharedArray</span><span class="p">(</span><span class="s1">&#39;users&#39;</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">  <span class="k">return</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">open</span><span class="p">(</span><span class="s1">&#39;./users.json&#39;</span><span class="p">));</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="p">});</span></span></span></code></pre></div><p>資料來源可以是 production sample（脫敏後）或 synthetic generation。資料分佈需要接近 production — ID 範圍、key 分佈、payload 大小都會影響 query plan 與 cache 行為。</p>
<h2 id="ci-整合實務">CI 整合實務</h2>
<h3 id="fast-path每次-push">Fast path（每次 push）</h3>
<p>固定 scenario + 短 duration（30s-2min），用 constant-arrival-rate 做 regression 偵測。threshold 設在 production baseline + 10%。這一層的目的是快速攔住明顯退化，不需要模擬完整峰值。</p>
<h3 id="slow-pathmerge-gate">Slow path（merge gate）</h3>
<p>完整 scenario + 較長 duration（5-15min），包含多 cohort 與 ramping 模擬。threshold 涵蓋 path-level 指標。這一層的目的是深層驗證變更在接近真實壓力下的行為。</p>
<h3 id="結果留存">結果留存</h3>
<p>k6 結果預設輸出到 stdout。CI 整合時用 <code>--out</code> flag 把結果送到時序資料庫（InfluxDB / Prometheus Remote Write / Grafana Cloud k6），讓歷史趨勢可查詢。趨勢比較能偵測 threshold 內但持續惡化的 slow drift。</p>
<p>LinkedIn 的自動化壓測實踐把 load test 結果跟容量預測接在一起 — saturation point 隨時間的變化趨勢直接驅動擴容決策。</p>
<h2 id="邊界與陷阱">邊界與陷阱</h2>
<p><strong>Threshold variance</strong>：CI runner 的硬體差異（shared runner 的鄰居效應、network jitter、GC pause）會讓同一份 code 在不同 run 產生不同結果。控制方式：dedicated runner 消除鄰居效應、warmup iteration 丟棄前幾輪結果、多次 run 取中位數。若 variance 超過 threshold 的退化幅度，gate 判讀就不可信。</p>
<p><strong>門檻過寬或過緊</strong>：threshold 永遠通過代表 gate 形同虛設；threshold 頻繁 false positive 會讓團隊忽略 CI 結果。兩者都會讓 gate 失去判讀價值。校準的判準是：過去 30 天的 threshold 結果中，真正需要關注的退化是否都被攔住，同時 false positive 率低於 5%。</p>
<p><strong>Scenario 跟 production drift</strong>：production 的流量結構會隨產品演進改變。定期（每月或每次重大功能上線）用 access log 校準 scenario 的 RPS、cohort 比例與資料分佈，避免模型越跑越偏。</p>
<h2 id="整合路由">整合路由</h2>
<ul>
<li>上游概念：<a href="/blog/backend/06-reliability/load-testing/" data-link-title="6.2 load test" data-link-desc="把 production 流量結構轉成可重播壓力情境，定位 saturation 轉折與容量邊界">6.2 load testing</a> 的 workload model 設計</li>
<li>下游能力：<a href="/blog/backend/06-reliability/performance-regression-gate/" data-link-title="6.13 Performance Regression Gate" data-link-desc="把效能 baseline 從一次性壓測變成持續對齊的 release gate，涵蓋 baseline 設定、判讀方法、variance 控制與退化定位">6.13 performance regression gate</a> 的 baseline 管理與退化定位</li>
<li>平行 vendor：<a href="/blog/backend/06-reliability/vendors/gatling/" data-link-title="Gatling" data-link-desc="JVM-based load test、Scala / Java / Kotlin DSL、強型別 scenario、HAR-driven recording">Gatling</a>、<a href="/blog/backend/06-reliability/vendors/locust/" data-link-title="Locust" data-link-desc="Python-based load test、distributed、易擴展">Locust</a>、<a href="/blog/backend/06-reliability/vendors/jmeter/" data-link-title="Apache JMeter" data-link-desc="老牌 load test 工具、GUI &#43; plugins">JMeter</a></li>
<li>案例回寫：<a href="/blog/backend/06-reliability/cases/shopify/bfcm-capacity-and-game-day/" data-link-title="Shopify：BFCM 容量治理與 Game Day 驗證節奏" data-link-desc="把季節性流量峰值轉成年度可靠性流程，透過容量模型、演練與隔離策略提前吸收風險。">Shopify BFCM 容量治理</a>（game day load test 對齊峰值形狀）、<a href="/blog/backend/06-reliability/cases/linkedin/automated-load-testing-and-capacity-forecasting/" data-link-title="LinkedIn：Automated Load Testing 與 Capacity Forecasting" data-link-desc="持續壓測驅動容量預測：用自動化回饋取代一次性壓測的容量規劃。">LinkedIn Automated Load Testing</a>（持續壓測驅動容量預測）</li>
</ul>
]]></content:encoded></item><item><title>Sloth：SLO YAML 與 Multi-burn-rate Alert 生成</title><link>https://tarrragon.github.io/blog/backend/06-reliability/vendors/sloth/slo-yaml-and-multi-burn-rate-alert-generation/</link><pubDate>Tue, 23 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/06-reliability/vendors/sloth/slo-yaml-and-multi-burn-rate-alert-generation/</guid><description>&lt;h2 id="問題情境">問題情境&lt;/h2>
&lt;p>SLO 從定義到 Prometheus 落地需要多層 rule。一個 SLO 對應 4 組 time window 的 recording rule（計算各窗口的 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/burn-rate/" data-link-title="Burn Rate" data-link-desc="說明 error budget 消耗速度如何支援告警與事故分級">burn rate&lt;/a>），再對應 fast burn 和 slow burn 兩組 alerting rule。手動維護這些 rule 容易出錯：window 參數不一致、新增 SLO 忘記補 alert、修改 SLI expression 只改了部分 rule。&lt;/p>
&lt;p>Sloth 的責任是把這個過程自動化。輸入一份 SLO YAML，產出一組完整的 Prometheus recording + alerting rules，讓 SLO 維護回到宣告式：改 YAML、重新生成、載入 Prometheus。&lt;/p>
&lt;h2 id="slo-yaml-設計">SLO YAML 設計&lt;/h2>
&lt;p>Sloth YAML 的核心結構是 &lt;code>version&lt;/code> → &lt;code>service&lt;/code> → &lt;code>slos[]&lt;/code>。每個 SLO 定義三件事：目標數字（objective）、量測方式（SLI）、告警等級（alerting）。&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="nt">version&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">prometheus/v1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">service&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">checkout-api&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">slos&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">availability&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">objective&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">99.9&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">description&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;checkout API 的請求成功率&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">sli&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">events&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">error_query&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">sum(rate(http_requests_total{service=&amp;#34;checkout&amp;#34;,code=~&amp;#34;5..&amp;#34;}[{{.window}}]))&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">total_query&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">sum(rate(http_requests_total{service=&amp;#34;checkout&amp;#34;}[{{.window}}]))&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">alerting&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">CheckoutAvailability&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">page_alert&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">labels&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">severity&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">critical&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">ticket_alert&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">labels&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">severity&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">warning&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>SLI 有兩種類型。events-based SLI 用 error/total ratio 定義，Sloth 自動把 &lt;code>{{.window}}&lt;/code> 參數代入各 recording rule 的 range vector。raw SLI 直接寫 PromQL expression 算 error ratio，適合非 request-based 的 SLO（如 data freshness、replication lag）。&lt;/p>
&lt;p>raw SLI 範例 — data freshness：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">data-freshness&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">objective&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">99.5&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">sli&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">raw&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">error_ratio_query&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">|&lt;/span>&lt;span class="sd">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">&lt;span class="sd"> 1 - clamp_max(
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">&lt;span class="sd"> replication_lag_seconds{service=&amp;#34;checkout-db&amp;#34;} / 60,
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl">&lt;span class="sd"> 1
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">9&lt;/span>&lt;span class="cl">&lt;span class="sd"> )&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>objective 數字的來源是 &lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/slo-error-budget/" data-link-title="6.6 SLO 與 Error Budget 政策" data-link-desc="把可靠性目標轉成可驗證量測與凍結條件">6.6 SLO 政策&lt;/a> — 先從使用者旅程定義服務承諾，再把承諾轉成 objective。Sloth 不負責決定 objective 該是多少，只負責把 objective 轉成可執行的 Prometheus rule。&lt;/p>
&lt;p>alerting 分 page（嚴重，觸發即時通知）和 ticket（一般，產生工單）。兩者的 burn rate 門檻不同：page 用 fast burn window，ticket 用 slow burn window。label 設計跟 Alertmanager routing 對齊 — &lt;code>severity: critical&lt;/code> 走 PagerDuty / Slack alert channel，&lt;code>severity: warning&lt;/code> 走 ticket system（Jira / Linear）。&lt;/p></description><content:encoded><![CDATA[<h2 id="問題情境">問題情境</h2>
<p>SLO 從定義到 Prometheus 落地需要多層 rule。一個 SLO 對應 4 組 time window 的 recording rule（計算各窗口的 <a href="/blog/backend/knowledge-cards/burn-rate/" data-link-title="Burn Rate" data-link-desc="說明 error budget 消耗速度如何支援告警與事故分級">burn rate</a>），再對應 fast burn 和 slow burn 兩組 alerting rule。手動維護這些 rule 容易出錯：window 參數不一致、新增 SLO 忘記補 alert、修改 SLI expression 只改了部分 rule。</p>
<p>Sloth 的責任是把這個過程自動化。輸入一份 SLO YAML，產出一組完整的 Prometheus recording + alerting rules，讓 SLO 維護回到宣告式：改 YAML、重新生成、載入 Prometheus。</p>
<h2 id="slo-yaml-設計">SLO YAML 設計</h2>
<p>Sloth YAML 的核心結構是 <code>version</code> → <code>service</code> → <code>slos[]</code>。每個 SLO 定義三件事：目標數字（objective）、量測方式（SLI）、告警等級（alerting）。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="nt">version</span><span class="p">:</span><span class="w"> </span><span class="l">prometheus/v1</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="w"></span><span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">checkout-api</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="w"></span><span class="nt">slos</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="w">  </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">availability</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="w">    </span><span class="nt">objective</span><span class="p">:</span><span class="w"> </span><span class="m">99.9</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="w">    </span><span class="nt">description</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;checkout API 的請求成功率&#34;</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="w">    </span><span class="nt">sli</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="w">      </span><span class="nt">events</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="w">        </span><span class="nt">error_query</span><span class="p">:</span><span class="w"> </span><span class="l">sum(rate(http_requests_total{service=&#34;checkout&#34;,code=~&#34;5..&#34;}[{{.window}}]))</span><span class="w">
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="w">        </span><span class="nt">total_query</span><span class="p">:</span><span class="w"> </span><span class="l">sum(rate(http_requests_total{service=&#34;checkout&#34;}[{{.window}}]))</span><span class="w">
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="w">    </span><span class="nt">alerting</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="w">      </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">CheckoutAvailability</span><span class="w">
</span></span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="w">      </span><span class="nt">page_alert</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="w">        </span><span class="nt">labels</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="w">          </span><span class="nt">severity</span><span class="p">:</span><span class="w"> </span><span class="l">critical</span><span class="w">
</span></span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="w">      </span><span class="nt">ticket_alert</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="w">        </span><span class="nt">labels</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="w">          </span><span class="nt">severity</span><span class="p">:</span><span class="w"> </span><span class="l">warning</span></span></span></code></pre></div><p>SLI 有兩種類型。events-based SLI 用 error/total ratio 定義，Sloth 自動把 <code>{{.window}}</code> 參數代入各 recording rule 的 range vector。raw SLI 直接寫 PromQL expression 算 error ratio，適合非 request-based 的 SLO（如 data freshness、replication lag）。</p>
<p>raw SLI 範例 — data freshness：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="ln">1</span><span class="cl"><span class="w">  </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">data-freshness</span><span class="w">
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="w">    </span><span class="nt">objective</span><span class="p">:</span><span class="w"> </span><span class="m">99.5</span><span class="w">
</span></span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="w">    </span><span class="nt">sli</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="w">      </span><span class="nt">raw</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="w">        </span><span class="nt">error_ratio_query</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd">
</span></span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="sd">          1 - clamp_max(
</span></span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="sd">            replication_lag_seconds{service=&#34;checkout-db&#34;} / 60,
</span></span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="sd">            1
</span></span></span><span class="line"><span class="ln">9</span><span class="cl"><span class="sd">          )</span></span></span></code></pre></div><p>objective 數字的來源是 <a href="/blog/backend/06-reliability/slo-error-budget/" data-link-title="6.6 SLO 與 Error Budget 政策" data-link-desc="把可靠性目標轉成可驗證量測與凍結條件">6.6 SLO 政策</a> — 先從使用者旅程定義服務承諾，再把承諾轉成 objective。Sloth 不負責決定 objective 該是多少，只負責把 objective 轉成可執行的 Prometheus rule。</p>
<p>alerting 分 page（嚴重，觸發即時通知）和 ticket（一般，產生工單）。兩者的 burn rate 門檻不同：page 用 fast burn window，ticket 用 slow burn window。label 設計跟 Alertmanager routing 對齊 — <code>severity: critical</code> 走 PagerDuty / Slack alert channel，<code>severity: warning</code> 走 ticket system（Jira / Linear）。</p>
<h2 id="multi-window-multi-burn-rate-alert">Multi-window Multi-burn-rate Alert</h2>
<p>Sloth 預設產生 Google SRE 推薦的 4-window alert 結構。每個 SLO 生成以下 recording rules 和 alerting rules。</p>
<table>
  <thead>
      <tr>
          <th>Window 組合</th>
          <th>責任</th>
          <th>觸發行動</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>5m / 1h</td>
          <td>Fast burn 偵測</td>
          <td>短時間大量消耗 → page 通知</td>
      </tr>
      <tr>
          <td>30m / 6h</td>
          <td>Moderate burn 偵測</td>
          <td>中速消耗 → page 或 ticket</td>
      </tr>
      <tr>
          <td>2h / 1d</td>
          <td>Slow burn 偵測</td>
          <td>緩慢消耗 → ticket</td>
      </tr>
      <tr>
          <td>6h / 3d</td>
          <td>Very slow 偵測</td>
          <td>長期趨勢退化 → ticket 或 review</td>
      </tr>
  </tbody>
</table>
<p>fast burn alert 回答「error budget 是否正在被快速吃掉」。當 5 分鐘窗口的 burn rate 超過 14.4 倍（代表如果持續下去，1 小時會消耗完整個月的 budget），觸發 page。這個門檻的設計邏輯是：越短的窗口允許越高的 burn rate 容忍，因為短窗口的 false positive 率較高，需要搭配較長窗口的確認。</p>
<p>slow burn alert 回答「error budget 是否在不被注意的情況下被緩慢消耗」。6 小時窗口的 burn rate 超過 1 倍（代表月底會剛好用完 budget），觸發 ticket。slow burn 常被忽略，但它是高變更頻率服務最常見的可靠性退化模式 — 每次小回歸都不夠大到觸發 fast burn，累積到月底才發現 budget 已透支。</p>
<p>burn rate alert 跟 <a href="/blog/backend/06-reliability/slo-error-budget/" data-link-title="6.6 SLO 與 Error Budget 政策" data-link-desc="把可靠性目標轉成可驗證量測與凍結條件">6.6 SLO error budget 政策</a> 直接對應：fast burn → 凍結變更；slow burn → 提高驗證門檻；budget 健康 → 正常發版。</p>
<p>Sloth 產出的 recording rule 範例（5m window）：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="ln">1</span><span class="cl">- <span class="nt">record</span><span class="p">:</span><span class="w"> </span><span class="l">slo:sli_error:ratio_rate5m</span><span class="w">
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="w">  </span><span class="nt">expr</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd">
</span></span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="sd">    sum(rate(http_requests_total{service=&#34;checkout&#34;,code=~&#34;5..&#34;}[5m]))
</span></span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="sd">    /
</span></span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="sd">    sum(rate(http_requests_total{service=&#34;checkout&#34;}[5m]))</span><span class="w">
</span></span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="w">  </span><span class="nt">labels</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="w">    </span><span class="nt">sloth_service</span><span class="p">:</span><span class="w"> </span><span class="l">checkout-api</span><span class="w">
</span></span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="w">    </span><span class="nt">sloth_slo</span><span class="p">:</span><span class="w"> </span><span class="l">availability</span></span></span></code></pre></div><p>對應的 alerting rule（fast burn）：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="ln">1</span><span class="cl">- <span class="nt">alert</span><span class="p">:</span><span class="w"> </span><span class="l">CheckoutAvailabilityFastBurn</span><span class="w">
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="w">  </span><span class="nt">expr</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd">
</span></span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="sd">    slo:sli_error:ratio_rate5m{sloth_slo=&#34;availability&#34;} &gt; (14.4 * 0.001)
</span></span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="sd">    and
</span></span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="sd">    slo:sli_error:ratio_rate1h{sloth_slo=&#34;availability&#34;} &gt; (14.4 * 0.001)</span><span class="w">
</span></span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="w">  </span><span class="nt">labels</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="w">    </span><span class="nt">severity</span><span class="p">:</span><span class="w"> </span><span class="l">critical</span></span></span></code></pre></div><p>fast burn alert 要求 5m 和 1h 兩個窗口同時超過門檻，短窗口防止 spike false positive、長窗口確認趨勢持續。</p>
<h2 id="實作流程">實作流程</h2>
<h3 id="cli-生成">CLI 生成</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">sloth generate -i slo.yaml -o rules.yaml
</span></span><span class="line"><span class="ln">2</span><span class="cl">sloth validate -i slo.yaml</span></span></code></pre></div><p><code>generate</code> 產出的 <code>rules.yaml</code> 包含所有 recording rules 和 alerting rules，直接放入 Prometheus 的 <code>rule_files</code> 載入。<code>validate</code> 在 CI 中先行檢查 YAML 格式與 SLI expression 語法。</p>
<h3 id="k8s-operator-mode">K8s Operator mode</h3>
<p>Sloth 提供 K8s Operator，用 <code>PrometheusServiceLevel</code> CRD 定義 SLO。Operator 自動 reconcile，把 CRD 轉成 Prometheus rules 並同步到 Prometheus Operator 的 <code>PrometheusRule</code> 資源。</p>
<p>Operator mode 適合 K8s-native 環境：SLO 定義跟 service deployment 放在同一個 GitOps repo，變更 SLO 跟變更服務走同一套 PR review + CI 流程。</p>
<h3 id="ci--gitops-整合">CI / GitOps 整合</h3>
<p>在 CI pipeline 中跑 <code>sloth validate</code> 驗證 YAML，再跑 <code>sloth generate</code> 產出 rules，commit 進 GitOps repo。Prometheus 透過 config reload 或 Operator reconcile 載入新 rules。這條流程讓 SLO 變更有版本歷史、有 review、有 rollback 能力。</p>
<h2 id="邊界與陷阱">邊界與陷阱</h2>
<p>Sloth 只支援 Prometheus 作為後端。若觀測平台是 Datadog、New Relic、Honeycomb 或 Grafana Cloud，需要各平台自己的 SLO 功能或 <a href="/blog/backend/06-reliability/vendors/nobl9/" data-link-title="Nobl9" data-link-desc="SLO platform、跨 data source、企業 SLO 治理">Nobl9</a> 的 multi-source 整合。</p>
<p>SLI expression 錯誤是最常見的問題。分母為零（service 沒有流量）會產生 NaN，cascading 到所有 recording rule。label 不匹配（<code>service</code> label 拼錯）會產生空 series，alert 永遠不觸發。<code>sloth validate</code> 檢查語法但不檢查 Prometheus 中是否真的有對應 series — 上線後需要用 Prometheus query 確認 recording rule 產出非空結果。</p>
<p>SLO 數量增長會累積 recording rule 成本。每個 SLO 產生約 30 條 recording rule（4 windows × 多組 aggregation）。100 個 SLO 產生 3000 條 rule，Prometheus 的 rule evaluation 會消耗明顯的 CPU 和記憶體。定期監控 <code>prometheus_rule_evaluation_duration_seconds</code> 和 <code>prometheus_rule_group_rules</code>，在 rule 數量影響 evaluation latency 前調整。</p>
<p>升級路徑：Sloth YAML 跟 OpenSLO spec 部分相容。從 Sloth 移到 Nobl9 時，SLO 定義的語意可以保留，SLI expression 需要改寫成 Nobl9 的 data source query。這條路徑適合從 Prometheus-only 環境逐步擴展到 multi-source SLO governance。</p>
<h2 id="整合路由">整合路由</h2>
<ul>
<li>上游：<a href="/blog/backend/06-reliability/slo-error-budget/" data-link-title="6.6 SLO 與 Error Budget 政策" data-link-desc="把可靠性目標轉成可驗證量測與凍結條件">6.6 SLO 與 Error Budget 政策</a> — SLO 定義與 objective 來源</li>
<li>下游：<a href="/blog/backend/06-reliability/release-gate/" data-link-title="6.8 Release Gate 與變更節奏" data-link-desc="把驗證、migration、相容性納入放行判準">6.8 Release Gate</a> — burn rate alert 觸發凍結</li>
<li>平行：<a href="/blog/backend/06-reliability/vendors/nobl9/" data-link-title="Nobl9" data-link-desc="SLO platform、跨 data source、企業 SLO 治理">Nobl9</a>（SaaS multi-source）、Pyrra（K8s-native + UI）</li>
<li>案例回寫：<a href="/blog/backend/06-reliability/cases/google/error-budget-policy-and-release-gating/" data-link-title="Google：Error Budget 政策如何決定發布節奏" data-link-desc="把 SLO 消耗量轉成 release gate，讓可靠性與交付速度共用同一套決策語言。">Google G1</a>（error budget policy 原典）、<a href="/blog/backend/06-reliability/cases/honeycomb/burn-rate-driven-reliability-operations/" data-link-title="Honeycomb：以 Burn Rate 驅動的可靠性操作" data-link-desc="把 SLO burn rate 直接連到值班決策與改善優先序，降低高噪音告警造成的判讀失真。">Honeycomb HC1</a>（burn rate 驅動可靠性操作）</li>
</ul>
]]></content:encoded></item><item><title>Cloudflare WAF</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/cloudflare-waf/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/cloudflare-waf/</guid><description>&lt;p>Cloudflare WAF 是 &lt;em>edge-deployed&lt;/em> 的 Web Application Firewall、跑在 Cloudflare 全球 anycast 網路上、攔截 HTTP/HTTPS 攻擊在抵達 origin 之前。它跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-waf/" data-link-title="AWS WAF" data-link-desc="AWS-internal WAF、跟 ALB / CloudFront / API Gateway 直接整合、Web ACL &amp;#43; Managed Rule Group &amp;#43; Rate-based Rule、Shield Standard 內含">AWS WAF&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/fastly-ngwaf/" data-link-title="Fastly Next-Gen WAF" data-link-desc="Behavioral / 語意分析 WAF（前 Signal Sciences）、低 false positive、Edge / Agent / Cloud 三種部署模型、API &amp;#43; ATO &amp;#43; Bot 一體">Fastly Next-Gen WAF&lt;/a> 的核心差異是 &lt;em>跟其他 Cloudflare 產品深度整合&lt;/em>：DDoS protection、Bot Management、Rate Limiting、Page Shield（JS supply chain）、API Shield（schema validation）、Zero Trust、Workers 邊緣計算共用同一個控制面。客戶選 Cloudflare WAF 通常不只是要 WAF、是要 &lt;em>整套 edge security suite&lt;/em>。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Cloudflare WAF 的核心定位是 &lt;em>把攻擊擋在 origin 之前的一站式 edge security&lt;/em>。流量打到 Cloudflare anycast IP、經過 WAF / DDoS / Bot / Rate Limit / Page Shield 多層處理、再 proxy 到 origin。這跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-waf/" data-link-title="AWS WAF" data-link-desc="AWS-internal WAF、跟 ALB / CloudFront / API Gateway 直接整合、Web ACL &amp;#43; Managed Rule Group &amp;#43; Rate-based Rule、Shield Standard 內含">AWS WAF&lt;/a> 跑在 AWS 內部 ALB / CloudFront / API Gateway 前是不同部署模型 — AWS WAF 流量 &lt;em>已經進到 AWS&lt;/em>、Cloudflare WAF 流量 &lt;em>還沒到 origin&lt;/em>。對 origin 是 &lt;em>任意雲 / on-prem&lt;/em> 的客戶、Cloudflare 是天然選項；對 AWS-only 客戶、AWS WAF 整合更深但 edge 範圍小。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/fastly-ngwaf/" data-link-title="Fastly Next-Gen WAF" data-link-desc="Behavioral / 語意分析 WAF（前 Signal Sciences）、低 false positive、Edge / Agent / Cloud 三種部署模型、API &amp;#43; ATO &amp;#43; Bot 一體">Fastly Next-Gen WAF&lt;/a>（前 Signal Sciences）相比、Cloudflare 走 &lt;em>signature + managed rule + ML&lt;/em> 混合、Fastly NG-WAF 走 &lt;em>語意分析 + behavioral detection&lt;/em>（不靠 regex signature）。Cloudflare managed rule 覆蓋廣但 false positive 較常見、需要 &lt;em>sensitivity tuning&lt;/em>；Fastly NG-WAF 預設較低 FP 但需要 &lt;em>自己定義業務 anomaly&lt;/em>。&lt;/p></description><content:encoded><![CDATA[<p>Cloudflare WAF 是 <em>edge-deployed</em> 的 Web Application Firewall、跑在 Cloudflare 全球 anycast 網路上、攔截 HTTP/HTTPS 攻擊在抵達 origin 之前。它跟 <a href="/blog/backend/07-security-data-protection/vendors/aws-waf/" data-link-title="AWS WAF" data-link-desc="AWS-internal WAF、跟 ALB / CloudFront / API Gateway 直接整合、Web ACL &#43; Managed Rule Group &#43; Rate-based Rule、Shield Standard 內含">AWS WAF</a> / <a href="/blog/backend/07-security-data-protection/vendors/fastly-ngwaf/" data-link-title="Fastly Next-Gen WAF" data-link-desc="Behavioral / 語意分析 WAF（前 Signal Sciences）、低 false positive、Edge / Agent / Cloud 三種部署模型、API &#43; ATO &#43; Bot 一體">Fastly Next-Gen WAF</a> 的核心差異是 <em>跟其他 Cloudflare 產品深度整合</em>：DDoS protection、Bot Management、Rate Limiting、Page Shield（JS supply chain）、API Shield（schema validation）、Zero Trust、Workers 邊緣計算共用同一個控制面。客戶選 Cloudflare WAF 通常不只是要 WAF、是要 <em>整套 edge security suite</em>。</p>
<h2 id="服務定位">服務定位</h2>
<p>Cloudflare WAF 的核心定位是 <em>把攻擊擋在 origin 之前的一站式 edge security</em>。流量打到 Cloudflare anycast IP、經過 WAF / DDoS / Bot / Rate Limit / Page Shield 多層處理、再 proxy 到 origin。這跟 <a href="/blog/backend/07-security-data-protection/vendors/aws-waf/" data-link-title="AWS WAF" data-link-desc="AWS-internal WAF、跟 ALB / CloudFront / API Gateway 直接整合、Web ACL &#43; Managed Rule Group &#43; Rate-based Rule、Shield Standard 內含">AWS WAF</a> 跑在 AWS 內部 ALB / CloudFront / API Gateway 前是不同部署模型 — AWS WAF 流量 <em>已經進到 AWS</em>、Cloudflare WAF 流量 <em>還沒到 origin</em>。對 origin 是 <em>任意雲 / on-prem</em> 的客戶、Cloudflare 是天然選項；對 AWS-only 客戶、AWS WAF 整合更深但 edge 範圍小。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/fastly-ngwaf/" data-link-title="Fastly Next-Gen WAF" data-link-desc="Behavioral / 語意分析 WAF（前 Signal Sciences）、低 false positive、Edge / Agent / Cloud 三種部署模型、API &#43; ATO &#43; Bot 一體">Fastly Next-Gen WAF</a>（前 Signal Sciences）相比、Cloudflare 走 <em>signature + managed rule + ML</em> 混合、Fastly NG-WAF 走 <em>語意分析 + behavioral detection</em>（不靠 regex signature）。Cloudflare managed rule 覆蓋廣但 false positive 較常見、需要 <em>sensitivity tuning</em>；Fastly NG-WAF 預設較低 FP 但需要 <em>自己定義業務 anomaly</em>。</p>
<p>關鍵張力：客戶信任的不只是 <em>WAF rule 攔截能力</em>、還包括 <em>Cloudflare control plane 的安全性</em>。<a href="/blog/backend/07-security-data-protection/cases/cloudflare-control-plane-token-2023/" data-link-title="7.C2 Cloudflare：2023 Control-plane Token 事件" data-link-desc="控制面 token 事件如何回寫 secrets 與機器憑證治理。">Cloudflare 2023 control plane token</a> 跟 <a href="/blog/backend/07-security-data-protection/cases/cloudflare-route-leak-2026/" data-link-title="7.C1 Cloudflare：2026 Route Leak 事件" data-link-desc="BGP 路由政策自動化失誤如何回寫控制面治理。">Cloudflare 2026 route leak</a> 兩個事件展示：vendor 自己被打進去 / 自動化配置失誤時、客戶側 <em>直接修不了</em>、只能等公告 + 客戶側 token rotation + emergency bypass。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>Cloudflare WAF 在 edge security stack 中承擔哪一段（DDoS / WAF / Bot / Page Shield / API Shield）、哪些要靠 origin 自己做</li>
<li>Managed Rule vs Custom Rule 的取捨、sensitivity tuning 跟 false positive curve</li>
<li>Cloudflare control plane 出事時的客戶側補強路徑（API token rotation、Origin Rules bypass、第二邊界 fallback）</li>
<li>何時用 Cloudflare、何時走 <a href="/blog/backend/07-security-data-protection/vendors/aws-waf/" data-link-title="AWS WAF" data-link-desc="AWS-internal WAF、跟 ALB / CloudFront / API Gateway 直接整合、Web ACL &#43; Managed Rule Group &#43; Rate-based Rule、Shield Standard 內含">AWS WAF</a> / <a href="/blog/backend/07-security-data-protection/vendors/fastly-ngwaf/" data-link-title="Fastly Next-Gen WAF" data-link-desc="Behavioral / 語意分析 WAF（前 Signal Sciences）、低 false positive、Edge / Agent / Cloud 三種部署模型、API &#43; ATO &#43; Bot 一體">Fastly NG-WAF</a> 的取捨</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Cloudflare WAF 配置是否健康、最少看四件事：</p>
<ul>
<li><strong>誰能改 WAF 規則</strong>：Cloudflare account 的 admin / member role 配置、API token scope（不要用 Global API Key、用 scoped API token + 限定 zone / 限定 permission）、Audit Log 是否同步到 SIEM</li>
<li><strong>規則覆蓋面</strong>：Managed Ruleset（OWASP Core Ruleset + Cloudflare Managed Ruleset + Exposed Credentials Check）是否開、Sensitivity（Low / Medium / High）對應的 FP rate 是否監控、Custom Rule 是否進版控（Terraform provider）</li>
<li><strong>入口暴露</strong>：origin IP 是否曝光（DNS 直查 / 歷史 SAN cert / 子域名）、Argo Tunnel / Authenticated Origin Pull 是否強制、繞過 Cloudflare 直連 origin 的路徑是否封住</li>
<li><strong>證據可回查</strong>：Security Events Log 是否同步到 SIEM（Logpush 推到 R2 / S3 / Splunk）、Page Shield 偵測異常 script 是否 alert、API token 異常操作（特別 zone settings 變更）是否 alert</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">Audit Log</a> 與 <a href="/blog/backend/07-security-data-protection/entrypoint-and-server-protection/" data-link-title="7.3 入口治理與伺服器防護" data-link-desc="以問題驅動方式整理對外入口、管理平面與伺服器邊界">Entry Point Protection</a> 邊界的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>Managed Ruleset 分層</strong>：Cloudflare 提供三類 managed rule — <em>OWASP Core Ruleset</em>（OWASP CRS、寬覆蓋、FP 較多）、<em>Cloudflare Managed Ruleset</em>（Cloudflare 維護、針對熱門 CMS / framework）、<em>Exposed Credentials Check</em>（檢測登入流量中的已洩漏 credential）。production 通常開全部三套 + 各設適當 sensitivity。Sensitivity 不是「敏感度越高越好」— High sensitivity 攔截更多 borderline traffic、business-critical endpoint 可能誤殺合法請求。建議從 <em>Log Mode</em> 開始、觀察 1-2 週的 FP pattern、再切到 <em>Block</em>。</p>
<p><strong>Custom Rule（Cloudflare Rules）</strong>：用 Rules language（類 SQL 表達式）定義條件 + 動作（Block / Challenge / Log / JS Challenge / Managed Challenge）。常見用法：geo block（特定國家）、known bad IP（threat intel feed）、URI path-based limit（admin endpoint 限定 IP）、header anomaly（缺 User-Agent / 異常 Referer）。所有 Custom Rule 走 Terraform provider 進版控、避免 console 直接改、變更走 PR review。</p>
<p><strong>Rate Limiting</strong>：跟 WAF rule 是 <em>獨立 product</em>、配置是 <em>threshold + window + action</em>（例：1000 req/min per IP → challenge）。Rate Limiting 比 WAF 適合處理 <em>legitimate-looking high volume</em>（credential stuffing、scraping、API abuse）。注意 <em>NAT pool IP</em> 的問題 — 一個公司 / ISP NAT 出口可能合法產生高 QPS、簡單 per-IP rate limit 會誤殺、需要組合 <em>cf.threat_score</em> 或 <em>cookie-based identification</em>。</p>
<p><strong>Bot Management（單獨 SKU）</strong>：免費版 WAF 不含 Bot Management、需要 Pro / Business / Enterprise 才有。Bot Management 用 ML + behavioral fingerprint 區分 <em>human / good bot（搜尋引擎）/ likely bot / verified bot</em>、給 bot score（1-99）。客戶在 Custom Rule 用 <code>cf.bot_management.score &lt; 30</code> 之類條件挑出 likely bot 處理。簡單 user-agent 過濾擋不住現代 headless browser、必須走 Bot Management。</p>
<p><strong>Page Shield（JS supply chain 防護）</strong>：Page Shield 監測客戶網頁載入的 JS / connect 來源、發現 <em>新出現的腳本</em> 或 <em>已洩漏的 script</em>（CT log + threat intel）就 alert。意義是 <em>防 third-party script 被供應鏈攻擊</em>（類 <a href="https://en.wikipedia.org/wiki/Magecart">Magecart</a>）— WAF 攔不住、因為攻擊發生在 <em>browser 端</em> 而非 <em>origin 流量</em>。需要在 Page 載入 Page Shield 的 monitoring script。</p>
<p><strong>API Shield</strong>：用 OpenAPI schema validation、auto-discovery API endpoint、mTLS 驗證、JWT validation。對於有 schema 的 API、可以擋掉 <em>schema 不符的請求</em>（多餘欄位、型別錯誤、缺必要欄位）— 比 generic WAF rule 精準。</p>
<p><strong>Origin 暴露面收緊</strong>：Cloudflare 唯一有效的前提是 <em>流量必須經過 Cloudflare</em>。如果攻擊者拿到 origin 真實 IP（DNS 歷史記錄、漏洞披露網站、SSL cert SAN）、可以繞過 Cloudflare 直打 origin。控制方法：origin firewall 只允許 Cloudflare IP range 入站、Argo Tunnel（origin 主動建 outbound 連線到 Cloudflare、不開任何入站 port）、Authenticated Origin Pull（origin 用 cert 驗證請求來自 Cloudflare）三選一或組合。</p>
<p><strong>API token 治理</strong>：避免 Global API Key（全帳號 root token）、改用 <em>scoped API token</em>（限 zone + 限 permission + 限 IP + 限 TTL）。token 進 <a href="/blog/backend/knowledge-cards/secret-management/" data-link-title="Secret Management" data-link-desc="說明 token、key、password 與憑證如何保存、輪替與撤銷">Secret Management</a> / <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a>、定期 rotate。對應 <a href="/blog/backend/07-security-data-protection/cases/cloudflare-control-plane-token-2023/" data-link-title="7.C2 Cloudflare：2023 Control-plane Token 事件" data-link-desc="控制面 token 事件如何回寫 secrets 與機器憑證治理。">Cloudflare control plane token 2023</a> 揭示的 lesson：Cloudflare 自己也踩過 token 治理不足、客戶側不能假設 vendor 完美。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Cloudflare WAF</th>
          <th>AWS WAF</th>
          <th>Fastly Next-Gen WAF</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>部署位置</td>
          <td>Cloudflare global edge（300+ POP）</td>
          <td>AWS region 內 ALB / CloudFront / API Gateway 前</td>
          <td>Fastly edge + Agent + Module（自管 Nginx / Apache / Envoy / IIS）+ Cloud WAF proxy、三模型可混</td>
      </tr>
      <tr>
          <td>Origin 中立性</td>
          <td>強 — origin 可以是任何雲 / on-prem</td>
          <td>弱 — 跟 AWS 緊耦合（限 AWS service 前）</td>
          <td>強 — Fastly CDN / 任何 origin</td>
      </tr>
      <tr>
          <td>偵測模型</td>
          <td>Signature + Managed Rule + ML</td>
          <td>Signature + Managed Rule + Lambda 自訂</td>
          <td>Signal / behavioral（語意分析、低 FP）</td>
      </tr>
      <tr>
          <td>DDoS 內建</td>
          <td>是 — 跟 WAF 同套餐</td>
          <td>AWS Shield Standard 內建、Advanced 加價</td>
          <td>內建 + Fastly DDoS</td>
      </tr>
      <tr>
          <td>Bot Management</td>
          <td>加價 add-on（Pro / Business / Enterprise）</td>
          <td>AWS WAF Bot Control</td>
          <td>加價 add-on</td>
      </tr>
      <tr>
          <td>JS supply chain</td>
          <td>Page Shield（Business+）</td>
          <td>無原生、靠後端 CSP / 第三方</td>
          <td>Inline JS monitoring（Next-Gen WAF 部分）</td>
      </tr>
      <tr>
          <td>API schema</td>
          <td>API Shield（Enterprise）</td>
          <td>AWS WAF + API Gateway request validator</td>
          <td>NG-WAF inline + sigsci-agent</td>
      </tr>
      <tr>
          <td>學習曲線</td>
          <td>中 — UI / Rules language 易上手、Terraform 完整</td>
          <td>較陡 — JSON policy + 跟 AWS service 整合多軌</td>
          <td>中 — agent 安裝 + Signal 語意設定</td>
      </tr>
      <tr>
          <td>第三方信任成本</td>
          <td>高 — Cloudflare 控制面（2023、2026 自家事件）</td>
          <td>中 — AWS 控制面、跟 IAM 同套</td>
          <td>中 — Fastly 控制面（規模小、事件少但社群影響也小）</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>Multi-cloud / on-prem origin、要整套 edge security</td>
          <td>AWS-heavy、ALB / CloudFront 是主要入口</td>
          <td>高 FP 容忍度低、業務有 schema、想避 regex signature</td>
      </tr>
  </tbody>
</table>
<p>選 Cloudflare WAF 的核心訴求：<em>多雲 / on-prem origin</em> + 需要 <em>整套 edge security suite</em>（DDoS + WAF + Bot + Page Shield + API Shield） + 接受 Cloudflare 控制面風險、且有預算做 Enterprise tier 才能拿到完整功能。純 AWS-internal app + ALB origin 用 AWS WAF 整合更直接。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Workers + Workers AI 作為 custom logic</strong>：當 managed rule + custom rule 表達力不夠（例：根據 user account tier 決定 challenge 強度、整合內部 risk score API）、可以用 Cloudflare Workers 寫 JavaScript / TypeScript / Rust 在 edge 執行。Workers AI 提供 edge ML inference、可以做 inline content moderation 或 anomaly detection。代價是 <em>Workers code 進 Cloudflare 控制面</em>、變更要走部署流程、debug 跟 origin 是兩條 trace。</p>
<p><strong>Logpush 跟 SIEM 整合</strong>：Cloudflare Security Events 量大、free / Pro 在 dashboard 看、Business / Enterprise 走 Logpush 到 R2 / S3 / Splunk / Datadog / Sumo Logic。production 必須走 Logpush、不能只在 dashboard — 事件 30 天保留期是 Cloudflare 端、SIEM 留更久。Logpush 也是 SIEM 上做 <em>跨來源 correlation</em> 的前提（WAF event + origin app log + IdP log）。</p>
<p><strong>Multi-account / Tenant</strong>：大企業有多個 Cloudflare account（不同 BU / 不同產品線）、要走 <em>Cloudflare for SaaS</em> 或 <em>Account-level access</em>、API token scope 要限定 account。Single account 多 zone 是常見小組織配置、但跨組織 / 跨產品線必須拆 account 隔離 admin compromise blast radius。</p>
<p><strong>Magic Transit / Zero Trust integration</strong>：Magic Transit 是 L3 DDoS（不只 HTTP、TCP / UDP 也 anycast）、Zero Trust 是 employee access（取代 VPN）。跟 WAF 是不同產品、但常一起部署 — Magic Transit 防 L3/L4 attack、WAF 防 L7、Zero Trust 防內部 east-west。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Managed Rule 誤殺合法請求</strong>：High sensitivity 開後 business endpoint 變慢 / 報錯 — 看 Security Events 找 rule_id、用 Custom Rule skip 該 rule 在特定 path / 特定 user-agent、不要全 zone 關 rule</li>
<li><strong>Bot Management 太嚴 / 太鬆</strong>：bot score threshold 設不對、合法 API client 被當 bot、或攻擊者拿到 verified bot 假冒 — 用 <em>Bot Analytics</em> 看分數分布、調整 threshold 同時加白名單（API key + IP CIDR）</li>
<li><strong>Rate Limit 誤殺 NAT 用戶</strong>：per-IP rate limit 在 NAT 出口 IP 上炸 — 改 per-session（cookie-based）或 cf.threat_score 條件</li>
<li><strong>Origin IP 外洩</strong>：DNS 歷史 + 漏洞披露 + cert SAN 揭露真實 origin、攻擊繞 Cloudflare 直打 — 換 IP + 開 origin firewall（只允許 Cloudflare CIDR）+ Argo Tunnel</li>
<li><strong>API token over-scoped</strong>：CI / 第三方 SaaS 拿到 Global API Key、整 account 都被改 — 改 scoped token、限 zone + permission + IP、進 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a></li>
<li><strong>Security Events 沒進 SIEM</strong>：事件只在 dashboard、跨來源 correlation 沒法做 — 配 Logpush + alert 規則</li>
<li><strong>Page Shield 沒裝</strong>：客戶端 JS 被植入、伺服器端日誌看不到攻擊、第三方 script CDN 被打 — 啟用 Page Shield + CSP report-uri 雙軌</li>
<li><strong>第二邊界沒設</strong>：完全依賴 Cloudflare、Cloudflare 出事流量全停（<a href="/blog/backend/07-security-data-protection/cases/cloudflare-route-leak-2026/" data-link-title="7.C1 Cloudflare：2026 Route Leak 事件" data-link-desc="BGP 路由政策自動化失誤如何回寫控制面治理。">2023 / 2026 自家事件</a>）— 高 SLA 服務應該設 fallback origin / secondary DNS（如 Route53 health check failover 到 Fastly 或直連 origin）</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>AWS-only + ALB / CloudFront origin</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/aws-waf/" data-link-title="AWS WAF" data-link-desc="AWS-internal WAF、跟 ALB / CloudFront / API Gateway 直接整合、Web ACL &#43; Managed Rule Group &#43; Rate-based Rule、Shield Standard 內含">AWS WAF</a></td>
      </tr>
      <tr>
          <td>低 FP 容忍 / 業務有 schema</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/fastly-ngwaf/" data-link-title="Fastly Next-Gen WAF" data-link-desc="Behavioral / 語意分析 WAF（前 Signal Sciences）、低 false positive、Edge / Agent / Cloud 三種部署模型、API &#43; ATO &#43; Bot 一體">Fastly Next-Gen WAF</a></td>
      </tr>
      <tr>
          <td>純內部 mTLS / east-west</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/spire/" data-link-title="SPIRE" data-link-desc="SPIFFE Runtime Environment、attested workload identity、short-lived SVID &#43; Trust Bundle、跨組織 federation">SPIRE</a> + service mesh</td>
      </tr>
      <tr>
          <td>Cert lifecycle</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/cert-manager/" data-link-title="cert-manager" data-link-desc="K8s 原生 certificate lifecycle automation、支援 Let&#39;s Encrypt / Vault PKI / Venafi 等多 issuer、auto-renewal &#43; Challenge solver">cert-manager</a> / <a href="/blog/backend/07-security-data-protection/vendors/letsencrypt/" data-link-title="Let&#39;s Encrypt" data-link-desc="免費 &#43; 自動化的公共 ACME CA、90 天 TTL 強制自動化、跨雲跨平台 public TLS cert 的事實基礎">Let&rsquo;s Encrypt</a></td>
      </tr>
      <tr>
          <td>客戶端 JS supply chain</td>
          <td>Page Shield + <a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">supply chain integrity</a></td>
      </tr>
      <tr>
          <td>DDoS L3/L4</td>
          <td>Cloudflare Magic Transit / AWS Shield Advanced</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Cloudflare 完整 product line（Workers / Pages / R2 / D1 / Magic Transit / Zero Trust 各自細節）</li>
<li>WAF Rules language 完整語法 reference</li>
<li>Page Shield / API Shield Enterprise tier 完整功能對照</li>
<li>各 PCI DSS / SOC 2 / FedRAMP 合規矩陣</li>
<li>Cloudflare 在中國的部署模式（JD Cloud Union 合作）</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>Cloudflare WAF 在 07 案例庫有 <em>兩個直接 vendor-level 事件</em> + 多個 edge-exposure 對照：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 Cloudflare WAF 的關係</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/cases/cloudflare-control-plane-token-2023/" data-link-title="7.C2 Cloudflare：2023 Control-plane Token 事件" data-link-desc="控制面 token 事件如何回寫 secrets 與機器憑證治理。">Cloudflare Control Plane Token 2023</a></td>
          <td>直接 — Cloudflare 自家 API token 治理不足、客戶側必須假設 vendor 也會被打、API token rotation 跟 IP allowlist 必做</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/cases/cloudflare-route-leak-2026/" data-link-title="7.C1 Cloudflare：2026 Route Leak 事件" data-link-desc="BGP 路由政策自動化失誤如何回寫控制面治理。">Cloudflare Route Leak 2026</a></td>
          <td>直接 — 自動化路由配置錯誤導致流量擁塞、客戶側應有 secondary DNS / failover origin 預案</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/edge-exposure/citrix-bleed-2023-session-hijack/" data-link-title="7.R7.3.3 Citrix Bleed 2023：會話被劫持與重放風險" data-link-desc="邊界設備會話資料外洩後，如何演變成帳號與服務風險">Citrix Bleed 2023 Session Hijack</a></td>
          <td>對照啟示 — WAF 攔不住 edge appliance zero-day、需要「修補 + session 失效 + 異常清查」三同步</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/edge-exposure/fortinet-cve-2023-27997-sslvpn-overflow/" data-link-title="7.R7.3.21 Fortinet 2023：CVE-2023-27997 SSL-VPN 溢位" data-link-desc="SSL-VPN 漏洞在邊界設備上會放大大規模掃描與利用速度">Fortinet SSL-VPN CVE 2023-27997</a></td>
          <td>對照啟示 — vendor patch 前的臨時 WAF rule + 收斂可達來源是修補窗口期的標準動作</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/log4shell-cve-2021-44228-component-chain/" data-link-title="7.R7.2.7 Log4Shell 2021：共用元件風險與修補鏈" data-link-desc="共用元件漏洞如何同步影響多服務，並迫使團隊建立依賴治理 workflow">Log4Shell CVE-2021-44228</a></td>
          <td>對照啟示 — WAF rule 是 emergency mitigation、但 exploitation 過 WAF 後在後端執行、不能單靠 WAF 防後端 supply chain</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/okta-cloudflare-2023-support-supply-chain/" data-link-title="7.R7.1.2 Okta &#43; Cloudflare 2023：支援流程與身分供應鏈" data-link-desc="支援工單與第三方身份供應商路徑如何變成入侵鏈的一部分">Okta-Cloudflare 2023 Support Supply Chain</a></td>
          <td>對照啟示 — 上游 IdP 出事傳導到 Cloudflare admin 帳號、API token / admin session 要立即 rotate、不等供應商公告</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/entrypoint-and-server-protection/" data-link-title="7.3 入口治理與伺服器防護" data-link-desc="以問題驅動方式整理對外入口、管理平面與伺服器邊界">7.3 入口治理與伺服器防護</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/aws-waf/" data-link-title="AWS WAF" data-link-desc="AWS-internal WAF、跟 ALB / CloudFront / API Gateway 直接整合、Web ACL &#43; Managed Rule Group &#43; Rate-based Rule、Shield Standard 內含">AWS WAF</a>、<a href="/blog/backend/07-security-data-protection/vendors/fastly-ngwaf/" data-link-title="Fastly Next-Gen WAF" data-link-desc="Behavioral / 語意分析 WAF（前 Signal Sciences）、低 false positive、Edge / Agent / Cloud 三種部署模型、API &#43; ATO &#43; Bot 一體">Fastly Next-Gen WAF</a></li>
<li>下游：<a href="/blog/backend/07-security-data-protection/data-protection-and-masking-governance/" data-link-title="7.4 資料保護與遮罩治理" data-link-desc="以問題驅動方式整理資料分級、遮罩、匯出與備份治理">7.4 資料保護與遮罩治理</a>（WAF block 不夠時、資料層也要遮罩）</li>
<li>跨類：<a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a>（Cloudflare API token 存放）、<a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a>（Cloudflare admin 走 SSO）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（WAF block 事件 / Cloudflare 自家事件如何 routing 進 IR）</li>
<li>官方：<a href="https://developers.cloudflare.com/waf/">Cloudflare WAF Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>HashiCorp Vault</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/hashicorp-vault/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/hashicorp-vault/</guid><description>&lt;p>HashiCorp Vault 是 self-hosted 的 secret management 控制面、解決三個核心問題：&lt;em>static secret 集中保管&lt;/em>（KV engine、跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/secret-management/" data-link-title="Secret Management" data-link-desc="說明 token、key、password 與憑證如何保存、輪替與撤銷">Secret Management&lt;/a> 卡同概念）、&lt;em>dynamic credential 即用即發即收&lt;/em>（database / cloud / SSH engine 在請求時動態建立短期憑證）、&lt;em>encryption-as-a-service 與內部 PKI&lt;/em>（transit engine 把加解密外包給 Vault、PKI engine 自簽憑證）。三件事在 cloud-native 替代品（&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-secrets-manager/" data-link-title="AWS Secrets Manager" data-link-desc="AWS 原生 secret store &amp;#43; 內建 RDS / Redshift rotation Lambda、Resource Policy 跨帳號共享、KMS 加密">AWS Secrets Manager&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/google-secret-manager/" data-link-title="Google Secret Manager" data-link-desc="GCP 原生 secret store、CMEK &amp;#43; Workload Identity Federation 整合、rotation 走自寫 Cloud Function 而非 built-in Lambda">Google Secret Manager&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/azure-key-vault/" data-link-title="Azure Key Vault" data-link-desc="Azure 三合一 service（Secret &amp;#43; Key &amp;#43; Certificate）、整合 Managed Identity &amp;#43; Entra ID RBAC、Premium tier 走 HSM">Azure Key Vault&lt;/a>）裡通常拆成不同 service、且綁單一雲。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Vault 的核心定位是 &lt;em>跨雲 + 跨環境 + 跨 secret 形態的單一 secret 控制面&lt;/em>。當組織同時跑 AWS + GCP + on-prem K8s、又需要 dynamic database credential + 內部 PKI + envelope encryption、用三個 cloud-native service 拼起來會出現 &lt;em>secret 治理鏈不連續&lt;/em>（AWS 的 secret 怎麼授權 GCP service 取用、on-prem app 怎麼拿短期 cloud credential、內部 CA 跟外部 ACM 怎麼分工）。Vault 把這層 &lt;em>統一抽象&lt;/em> — 應用端只跟 Vault 講話、Vault 後端接各雲 KMS / database / PKI。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-secrets-manager/" data-link-title="AWS Secrets Manager" data-link-desc="AWS 原生 secret store &amp;#43; 內建 RDS / Redshift rotation Lambda、Resource Policy 跨帳號共享、KMS 加密">AWS Secrets Manager&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/google-secret-manager/" data-link-title="Google Secret Manager" data-link-desc="GCP 原生 secret store、CMEK &amp;#43; Workload Identity Federation 整合、rotation 走自寫 Cloud Function 而非 built-in Lambda">Google Secret Manager&lt;/a> 相比、Vault 多了：&lt;em>dynamic credential engine&lt;/em>（cloud-native 對應產品有限）、&lt;em>transit engine&lt;/em> 做 encryption-as-a-service、&lt;em>PKI engine&lt;/em> 自簽內部憑證、&lt;em>跨雲統一介面&lt;/em>。代價是 &lt;em>自管運維&lt;/em>（HA cluster、auto-unseal、replication、upgrade）— 跟自管 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/keycloak/" data-link-title="Keycloak" data-link-desc="Open source self-hosted Identity Provider、Red Hat 主導、Realm-based multi-tenancy、適合資料主權與自訂 flow 需求">Keycloak&lt;/a> 的取捨同類。HCP Vault（HashiCorp Cloud Platform）是 HashiCorp 託管版、把運維交還、但綁 HashiCorp。&lt;/p></description><content:encoded><![CDATA[<p>HashiCorp Vault 是 self-hosted 的 secret management 控制面、解決三個核心問題：<em>static secret 集中保管</em>（KV engine、跟 <a href="/blog/backend/knowledge-cards/secret-management/" data-link-title="Secret Management" data-link-desc="說明 token、key、password 與憑證如何保存、輪替與撤銷">Secret Management</a> 卡同概念）、<em>dynamic credential 即用即發即收</em>（database / cloud / SSH engine 在請求時動態建立短期憑證）、<em>encryption-as-a-service 與內部 PKI</em>（transit engine 把加解密外包給 Vault、PKI engine 自簽憑證）。三件事在 cloud-native 替代品（<a href="/blog/backend/07-security-data-protection/vendors/aws-secrets-manager/" data-link-title="AWS Secrets Manager" data-link-desc="AWS 原生 secret store &#43; 內建 RDS / Redshift rotation Lambda、Resource Policy 跨帳號共享、KMS 加密">AWS Secrets Manager</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-secret-manager/" data-link-title="Google Secret Manager" data-link-desc="GCP 原生 secret store、CMEK &#43; Workload Identity Federation 整合、rotation 走自寫 Cloud Function 而非 built-in Lambda">Google Secret Manager</a> / <a href="/blog/backend/07-security-data-protection/vendors/azure-key-vault/" data-link-title="Azure Key Vault" data-link-desc="Azure 三合一 service（Secret &#43; Key &#43; Certificate）、整合 Managed Identity &#43; Entra ID RBAC、Premium tier 走 HSM">Azure Key Vault</a>）裡通常拆成不同 service、且綁單一雲。</p>
<h2 id="服務定位">服務定位</h2>
<p>Vault 的核心定位是 <em>跨雲 + 跨環境 + 跨 secret 形態的單一 secret 控制面</em>。當組織同時跑 AWS + GCP + on-prem K8s、又需要 dynamic database credential + 內部 PKI + envelope encryption、用三個 cloud-native service 拼起來會出現 <em>secret 治理鏈不連續</em>（AWS 的 secret 怎麼授權 GCP service 取用、on-prem app 怎麼拿短期 cloud credential、內部 CA 跟外部 ACM 怎麼分工）。Vault 把這層 <em>統一抽象</em> — 應用端只跟 Vault 講話、Vault 後端接各雲 KMS / database / PKI。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/aws-secrets-manager/" data-link-title="AWS Secrets Manager" data-link-desc="AWS 原生 secret store &#43; 內建 RDS / Redshift rotation Lambda、Resource Policy 跨帳號共享、KMS 加密">AWS Secrets Manager</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-secret-manager/" data-link-title="Google Secret Manager" data-link-desc="GCP 原生 secret store、CMEK &#43; Workload Identity Federation 整合、rotation 走自寫 Cloud Function 而非 built-in Lambda">Google Secret Manager</a> 相比、Vault 多了：<em>dynamic credential engine</em>（cloud-native 對應產品有限）、<em>transit engine</em> 做 encryption-as-a-service、<em>PKI engine</em> 自簽內部憑證、<em>跨雲統一介面</em>。代價是 <em>自管運維</em>（HA cluster、auto-unseal、replication、upgrade）— 跟自管 <a href="/blog/backend/07-security-data-protection/vendors/keycloak/" data-link-title="Keycloak" data-link-desc="Open source self-hosted Identity Provider、Red Hat 主導、Realm-based multi-tenancy、適合資料主權與自訂 flow 需求">Keycloak</a> 的取捨同類。HCP Vault（HashiCorp Cloud Platform）是 HashiCorp 託管版、把運維交還、但綁 HashiCorp。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>哪些 secret 適合 Vault（dynamic credential、跨雲、PKI、encryption-as-a-service）、哪些直接用雲端 native service 即可</li>
<li>Vault deployment 的最低安全需求（auto-unseal、HA、audit device、policy、replication）</li>
<li>Vault 自己出事時的降級路徑（seal storm、root token 復原、audit log gap）</li>
<li>何時用 Vault、何時走 <a href="/blog/backend/07-security-data-protection/vendors/aws-secrets-manager/" data-link-title="AWS Secrets Manager" data-link-desc="AWS 原生 secret store &#43; 內建 RDS / Redshift rotation Lambda、Resource Policy 跨帳號共享、KMS 加密">Secrets Manager</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-secret-manager/" data-link-title="Google Secret Manager" data-link-desc="GCP 原生 secret store、CMEK &#43; Workload Identity Federation 整合、rotation 走自寫 Cloud Function 而非 built-in Lambda">Google Secret Manager</a> / <a href="/blog/backend/07-security-data-protection/vendors/azure-key-vault/" data-link-title="Azure Key Vault" data-link-desc="Azure 三合一 service（Secret &#43; Key &#43; Certificate）、整合 Managed Identity &#43; Entra ID RBAC、Premium tier 走 HSM">Azure Key Vault</a> 的取捨</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Vault deployment 是否健康、最少看五件事：</p>
<ul>
<li><strong>誰能做什麼</strong>：root token 是否已 revoke、policy 是否走 path-based least privilege、admin 是否走 OIDC / <a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM auth</a> 而不是 token、break-glass token 是否離線存</li>
<li><strong>Auth method 收緊</strong>：AppRole / Kubernetes / OIDC / JWT auth 哪些開、role 對應的 policy 是不是過寬、TTL 是否短、<code>bound_*</code> 條件是否鎖（namespace / audience / subject）</li>
<li><strong>Secret engine 設定</strong>：KV v2 開 versioning？dynamic engine（database / aws / pki）lease TTL 多久、max TTL 限制是什麼、revocation 是否驗證生效</li>
<li><strong>Seal / unseal 治理</strong>：是否走 auto-unseal（KMS-backed）、recovery key 持有者跟 Shamir threshold、replication 跟 DR cluster 是否同步</li>
<li><strong>證據是否可回查</strong>：audit device（file / syslog / socket）是否多 channel、是否同步到 SIEM、replay 攻擊防護是否開（HMAC + nonce）</li>
</ul>
<p>五件事任一缺失、就是 <a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">Audit Log</a> 與 <a href="/blog/backend/knowledge-cards/secret-management/" data-link-title="Secret Management" data-link-desc="說明 token、key、password 與憑證如何保存、輪替與撤銷">Secret Management</a> 邊界的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>Auth method 設計</strong>：AppRole 適合不在雲端 metadata 內的 workload（on-prem、CI runner）但 <em>secret_id</em> 本身要妥善保管；Kubernetes auth 適合 K8s 內 workload、用 ServiceAccount token + projected token；<a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM auth</a> 適合 AWS 內 workload、走 STS 簽名驗證、不需要存 secret；OIDC / JWT 適合 human admin + CI（GitHub Actions / GitLab CI 走 OIDC token）。每個 auth method 對應 <em>一組 role</em>、role 綁 <em>policy</em> 跟 <em>TTL</em>。</p>
<p><strong>Secret engine 分層</strong>：KV v2（static secret + version history）作為基線；dynamic database engine（PostgreSQL / MySQL / MongoDB）發短期 DB user、<code>max_ttl = 1h</code> 級別、過期 Vault 自動 revoke；AWS / Azure / GCP secret engine 對 cloud account 發短期 STS credential / service account key；PKI engine 自簽憑證、跟 <a href="/blog/backend/07-security-data-protection/vendors/cert-manager/" data-link-title="cert-manager" data-link-desc="K8s 原生 certificate lifecycle automation、支援 Let&#39;s Encrypt / Vault PKI / Venafi 等多 issuer、auto-renewal &#43; Challenge solver">cert-manager</a> 整合做 K8s workload mTLS；transit engine 做 envelope encryption — app 把資料丟給 Vault 加密、key 不離 Vault。</p>
<p><strong>Policy（path-based）</strong>：Vault policy 是 <em>path + capabilities</em>（create / read / update / delete / list / sudo）的 mapping。常見錯配：給 <code>secret/*</code> read 等於整個組織所有 secret 都看得到、應該用 <code>secret/data/{team}/*</code> 之類前綴限定；admin policy 不要給 <code>sudo</code> 太寬、policy 變更走 PR review + CI apply。</p>
<p><strong>Rotation 跟 lease 治理</strong>：static secret（KV）的 rotation 是 <em>app 自己做</em>（拿新 secret 後手動 update）；dynamic secret 是 <em>Vault 控制 lease 生命週期</em>、app 只要在 TTL 內續租即可。對應 <a href="/blog/backend/07-security-data-protection/cases/failure-credential-rotation-without-scope/" data-link-title="7.C9 反例：憑證輪替未分 Scope" data-link-desc="憑證輪替若未分域分批，容易造成跨系統連鎖中斷。">Failure: Credential Rotation Without Scope</a>：static secret 的 rotation 必須有 <em>scope map</em> — 哪些 service 用了同一把 secret、哪個 service 支援零停機 rotation、誰是 last to be rotated。沒這份 map 就會發生「rotate 後某個被遺忘的 cron job 認證失敗、整個下游崩」。</p>
<p><strong>Seal / unseal 設計</strong>：Vault 啟動時 sealed、必須 unseal 才能服務。Shamir secret sharing 是預設（5 key holders、3 threshold）— 任何重啟需要找齊 3 個人合 unseal、production 場景幾乎都該換 auto-unseal（用 <a href="/blog/backend/07-security-data-protection/vendors/aws-kms/" data-link-title="AWS KMS" data-link-desc="AWS 原生 key management service、envelope encryption / digital signing / Multi-Region Key、Key Policy &#43; Grant 雙軌授權">AWS KMS</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-kms/" data-link-title="Google Cloud KMS" data-link-desc="GCP 原生 key management service、KeyRing / CryptoKey Version 設計、CMEK 整合 &#43; Cloud HSM &#43; External Key Manager">GCP KMS</a> / <a href="/blog/backend/07-security-data-protection/vendors/azure-key-vault/" data-link-title="Azure Key Vault" data-link-desc="Azure 三合一 service（Secret &#43; Key &#43; Certificate）、整合 Managed Identity &#43; Entra ID RBAC、Premium tier 走 HSM">Azure Key Vault</a> 當 master key custodian）。代價是 <em>把 master key 託給雲廠</em> — 不接受的組織保留 Shamir + 嚴格 key holder rotation。</p>
<p><strong>Audit device 是 <em>必開</em></strong>：Vault 預設不開 audit、要手動 enable（<code>vault audit enable file path=/var/log/vault_audit.log</code>）。沒 audit device 在 production = 事故時 <em>連 token 被誰用過都查不到</em>。建議多 channel（file + syslog + 推到外部 SIEM）— 單一 channel 失效（disk full、socket broken）Vault 會拒絕請求、影響 availability、所以多 channel 是必要冗餘。</p>
<p><strong>Break-glass 與 root token</strong>：初始化時產生的 root token 應該 <em>用完立刻 revoke</em>、改用 admin policy + OIDC auth。break-glass scenario 用 <em>recovery key 重新發 root token</em>、recovery key 走 Shamir 多人持有 + 離線存。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Vault (self-hosted)</th>
          <th>HCP Vault</th>
          <th>AWS Secrets Manager</th>
          <th>Google Secret Manager</th>
          <th>Azure Key Vault</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>部署模型</td>
          <td>自管 cluster（HA + replication）</td>
          <td>HashiCorp 託管</td>
          <td>AWS managed</td>
          <td>GCP managed</td>
          <td>Azure managed</td>
      </tr>
      <tr>
          <td>跨雲</td>
          <td>強 — 同一介面跨 AWS / GCP / Azure / on-prem</td>
          <td>強</td>
          <td>弱 — 綁 AWS</td>
          <td>弱 — 綁 GCP</td>
          <td>弱 — 綁 Azure</td>
      </tr>
      <tr>
          <td>Dynamic credential</td>
          <td>DB / cloud / SSH engine 完整</td>
          <td>同 OSS</td>
          <td>無 — 僅 RDS / Redshift static rotation Lambda</td>
          <td>無 — 自寫 Cloud Function；secret-less 走 WIF</td>
          <td>無 — 純 static；secret-less 走 Managed Identity</td>
      </tr>
      <tr>
          <td>PKI / transit</td>
          <td>內建 PKI engine + transit engine</td>
          <td>同 OSS</td>
          <td>走 <a href="/blog/backend/07-security-data-protection/vendors/aws-acm/" data-link-title="AWS ACM" data-link-desc="AWS-managed certificate provisioning、DNS validation &#43; auto-renewal、整合 ELB / CloudFront / API Gateway、Private CA 後端">AWS ACM</a> + <a href="/blog/backend/07-security-data-protection/vendors/aws-kms/" data-link-title="AWS KMS" data-link-desc="AWS 原生 key management service、envelope encryption / digital signing / Multi-Region Key、Key Policy &#43; Grant 雙軌授權">KMS</a></td>
          <td>走 cloud KMS + Certificate Authority Service</td>
          <td>走 <a href="/blog/backend/07-security-data-protection/vendors/azure-key-vault/" data-link-title="Azure Key Vault" data-link-desc="Azure 三合一 service（Secret &#43; Key &#43; Certificate）、整合 Managed Identity &#43; Entra ID RBAC、Premium tier 走 HSM">Azure Key Vault</a> cert 功能</td>
      </tr>
      <tr>
          <td>運維成本</td>
          <td>高 — HA、upgrade、replication、cert 自己顧</td>
          <td>低 — HashiCorp 顧</td>
          <td>低</td>
          <td>低</td>
          <td>低</td>
      </tr>
      <tr>
          <td>第三方信任成本</td>
          <td>低 — 自管</td>
          <td>中 — HashiCorp 控制面</td>
          <td>中 — AWS 控制面</td>
          <td>中 — GCP 控制面</td>
          <td>中 — Microsoft 控制面</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>跨雲、需要 dynamic credential、內部 PKI、預算允許</td>
          <td>想要 Vault 能力但不想自管</td>
          <td>AWS-heavy + 簡單 static secret</td>
          <td>GCP-heavy + Workload Identity 已主導</td>
          <td>Azure-heavy + Managed Identity 已主導</td>
      </tr>
      <tr>
          <td>退場成本</td>
          <td>中 — 自己掌握資料、但 dynamic engine 接線多</td>
          <td>中</td>
          <td>低</td>
          <td>低</td>
          <td>低</td>
      </tr>
  </tbody>
</table>
<p>選 Vault 的核心訴求：<em>跨雲 + dynamic credential + 內部 PKI + transit encryption 至少滿足兩項</em>、且能投入 SRE 量能跑 HA cluster、有 SIEM 接 audit log、能接受 self-hosted 的 upgrade / cert / DB 運維成本。單純需要 AWS-only static secret rotation、直接用 <a href="/blog/backend/07-security-data-protection/vendors/aws-secrets-manager/" data-link-title="AWS Secrets Manager" data-link-desc="AWS 原生 secret store &#43; 內建 RDS / Redshift rotation Lambda、Resource Policy 跨帳號共享、KMS 加密">Secrets Manager</a> 更便宜更簡單。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Dynamic credential 的 lease 生命週期治理</strong>：dynamic engine 發出的 credential 都帶 lease ID、Vault 在 TTL 到期時自動 revoke（database engine 真的會 DROP USER、cloud engine 真的會 DeleteAccessKey）。設計時要算清楚 <em>app 連線池的 connection lifetime</em> — DB connection 持續用同一組 credential、credential lease 過期但 connection 還在會出現 <em>staled credential</em> 問題。常見作法：lease TTL &gt; connection idle timeout * 2、加 lease renewal mechanism（app 在 TTL 50% 時主動 renew）。</p>
<p><strong>Transit engine（encryption-as-a-service）</strong>：app 不持 encryption key、把 plaintext 丟給 Vault <code>encrypt</code> API、拿 ciphertext 回來；解密時把 ciphertext 給 Vault <code>decrypt</code> API。Key 完全不離 Vault、所有 cryptographic operation 在 Vault 內、app 只需要 <em>encrypt / decrypt capability</em>。對應 <a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/microsoft-storm-0558-2023-signing-key-chain/" data-link-title="7.R7.1.5 Microsoft Storm-0558 2023：簽章金鑰鏈與郵件存取" data-link-desc="從簽章金鑰保護失效到雲端郵件存取，拆解身分信任鏈的關鍵控制點">Storm-0558 signing key chain</a> 的對照啟示：key 不能 export 是減 blast radius 的關鍵設計 — transit 把這個原則內建。</p>
<p><strong>PKI engine + cert-manager 整合</strong>：Vault PKI engine 可以當內部 root CA + intermediate CA、issue 短期 cert（hours-level）給 K8s workload；<a href="/blog/backend/07-security-data-protection/vendors/cert-manager/" data-link-title="cert-manager" data-link-desc="K8s 原生 certificate lifecycle automation、支援 Let&#39;s Encrypt / Vault PKI / Venafi 等多 issuer、auto-renewal &#43; Challenge solver">cert-manager</a> 用 Vault PKI issuer 自動更新 cert。比起手動跑 OpenSSL CA、Vault PKI 的優勢是 <em>cert lifecycle 進 Vault audit</em>、跟 secret rotation 用同一套 evidence chain（呼應 <a href="/blog/backend/07-security-data-protection/credential-rotation-scoped-evidence/" data-link-title="7.27 Credential Rotation with Scoped Evidence 實作示範" data-link-desc="以 webhook/API credential 輪替示範 scope map、證據欄位與回退窗口如何一起設計。">credential rotation scoped evidence</a>）。</p>
<p><strong>Namespace（Enterprise）跟 multi-tenancy</strong>：Enterprise 版 namespace 是 <em>tenant 邏輯隔離</em>、每個 namespace 有自己的 auth method、policy、secret engine。OSS 版沒 namespace — 多團隊共用 Vault 要靠 path 命名規約 + policy prefix 拼隔離、邊界較鬆。大組織通常需要 namespace 才能避免單一 admin 跨 team 越界。</p>
<p><strong>Replication（Enterprise）</strong>：Performance Replication（主從 + 多 region active）跟 DR Replication（純 standby）是兩個獨立功能。production HA 通常需要 <em>同 region 的 cluster + 跨 region 的 DR replication</em>、recovery key 跟 unseal 機制要跨 cluster 一致。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Audit device 沒開</strong>：production 啟動時忘了 enable audit、事故發生時無 forensic data — 啟動 checklist 必含「enable audit before serving traffic」、SRE runbook 用 health check 驗</li>
<li><strong>Policy 過寬</strong>：給整個 <code>secret/*</code> read、單一 token 等於拿到全公司 secret — 用 path prefix 限定到 <code>{team}/{env}/*</code>、policy review 走 PR</li>
<li><strong>Dynamic credential lease 太長 / 沒 max_ttl</strong>：DB user 跑了一週還沒收、攻擊者只要拿到一次就長期可用 — 設定 lease TTL = 1h、max_ttl = 24h</li>
<li><strong>Auto-unseal KMS access 沒監控</strong>：<a href="/blog/backend/07-security-data-protection/vendors/aws-kms/" data-link-title="AWS KMS" data-link-desc="AWS 原生 key management service、envelope encryption / digital signing / Multi-Region Key、Key Policy &#43; Grant 雙軌授權">AWS KMS</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-kms/" data-link-title="Google Cloud KMS" data-link-desc="GCP 原生 key management service、KeyRing / CryptoKey Version 設計、CMEK 整合 &#43; Cloud HSM &#43; External Key Manager">GCP KMS</a> 的 Vault auto-unseal key 沒 alert 異常使用 — KMS 端設 alert（GetKeyValue / Decrypt 突增）</li>
<li><strong>Replication lag 沒 alert</strong>：Performance / DR replication 落後幾分鐘到幾小時、failover 時拿到 stale state — Prometheus 監控 <code>vault.replication.*</code> metric</li>
<li><strong>Root token 未 revoke</strong>：初始化時的 root token 還在用、policy / audit / OIDC 全 bypass — 初始化 checklist 強制 revoke、CI 跑 <code>vault token lookup</code> 驗證 root 不可用</li>
<li><strong>Sealed 後 unseal key 找不到人</strong>：production cluster 緊急 restart、Shamir threshold 3 但有 1 個 key holder 在度假 — production 必須 auto-unseal、recovery key 走 <a href="/blog/backend/07-security-data-protection/identity-access-boundary/" data-link-title="7.2 身分與授權邊界" data-link-desc="以問題驅動方式整理身分、授權、會話與供應商身分鏈">break-glass</a> 流程</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>AWS-only + 簡單 static secret</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/aws-secrets-manager/" data-link-title="AWS Secrets Manager" data-link-desc="AWS 原生 secret store &#43; 內建 RDS / Redshift rotation Lambda、Resource Policy 跨帳號共享、KMS 加密">AWS Secrets Manager</a></td>
      </tr>
      <tr>
          <td>GCP-only + 已用 Workload Identity</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/google-secret-manager/" data-link-title="Google Secret Manager" data-link-desc="GCP 原生 secret store、CMEK &#43; Workload Identity Federation 整合、rotation 走自寫 Cloud Function 而非 built-in Lambda">Google Secret Manager</a></td>
      </tr>
      <tr>
          <td>Azure-only + 已用 Managed Identity</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/azure-key-vault/" data-link-title="Azure Key Vault" data-link-desc="Azure 三合一 service（Secret &#43; Key &#43; Certificate）、整合 Managed Identity &#43; Entra ID RBAC、Premium tier 走 HSM">Azure Key Vault</a></td>
      </tr>
      <tr>
          <td>大型 cryptographic / HSM 需求</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/cloudhsm/" data-link-title="AWS CloudHSM" data-link-desc="Single-tenant dedicated HSM（FIPS 140-2 Level 3）、AWS 不持 Crypto User credential、合規 &#43; 資料主權場景的 key custody">CloudHSM</a>（FIPS 140-2 Level 3、Vault auto-unseal 後端）</td>
      </tr>
      <tr>
          <td>公開憑證 PKI（serving cert）</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/aws-acm/" data-link-title="AWS ACM" data-link-desc="AWS-managed certificate provisioning、DNS validation &#43; auto-renewal、整合 ELB / CloudFront / API Gateway、Private CA 後端">AWS ACM</a> / <a href="/blog/backend/07-security-data-protection/vendors/letsencrypt/" data-link-title="Let&#39;s Encrypt" data-link-desc="免費 &#43; 自動化的公共 ACME CA、90 天 TTL 強制自動化、跨雲跨平台 public TLS cert 的事實基礎">Let&rsquo;s Encrypt</a></td>
      </tr>
      <tr>
          <td>K8s workload cert 自動化</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/cert-manager/" data-link-title="cert-manager" data-link-desc="K8s 原生 certificate lifecycle automation、支援 Let&#39;s Encrypt / Vault PKI / Venafi 等多 issuer、auto-renewal &#43; Challenge solver">cert-manager</a>（可用 Vault 當 issuer）</td>
      </tr>
      <tr>
          <td>跨服務 workload identity (SPIFFE)</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/spire/" data-link-title="SPIRE" data-link-desc="SPIFFE Runtime Environment、attested workload identity、short-lived SVID &#43; Trust Bundle、跨組織 federation">SPIRE</a></td>
      </tr>
      <tr>
          <td>Secret 全公司 rotation 證據鏈</td>
          <td><a href="/blog/backend/07-security-data-protection/credential-rotation-scoped-evidence/" data-link-title="7.27 Credential Rotation with Scoped Evidence 實作示範" data-link-desc="以 webhook/API credential 輪替示範 scope map、證據欄位與回退窗口如何一起設計。">7.5 Credential Rotation Scoped Evidence</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Vault 完整 API reference 跟 CLI 詳盡用法</li>
<li>每個 secret engine 的內部實作細節（DB connection pool、cloud SDK 呼叫順序）</li>
<li>Enterprise 各 license tier 的功能對照</li>
<li>Terraform / Ansible 跟 Vault 整合的完整步驟</li>
<li>各 auth method 的 OIDC / SAML provider 設定教學</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>Vault 在 07 案例庫沒有直接 vendor-level 事件、以下案例採對照引用：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 Vault 的關係（對照）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/cases/failure-credential-rotation-without-scope/" data-link-title="7.C9 反例：憑證輪替未分 Scope" data-link-desc="憑證輪替若未分域分批，容易造成跨系統連鎖中斷。">Failure: Credential Rotation Without Scope</a></td>
          <td>static secret rotation 必須有 scope map — Vault KV 多 service 共用同一把 secret 時、rotation 要分批 + 雙軌驗證窗口、不能一次 push 全域更新</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/microsoft-storm-0558-2023-signing-key-chain/" data-link-title="7.R7.1.5 Microsoft Storm-0558 2023：簽章金鑰鏈與郵件存取" data-link-desc="從簽章金鑰保護失效到雲端郵件存取，拆解身分信任鏈的關鍵控制點">Microsoft Storm-0558 Signing Key Chain (red-team)</a></td>
          <td>transit engine 的設計啟示 — key 不離保護邊界、即使被讀也搬不走、跟 HSM-bound 同 mindset</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/circleci-2023-secrets-rotation/" data-link-title="7.R7.2.3 CircleCI 2023：CI secrets 輪替壓力" data-link-desc="工程端點入侵後，CI 平台 secrets 如何成為高風險擴散點">CircleCI 2023 Secrets Rotation (red-team)</a></td>
          <td>CI 平台 secret 集中化的 blast radius — Vault AppRole secret_id 散落在 CI runner 時、CI 出事 = 大量 AppRole credential 一次外洩、需 scope tag + 優先級 rotation</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/cases/okta-support-system-incident-2023/" data-link-title="7.C5 Okta：2023 Support System 事件" data-link-desc="支援系統憑證風險如何擴散到客戶租戶的案例。">Okta Support System 2023</a></td>
          <td>對照啟示 — Vault 自己的 support / debug tooling（root token、recovery key）也是 secret leak vector、HAR 級別的事件可發生在任何 admin console</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/secrets-and-machine-credential-governance/" data-link-title="7.6 秘密管理與機器憑證治理" data-link-desc="以問題驅動方式整理 secret、token、key 與機器身份治理">7.6 秘密管理與機器憑證治理</a>、<a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">7.13 偵測覆蓋率與訊號治理</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/aws-secrets-manager/" data-link-title="AWS Secrets Manager" data-link-desc="AWS 原生 secret store &#43; 內建 RDS / Redshift rotation Lambda、Resource Policy 跨帳號共享、KMS 加密">AWS Secrets Manager</a>、<a href="/blog/backend/07-security-data-protection/vendors/google-secret-manager/" data-link-title="Google Secret Manager" data-link-desc="GCP 原生 secret store、CMEK &#43; Workload Identity Federation 整合、rotation 走自寫 Cloud Function 而非 built-in Lambda">Google Secret Manager</a>、<a href="/blog/backend/07-security-data-protection/vendors/azure-key-vault/" data-link-title="Azure Key Vault" data-link-desc="Azure 三合一 service（Secret &#43; Key &#43; Certificate）、整合 Managed Identity &#43; Entra ID RBAC、Premium tier 走 HSM">Azure Key Vault</a></li>
<li>下游：<a href="/blog/backend/07-security-data-protection/vendors/aws-kms/" data-link-title="AWS KMS" data-link-desc="AWS 原生 key management service、envelope encryption / digital signing / Multi-Region Key、Key Policy &#43; Grant 雙軌授權">AWS KMS</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-kms/" data-link-title="Google Cloud KMS" data-link-desc="GCP 原生 key management service、KeyRing / CryptoKey Version 設計、CMEK 整合 &#43; Cloud HSM &#43; External Key Manager">Google Cloud KMS</a>（Vault auto-unseal master key custodian）</li>
<li>下游：<a href="/blog/backend/07-security-data-protection/vendors/cert-manager/" data-link-title="cert-manager" data-link-desc="K8s 原生 certificate lifecycle automation、支援 Let&#39;s Encrypt / Vault PKI / Venafi 等多 issuer、auto-renewal &#43; Challenge solver">cert-manager</a>（用 Vault PKI engine 作為 K8s workload cert issuer）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（Vault 事件如何 routing 進 IR 流程）</li>
<li>官方：<a href="https://developer.hashicorp.com/vault/docs">Vault Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>Okta</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/okta/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/okta/</guid><description>&lt;p>Okta 是 SaaS Identity Provider 的事實標準。它承擔三個責任：human identity 的 SSO 與 MFA、application / cloud account 的 federation gateway、SCIM-based lifecycle 自動化（joiners / movers / leavers）。當公司把 SSO 集中到 Okta、員工的工作信任邊界就從「每個應用各自的密碼」變成「Okta tenant + 客服流程 + signing key」三件事是否安全。在 &lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/capability-buy-vs-build/" data-link-title="0.22 能力級買 vs 建：feature-as-a-service 與 BaaS bundle 選型" data-link-desc="在交付形態決定整個系統要不要自建之後、逐能力判斷該外包還是自建：辨識 managed 基礎設施、feature SaaS 與 BaaS bundle 三種外包深度、no-code 到 dev-tool 的服務光譜、買 vs 建判準與權重浮動、整合接縫與遷出代價">0.22 能力級買 vs 建&lt;/a> 的光譜上、把企業 SSO 交給 Okta 是認證 commodity「買」的代表選擇（feature SaaS 深度）；這個外包深度與遷出代價的權衡見 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/capability-outsourcing-depth/" data-link-title="Capability Outsourcing Depth（外包深度）" data-link-desc="說明外包一塊後端能力有三種深度（managed 基礎設施、feature SaaS、BaaS bundle）、深度決定保留多少控制權與遷出代價">外包深度&lt;/a> 卡。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Okta 是 &lt;em>人類身份的控制面&lt;/em>、不是 cloud resource permission engine。把 cloud IAM（AWS IAM、Google Cloud IAM、Azure RBAC）的角色指派交給 Okta 是常見組合 — Okta 負責「這個人是誰」、雲端 IAM 負責「這個身份能對 resource 做什麼」。Workforce Identity Cloud（員工）跟 Customer Identity Cloud（消費者、原 Auth0）是兩個產品線、安全模型跟事件分布都不同（本頁聚焦 Workforce、Auth0 見 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/auth0/" data-link-title="Auth0" data-link-desc="B2C / B2B Customer Identity Provider、Universal Login、Action / Rule hook、屬 Okta 旗下 Customer Identity Cloud">Auth0 vendor&lt;/a>）。&lt;/p>
&lt;p>跟自管 IdP（&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/keycloak/" data-link-title="Keycloak" data-link-desc="Open source self-hosted Identity Provider、Red Hat 主導、Realm-based multi-tenancy、適合資料主權與自訂 flow 需求">Keycloak&lt;/a>）相比、Okta 把 issuer 信任、signing key 生命週期、support tooling 都託管出去 — 代價是 &lt;em>第三方控制面的事故會直接打到自己&lt;/em>（Okta 2022 Sitel 環境洩漏、2023 support system HAR token 外洩、2023 cross-tenant impersonation）。跟 cloud-native SSO（&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-iam-identity-center/" data-link-title="AWS IAM Identity Center" data-link-desc="AWS 原生 workforce SSO、前 AWS SSO、Permission Set 跨帳號 access、可串外部 IdP federation">AWS IAM Identity Center&lt;/a>）相比、Okta 的核心優勢是 &lt;em>多雲 + SaaS app 數百個 integration 預先建好&lt;/em>、不是綁單一雲廠。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本頁、讀者能判斷：&lt;/p>
&lt;ol>
&lt;li>Okta 該承擔哪一段 identity 控制（SSO / MFA / lifecycle / federation）、哪一段該交給雲端 IAM&lt;/li>
&lt;li>Okta tenant 的信任邊界與最低稽核需求（admin role、API token、SCIM、support workflow）&lt;/li>
&lt;li>Okta 自己出事時的降級路徑（emergency access、break-glass、out-of-band MFA）&lt;/li>
&lt;li>何時用 Okta、何時走 Auth0 / Keycloak / AWS IAM Identity Center 的取捨&lt;/li>
&lt;/ol>
&lt;h2 id="最短判讀路徑">最短判讀路徑&lt;/h2>
&lt;p>判斷 Okta 配置是否健康、最少看四件事：&lt;/p></description><content:encoded><![CDATA[<p>Okta 是 SaaS Identity Provider 的事實標準。它承擔三個責任：human identity 的 SSO 與 MFA、application / cloud account 的 federation gateway、SCIM-based lifecycle 自動化（joiners / movers / leavers）。當公司把 SSO 集中到 Okta、員工的工作信任邊界就從「每個應用各自的密碼」變成「Okta tenant + 客服流程 + signing key」三件事是否安全。在 <a href="/blog/backend/00-service-selection/capability-buy-vs-build/" data-link-title="0.22 能力級買 vs 建：feature-as-a-service 與 BaaS bundle 選型" data-link-desc="在交付形態決定整個系統要不要自建之後、逐能力判斷該外包還是自建：辨識 managed 基礎設施、feature SaaS 與 BaaS bundle 三種外包深度、no-code 到 dev-tool 的服務光譜、買 vs 建判準與權重浮動、整合接縫與遷出代價">0.22 能力級買 vs 建</a> 的光譜上、把企業 SSO 交給 Okta 是認證 commodity「買」的代表選擇（feature SaaS 深度）；這個外包深度與遷出代價的權衡見 <a href="/blog/backend/knowledge-cards/capability-outsourcing-depth/" data-link-title="Capability Outsourcing Depth（外包深度）" data-link-desc="說明外包一塊後端能力有三種深度（managed 基礎設施、feature SaaS、BaaS bundle）、深度決定保留多少控制權與遷出代價">外包深度</a> 卡。</p>
<h2 id="服務定位">服務定位</h2>
<p>Okta 是 <em>人類身份的控制面</em>、不是 cloud resource permission engine。把 cloud IAM（AWS IAM、Google Cloud IAM、Azure RBAC）的角色指派交給 Okta 是常見組合 — Okta 負責「這個人是誰」、雲端 IAM 負責「這個身份能對 resource 做什麼」。Workforce Identity Cloud（員工）跟 Customer Identity Cloud（消費者、原 Auth0）是兩個產品線、安全模型跟事件分布都不同（本頁聚焦 Workforce、Auth0 見 <a href="/blog/backend/07-security-data-protection/vendors/auth0/" data-link-title="Auth0" data-link-desc="B2C / B2B Customer Identity Provider、Universal Login、Action / Rule hook、屬 Okta 旗下 Customer Identity Cloud">Auth0 vendor</a>）。</p>
<p>跟自管 IdP（<a href="/blog/backend/07-security-data-protection/vendors/keycloak/" data-link-title="Keycloak" data-link-desc="Open source self-hosted Identity Provider、Red Hat 主導、Realm-based multi-tenancy、適合資料主權與自訂 flow 需求">Keycloak</a>）相比、Okta 把 issuer 信任、signing key 生命週期、support tooling 都託管出去 — 代價是 <em>第三方控制面的事故會直接打到自己</em>（Okta 2022 Sitel 環境洩漏、2023 support system HAR token 外洩、2023 cross-tenant impersonation）。跟 cloud-native SSO（<a href="/blog/backend/07-security-data-protection/vendors/aws-iam-identity-center/" data-link-title="AWS IAM Identity Center" data-link-desc="AWS 原生 workforce SSO、前 AWS SSO、Permission Set 跨帳號 access、可串外部 IdP federation">AWS IAM Identity Center</a>）相比、Okta 的核心優勢是 <em>多雲 + SaaS app 數百個 integration 預先建好</em>、不是綁單一雲廠。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>Okta 該承擔哪一段 identity 控制（SSO / MFA / lifecycle / federation）、哪一段該交給雲端 IAM</li>
<li>Okta tenant 的信任邊界與最低稽核需求（admin role、API token、SCIM、support workflow）</li>
<li>Okta 自己出事時的降級路徑（emergency access、break-glass、out-of-band MFA）</li>
<li>何時用 Okta、何時走 Auth0 / Keycloak / AWS IAM Identity Center 的取捨</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Okta 配置是否健康、最少看四件事：</p>
<ul>
<li><strong>誰能做什麼</strong>：Super Admin / Org Admin / Read-Only Admin 的人數、是否走 Okta 自己的 access request workflow、是否強制 <a href="/blog/backend/knowledge-cards/authentication/" data-link-title="Authentication" data-link-desc="說明系統如何確認呼叫者身份">phishing-resistant 認證</a></li>
<li><strong>憑證在哪裡</strong>：API token 的 owner、scope、TTL、是否走 OAuth service app 而不是 personal API token；service account 是否獨立 audit</li>
<li><strong>入口如何暴露</strong>：SSO 是 SAML 還是 OIDC、IdP-initiated 是否關閉、admin console 是否限 IP / device trust、helpdesk reset 是否要 callback / out-of-band 驗證</li>
<li><strong>證據是否可回查</strong>：System Log 是否同步到 SIEM、admin / token / impersonation 事件是否 alert、是否保留 90 天以上</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">Audit Log</a> 與 <a href="/blog/backend/knowledge-cards/authorization/" data-link-title="Authorization" data-link-desc="說明授權如何判斷誰能對哪些資源執行哪些操作">Authorization</a> 邊界的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>Onboarding / lifecycle</strong>：HR 系統推 SCIM 進 Okta、Okta 推 SCIM 到下游 SaaS / 雲端 SSO。決策點是 <em>誰是 source of truth</em> — HRIS 還是 Okta 自己。混用會造成 stale account 與例外帳號無法收。</p>
<p><strong>Policy（authentication）</strong>：Sign-On Policy 跟 Authentication Policy（New Policy Framework）兩套並行、要避免規則交疊。高風險操作（admin login、寫權限應用）應該強制 <a href="/blog/backend/knowledge-cards/authentication/" data-link-title="Authentication" data-link-desc="說明系統如何確認呼叫者身份">phishing-resistant</a> factor（WebAuthn / passkey）、不只是 push MFA（Uber 2022 揭露：純 push MFA 抗不過 fatigue）。</p>
<p><strong>MFA factor 選擇</strong>：避免 SMS / voice 作為主要 factor。Okta 2024 把 telephony 推給客戶 BYO（<a href="/blog/backend/07-security-data-protection/cases/okta-byo-telephony-security-shift/" data-link-title="7.C7 Okta：BYO Telephony 的身份安全責任轉換" data-link-desc="MFA 簡訊/語音路徑從平台托管轉向客戶自管的治理案例。">Okta BYO Telephony case</a>）— 信任邊界從「Okta 全管」變成「客戶自己挑簡訊供應商」、若沒同步調整威脅模型會把 SMS swap 風險吃下來。</p>
<p><strong>API token / OAuth service app</strong>：personal API token 容易隨人員離職 stale、應該走 OAuth service app（client credentials）並把 scope 收到最小。token 不存 source code、走 <a href="/blog/backend/knowledge-cards/secret-management/" data-link-title="Secret Management" data-link-desc="說明 token、key、password 與憑證如何保存、輪替與撤銷">Secret Management</a> 取用。</p>
<p><strong>Exception / break-glass</strong>：至少 2 個 break-glass admin、credential 離線存（紙本保險箱 / <a href="/blog/backend/knowledge-cards/secret-management/" data-link-title="Secret Management" data-link-desc="說明 token、key、password 與憑證如何保存、輪替與撤銷">secret management</a> 隔離 tenant）、走獨立 MFA（hardware key、不依賴主要 Okta tenant 的 push）、季度驗證可用。Okta tenant 整個失聯時這是唯一退路。</p>
<p><strong>Audit / handoff</strong>：System Log 推進 SIEM、特別 alert 三類事件 — admin role 變更、API token 建立、impersonation / support access。Okta 2023 support system 事件展示：如果客戶沒 alert support impersonation 的 session、就只能等 Okta 公告。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Okta</th>
          <th>自管 Keycloak</th>
          <th>AWS IAM Identity Center</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>控制面責任</td>
          <td>Okta 託管 issuer / signing / support</td>
          <td>自己跑 issuer、key rotation、HA、support</td>
          <td>AWS 託管、限 AWS 帳號 + 已整合 SAML app</td>
      </tr>
      <tr>
          <td>Integration</td>
          <td>7000+ SaaS app 預建</td>
          <td>OIDC / SAML 通用、specific app 要自己接</td>
          <td>AWS 帳號 + 中等規模 SaaS</td>
      </tr>
      <tr>
          <td>第三方信任成本</td>
          <td>高 — Okta 出事客戶被動受害（2022 / 2023 多起）</td>
          <td>低 — 自管、自己承擔運維</td>
          <td>中 — 綁 AWS 信任邊界</td>
      </tr>
      <tr>
          <td>運維成本</td>
          <td>低 — SaaS</td>
          <td>高 — HA、DR、cert、DB、upgrade 都要顧</td>
          <td>低 — AWS managed</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>多雲、大量 SaaS、需要 lifecycle 自動化</td>
          <td>預算 / 主權 / 自管要求、不接受 SaaS IdP</td>
          <td>AWS-heavy、員工數中等、SaaS 少</td>
      </tr>
      <tr>
          <td>退場成本</td>
          <td>高 — SAML / SCIM 接線分散在數百 app</td>
          <td>中 — 自己掌握資料</td>
          <td>中 — AWS 內部換</td>
      </tr>
  </tbody>
</table>
<p>選 Okta 的核心訴求：<em>跨雲 + 大量 SaaS app + lifecycle 要自動化</em>、且能接受第三方控制面風險、有預算做完整 SIEM / break-glass / 第三方應變流程。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Federation 跟 workload identity</strong>：Okta 對人類 SSO 強、對 workload identity 較弱。CI / 服務間用 <a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM role 的 OIDC trust</a>、<a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google workload identity federation</a> 比把 Okta API token 散到服務裡更安全。</p>
<p><strong>Cross-tenant 邊界</strong>：B2B 合作（partner、contractor）要清楚是「partner 用自己 IdP 做 federation 進來」還是「partner 在我的 Okta tenant 開帳號」。2023 cross-tenant impersonation 事件（<a href="/blog/backend/07-security-data-protection/cases/okta-cross-tenant-impersonation-2023/" data-link-title="7.C6 Okta：Cross-tenant Impersonation 防禦回寫" data-link-desc="跨租戶 impersonation 風險如何轉成身份治理與偵測策略。">Okta Cross-Tenant case</a>）揭示：admin 工具若沒限定 tenant scope、單一 admin compromise 會跨多 tenant 擴散。</p>
<p><strong>Device trust / posture</strong>：Okta Device Trust + EDR signal 是補 phishing-resistant MFA 之後的下一層 — 確認 <em>使用者</em> 對之外、確認 <em>裝置</em> 健康。BYOD 比例高的組織這層做不起來就靠人類因子守。</p>
<p><strong>Identity Threat Protection / ITP</strong>：Okta 2024 推的事件偵測 add-on、補 session anomaly、credential stuffing、impossible travel 等場景。本質是把 SIEM detection 的一部分內建、不是取代外部 SIEM。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Admin account 過多</strong>：經常超過必要 — 用 Group Rules + Access Request workflow 收斂、把日常操作用 Read-Only Admin + 特定權限 group 替代</li>
<li><strong>API token stale / 散落</strong>：personal API token 跟著員工離職留下 — 季度盤點、改 OAuth service app</li>
<li><strong>SMS MFA 還是預設</strong>：MFA enrollment 沒強制 WebAuthn / passkey、新員工選最弱 factor — Authentication Policy 應該限制可選 factor</li>
<li><strong>System Log 沒進 SIEM</strong>：事件只在 Okta UI、alert 沒接 <a href="/blog/backend/knowledge-cards/on-call/" data-link-title="On-Call" data-link-desc="說明值班制度如何承接告警、事故分級與升級流程">on-call</a> — 用 Log Streaming（CloudWatch / S3 / Splunk HEC）打進 SIEM、特定事件接 <a href="/blog/backend/knowledge-cards/alert-runbook/" data-link-title="Alert Runbook" data-link-desc="說明告警如何連到可執行的排障與恢復流程">alert runbook</a></li>
<li><strong>Helpdesk reset 無 callback</strong>：MGM 2023 / Caesars 2023 都是 helpdesk social engineering、需要 callback + out-of-band 驗證、不是 ticket 上看到「我忘記密碼」就 reset</li>
<li><strong>Support 工具 session 沒監控</strong>：Okta 2023 support 事件揭示需要 alert <em>support impersonation session 進入我的 tenant 的事件</em> — System Log 有對應事件、但通常沒 default alert</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Customer / B2C identity</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/auth0/" data-link-title="Auth0" data-link-desc="B2C / B2B Customer Identity Provider、Universal Login、Action / Rule hook、屬 Okta 旗下 Customer Identity Cloud">Auth0 vendor</a></td>
      </tr>
      <tr>
          <td>自管 / 不接受 SaaS IdP</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/keycloak/" data-link-title="Keycloak" data-link-desc="Open source self-hosted Identity Provider、Red Hat 主導、Realm-based multi-tenancy、適合資料主權與自訂 flow 需求">Keycloak vendor</a></td>
      </tr>
      <tr>
          <td>AWS-only 員工 SSO</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/aws-iam-identity-center/" data-link-title="AWS IAM Identity Center" data-link-desc="AWS 原生 workforce SSO、前 AWS SSO、Permission Set 跨帳號 access、可串外部 IdP federation">AWS IAM Identity Center</a></td>
      </tr>
      <tr>
          <td>Microsoft 365 / Azure 重度組織</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/azure-rbac/" data-link-title="Azure RBAC &#43; Entra ID" data-link-desc="Azure 雙層身份/權限體系、Entra ID（IdP）&#43; Azure RBAC（resource permission）、Conditional Access、PIM、Managed Identity">Entra ID（Azure RBAC vendor 頁）</a> — Entra ID 是 Microsoft 自家 workforce IdP、跟 Okta 直接競爭、M365 + Azure 為主的組織通常直接用 Entra ID 而非疊一層 Okta</td>
      </tr>
      <tr>
          <td>Cloud resource permission（非人類身份）</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google IAM</a> / <a href="/blog/backend/07-security-data-protection/vendors/azure-rbac/" data-link-title="Azure RBAC &#43; Entra ID" data-link-desc="Azure 雙層身份/權限體系、Entra ID（IdP）&#43; Azure RBAC（resource permission）、Conditional Access、PIM、Managed Identity">Azure RBAC</a></td>
      </tr>
      <tr>
          <td>事件偵測（不只 Okta 內部）</td>
          <td>04 SIEM / detection 工具（<a href="/blog/backend/04-observability/" data-link-title="模組四：可觀測性平台" data-link-desc="整理 log、metric、trace、dashboard 與 alert 的後端操作實務">04 observability</a> 跟 07 SIEM 章節）</td>
      </tr>
      <tr>
          <td>Secret / API key 治理</td>
          <td><a href="/blog/backend/07-security-data-protection/secrets-and-machine-credential-governance/" data-link-title="7.6 秘密管理與機器憑證治理" data-link-desc="以問題驅動方式整理 secret、token、key 與機器身份治理">7.6 秘密管理與機器憑證治理</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Okta 完整 SAML / OIDC 規格細節、SCIM schema 客製</li>
<li>Workforce vs Customer Identity Cloud 完整功能對照</li>
<li>Okta 各定價層級的功能差異</li>
<li>各 SaaS app 的 SSO 接線教學</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 Okta 的關係</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/cases/okta-support-system-incident-2023/" data-link-title="7.C5 Okta：2023 Support System 事件" data-link-desc="支援系統憑證風險如何擴散到客戶租戶的案例。">Okta Support System Incident 2023</a></td>
          <td>支援工具鏈納入身份治理、HAR session 透過個人 Chrome profile 同步外洩、客戶側必須 alert impersonation session</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/cases/okta-cross-tenant-impersonation-2023/" data-link-title="7.C6 Okta：Cross-tenant Impersonation 防禦回寫" data-link-desc="跨租戶 impersonation 風險如何轉成身份治理與偵測策略。">Okta Cross-Tenant Impersonation 2023</a></td>
          <td>admin tool 缺 tenant scope、單一 admin compromise 跨 tenant 擴散</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/cases/okta-byo-telephony-security-shift/" data-link-title="7.C7 Okta：BYO Telephony 的身份安全責任轉換" data-link-desc="MFA 簡訊/語音路徑從平台托管轉向客戶自管的治理案例。">Okta BYO Telephony Shift</a></td>
          <td>telephony 供應商責任轉移、客戶要重新評估 SMS 路徑威脅模型</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/cloudflare-2023-okta-token-follow-through/" data-link-title="7.R7.1.6 Cloudflare 2023：供應商事件後的身分收斂" data-link-desc="同一條供應商事件鏈，如何在客戶端變成 session 與 token 的收斂壓力">Cloudflare 2023 Okta Token Follow-Through</a></td>
          <td>上游 IdP 事件後客戶側的 token / session rotation 節奏、不該等供應商公告</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/uber-2022-mfa-fatigue/" data-link-title="7.R7.1.1 Uber 2022：MFA 疲勞與內部工具擴散" data-link-desc="從社交工程到內部工具存取，拆解身分流程與權限邊界的失效點">Uber 2022 MFA Fatigue</a></td>
          <td>純 push MFA 抗不過 fatigue、高風險操作要求 phishing-resistant factor</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/mgm-2023-identity-lateral-impact/" data-link-title="7.R7.1.4 MGM 2023：身分流程被打穿後的營運中斷" data-link-desc="社交工程造成身分邊界失守後，如何演變成可用性與營運衝擊">MGM 2023 Identity Lateral Impact</a></td>
          <td>helpdesk social engineering 是 Okta-customer 通用入口、callback / out-of-band 驗證是控制面</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/twilio-2022-social-engineering/" data-link-title="7.R7.1.3 Twilio 2022：社交工程與員工帳號路徑" data-link-desc="社交工程如何穿透員工身分流程，並影響下游客戶與供應鏈">Twilio 2022 Social Engineering</a></td>
          <td>員工身份即客戶風險面、IdP 對員工帳號異常的隔離速度決定下游受損規模</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/cases/failure-credential-rotation-without-scope/" data-link-title="7.C9 反例：憑證輪替未分 Scope" data-link-desc="憑證輪替若未分域分批，容易造成跨系統連鎖中斷。">Failure: Credential Rotation Without Scope</a></td>
          <td>Okta API token / OAuth service app credential 的 rotation 必須分域、不能把多 service app 共用同一批 rotation 命令打</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/identity-access-boundary/" data-link-title="7.2 身分與授權邊界" data-link-desc="以問題驅動方式整理身分、授權、會話與供應商身分鏈">7.2 身分與授權邊界</a>、<a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">7.13 偵測覆蓋率與訊號治理</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/auth0/" data-link-title="Auth0" data-link-desc="B2C / B2B Customer Identity Provider、Universal Login、Action / Rule hook、屬 Okta 旗下 Customer Identity Cloud">Auth0 vendor</a>、<a href="/blog/backend/07-security-data-protection/vendors/keycloak/" data-link-title="Keycloak" data-link-desc="Open source self-hosted Identity Provider、Red Hat 主導、Realm-based multi-tenancy、適合資料主權與自訂 flow 需求">Keycloak vendor</a>、<a href="/blog/backend/07-security-data-protection/vendors/aws-iam-identity-center/" data-link-title="AWS IAM Identity Center" data-link-desc="AWS 原生 workforce SSO、前 AWS SSO、Permission Set 跨帳號 access、可串外部 IdP federation">AWS IAM Identity Center</a></li>
<li>下游：<a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google Cloud IAM</a> / <a href="/blog/backend/07-security-data-protection/vendors/azure-rbac/" data-link-title="Azure RBAC &#43; Entra ID" data-link-desc="Azure 雙層身份/權限體系、Entra ID（IdP）&#43; Azure RBAC（resource permission）、Conditional Access、PIM、Managed Identity">Azure RBAC</a>（Okta 之後的 cloud resource permission 層）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（Okta 事件如何 routing 進 IR 流程）</li>
<li>官方：<a href="https://help.okta.com/">Okta Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>Splunk</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/splunk/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/splunk/</guid><description>&lt;p>Splunk 是 SIEM（Security Information and Event Management）的事實標準、大企業 / 金融 / 政府的 SOC 主流選擇。2024 年被 Cisco 收購、產品線維持獨立發展。它跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &amp;#43; EDR &amp;#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &amp;#43; CSPM &amp;#43; CWS &amp;#43; AAP &amp;#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Security&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/google-security-operations/" data-link-title="Google Security Operations" data-link-desc="Google 雲原生 SIEM &amp;#43; SOAR &amp;#43; Mandiant threat intel 三合一（前 Chronicle）、UDM &amp;#43; YARA-L、fixed-price by data tier、PB-scale 友善">Google Security Operations&lt;/a> 的差異在 &lt;em>計費模型 + ecosystem maturity + detection content 深度&lt;/em>、偵測能力本身相近 — Splunk 的 ingestion-based pricing 是業界最貴的 SIEM 計費模式、但 detection content 跟 SOC tooling ecosystem 也是最成熟的。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Splunk 的核心定位是 &lt;em>任意 log source 的統一查詢平台&lt;/em>、SIEM 是其上的 &lt;em>application layer&lt;/em>（Splunk Enterprise Security app）。底層是 &lt;em>Splunk Enterprise&lt;/em>（自管）或 &lt;em>Splunk Cloud Platform&lt;/em>（SaaS）、頂層產品包含：&lt;em>Enterprise Security (ES)&lt;/em> — premium SIEM app、含 correlation rule、Risk-Based Alerting、ITSI 整合；&lt;em>SOAR&lt;/em>（前 Phantom）— security orchestration / automated response；&lt;em>UBA&lt;/em>（User Behavior Analytics）— ML-based anomaly detection。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &amp;#43; EDR &amp;#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security&lt;/a> 比、Splunk 走 &lt;em>deeper but more expensive&lt;/em> — SPL 比 KQL / EQL 表達力更強、detection content（Splunk Security Content 公開 YAML rules）覆蓋廣、ES app 的 Risk-Based Alerting 是業界先驅；但 ingestion-based pricing 在 TB/day 級別會痛。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &amp;#43; CSPM &amp;#43; CWS &amp;#43; AAP &amp;#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Security&lt;/a> 比、Splunk 走 &lt;em>security-first&lt;/em>、Datadog Cloud SIEM 是 &lt;em>observability platform 加上 security view&lt;/em>；Datadog 適合 cloud-native + 中等規模、Splunk 適合 enterprise + 跨 on-prem。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/google-security-operations/" data-link-title="Google Security Operations" data-link-desc="Google 雲原生 SIEM &amp;#43; SOAR &amp;#43; Mandiant threat intel 三合一（前 Chronicle）、UDM &amp;#43; YARA-L、fixed-price by data tier、PB-scale 友善">Google Security Operations&lt;/a>（前 Chronicle）比、Google Security Ops 走 &lt;em>fixed-price by data、massive scale&lt;/em>、Splunk 是 &lt;em>per-GB 累進&lt;/em>、超大規模反而 Google 划算。&lt;/p></description><content:encoded><![CDATA[<p>Splunk 是 SIEM（Security Information and Event Management）的事實標準、大企業 / 金融 / 政府的 SOC 主流選擇。2024 年被 Cisco 收購、產品線維持獨立發展。它跟 <a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a> / <a href="/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &#43; CSPM &#43; CWS &#43; AAP &#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Security</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-security-operations/" data-link-title="Google Security Operations" data-link-desc="Google 雲原生 SIEM &#43; SOAR &#43; Mandiant threat intel 三合一（前 Chronicle）、UDM &#43; YARA-L、fixed-price by data tier、PB-scale 友善">Google Security Operations</a> 的差異在 <em>計費模型 + ecosystem maturity + detection content 深度</em>、偵測能力本身相近 — Splunk 的 ingestion-based pricing 是業界最貴的 SIEM 計費模式、但 detection content 跟 SOC tooling ecosystem 也是最成熟的。</p>
<h2 id="服務定位">服務定位</h2>
<p>Splunk 的核心定位是 <em>任意 log source 的統一查詢平台</em>、SIEM 是其上的 <em>application layer</em>（Splunk Enterprise Security app）。底層是 <em>Splunk Enterprise</em>（自管）或 <em>Splunk Cloud Platform</em>（SaaS）、頂層產品包含：<em>Enterprise Security (ES)</em> — premium SIEM app、含 correlation rule、Risk-Based Alerting、ITSI 整合；<em>SOAR</em>（前 Phantom）— security orchestration / automated response；<em>UBA</em>（User Behavior Analytics）— ML-based anomaly detection。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a> 比、Splunk 走 <em>deeper but more expensive</em> — SPL 比 KQL / EQL 表達力更強、detection content（Splunk Security Content 公開 YAML rules）覆蓋廣、ES app 的 Risk-Based Alerting 是業界先驅；但 ingestion-based pricing 在 TB/day 級別會痛。跟 <a href="/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &#43; CSPM &#43; CWS &#43; AAP &#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Security</a> 比、Splunk 走 <em>security-first</em>、Datadog Cloud SIEM 是 <em>observability platform 加上 security view</em>；Datadog 適合 cloud-native + 中等規模、Splunk 適合 enterprise + 跨 on-prem。跟 <a href="/blog/backend/07-security-data-protection/vendors/google-security-operations/" data-link-title="Google Security Operations" data-link-desc="Google 雲原生 SIEM &#43; SOAR &#43; Mandiant threat intel 三合一（前 Chronicle）、UDM &#43; YARA-L、fixed-price by data tier、PB-scale 友善">Google Security Operations</a>（前 Chronicle）比、Google Security Ops 走 <em>fixed-price by data、massive scale</em>、Splunk 是 <em>per-GB 累進</em>、超大規模反而 Google 划算。</p>
<p>關鍵張力：<em>ingestion-based 計費</em> ↔ <em>偵測覆蓋率</em> 是 Splunk 客戶最大的 trade-off。為了省錢選擇性 ingest log（只進 Windows Event Log 不進 Linux auth log、只進 prod 不進 dev）、結果 Storm-0558 / Uber MFA 那種跨來源 correlation 抓不到。要看清楚自己 <em>容忍多少偵測盲點換多少預算</em>。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>Splunk 在 SOC stack 中承擔哪一段（log aggregation / SIEM / SOAR / UBA）、哪些要外接（<a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a> 管 service token、IdP log 來源治理）</li>
<li>SPL / correlation rule / detection content 的 ownership 設計（誰寫、誰 review、誰調 false positive）</li>
<li>Ingestion pricing trap 的應對（log priority tiering、Cribl / Cribl Stream 做 pre-filter、Splunk SmartStore 把冷資料丟 S3）</li>
<li>何時用 Splunk、何時走 Elastic / Datadog / Google Security Ops 的取捨</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Splunk deployment 是否健康、最少看四件事：</p>
<ul>
<li><strong>誰能改 correlation rule</strong>：Splunk admin / ES admin / KV store admin 的人數、SPL search 跟 saved search 是否走版控（Git → <code>git-fusion</code> / Splunk Cloud Versioned Configs）、rule change 是否經 PR review</li>
<li><strong>Ingestion 治理</strong>：哪些 source 進 Splunk（IdP audit log / cloud control plane log / endpoint log / network log / app log）、是否有 <em>log priority tier</em>（critical / standard / archive）、Cribl Stream 是否在前面做 pre-filter / routing</li>
<li><strong>Detection content coverage</strong>：Splunk Security Content（<a href="https://research.splunk.com/">公開 YAML rule library</a>）有多少 enabled、是否跟 MITRE ATT&amp;CK 對照、自家 custom rule 是否補 organization-specific anti-pattern</li>
<li><strong>Alert quality / SOC handoff</strong>：alert volume per day、SOC analyst triage time、false positive rate、alert 是否進 SOAR playbook 自動處理低風險、跟 <a href="/blog/backend/08-incident-response/" data-link-title="模組八：事故處理與復盤" data-link-desc="用 IR 領域詞彙建問題節點、以服務級案例庫累積事故脈絡，先建概念與案例庫再進實作交接">8 incident response</a> 的 routing 是否定義</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">Detection Coverage and Signal Governance</a> 邊界的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>Ingestion architecture</strong>：log 進 Splunk 三種路徑 — <em>Universal Forwarder</em> / <em>Heavy Forwarder</em>（agent-based，自管 host）、<em>HTTP Event Collector (HEC)</em>（push log via HTTP endpoint、SaaS / serverless workload 預設）、<em>Splunk Add-on for 各 cloud / SaaS</em>（cloud-native log pull）。production 通常混用：endpoint 用 Universal Forwarder、cloud control plane 用 Add-on（AWS / GCP / Azure / Okta）、自家 app 用 HEC。在前面接 <em>Cribl Stream</em> 做 routing / filtering / sampling 是大型 deployment 的標準補位。</p>
<p><strong>SPL（Search Processing Language）</strong>：類 Unix pipe 的 <code>|</code> 串接（<code>index=ids sourcetype=auth | stats count by user | where count &gt; 100</code>）、表達力強但學習曲線陡。SPL 是 first-class concept、不只是查詢工具 — saved search 變 correlation rule、scheduled search 變 alert、accelerated search 變 data model 加速。SPL 寫得好不好直接決定 <em>偵測規則品質 + 查詢成本</em>。</p>
<p><strong>Correlation rule / Notable Event</strong>：ES app 把 high-confidence finding 轉成 <em>Notable Event</em>、進 Incident Review queue。Correlation rule 的反例是 <em>single-event alert</em>（看到一個 SSH brute force attempt 就 alert、SOC analyst 一天看 10000 個沒意義）— production rule 應該是 <em>time-bounded aggregation</em>（過去 5min 內 100 個 brute force from same IP）+ <em>cross-source correlation</em>（brute force IP 同時出現在 cloud control plane access）。</p>
<p><strong>Detection content lifecycle</strong>：Splunk Security Content 是 Splunk 維護的 OSS detection rule library、YAML format、跟 MITRE ATT&amp;CK 對應。組織通常 <em>先 import 全部 baseline、再選擇性 disable noisy 規則 + 新增 organization-specific 規則</em>。Rule change 走 PR review、staging tenant 跑 24-48hr 觀察 false positive curve 才 promote 到 production。對應 <a href="/blog/backend/07-security-data-protection/blue-team/detection-engineering-lifecycle/" data-link-title="7.B5 Detection Engineering Lifecycle" data-link-desc="把偵測規則視為可維護資產，建立從來源、測試、調校到退場的完整生命週期">Detection Engineering Lifecycle</a> 的章節原則。</p>
<p><strong>Risk-Based Alerting (RBA)</strong>：ES app 7.0+ 引入、給每個 user / asset 累積 <em>risk score</em>（取代逐 finding alert）、累積到 threshold 才 alert。處理 alert fatigue 的工程化做法：5 個 low-confidence signal 加總超過 threshold 比單一 high-confidence alert 更接近真實 attack pattern。對應 <a href="/blog/backend/07-security-data-protection/blue-team/alert-fatigue-and-signal-quality/" data-link-title="7.B10 Alert Fatigue and Signal Quality" data-link-desc="建立告警疲勞治理方法，讓訊號品質、分級一致性與處置效率同步提升">Alert Fatigue and Signal Quality</a>。</p>
<p><strong>SOAR integration</strong>：Splunk SOAR（前 Phantom）接 alert + playbook 自動執行 — 例如 leaked credential 自動 rotate（拉 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a> API）、suspect IP 自動加 firewall block（拉 <a href="/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &#43; DDoS &#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF</a> custom rule）、suspect user 自動 force MFA re-enroll（拉 <a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a> API）。playbook 進版控、定期 dry-run、不能黑箱 production fire-and-forget。</p>
<p><strong>Ingestion pricing 治理</strong>：Splunk 按 ingestion volume（GB/day）計費、TB-scale deployment 年費千萬美元級別。實務治理：<em>tier 1 log</em>（IdP / cloud control plane / payment processor / DB audit）進 Splunk hot index、<em>tier 2 log</em>（app log / web access log）按 sampling / filtering 進 Splunk、<em>tier 3 log</em>（debug / verbose）走 <a href="https://docs.splunk.com/Documentation/Splunk/latest/Indexer/AboutSmartStore">SmartStore</a> 到 S3 / GCS 冷儲存、或繞過 Splunk 直接打到 Elastic / data lake。Cribl Stream 在 forwarder 前 pre-filter 是業界標準作法、可省 30-50% ingestion cost。</p>
<p><strong>SmartStore 跟冷熱分離</strong>：SmartStore 把 indexer 的 <em>warm + cold bucket</em> 放到 S3 / Azure Blob / GCS、indexer 只保留 hot data + cache。意義是 <em>retention 從幾個月延長到幾年但 cost 不線性漲</em>。production deployment 幾乎都該開、不開等於每年砸錢買 EBS。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Splunk</th>
          <th>Elastic Security</th>
          <th>Datadog Security</th>
          <th>Google Security Operations</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>計費模型</td>
          <td>Ingestion-based（GB/day、累進）</td>
          <td>Resource-based（node / cluster size）</td>
          <td>Per-host + per-event（events/month）</td>
          <td>Fixed price by data tier（PB-scale 划算）</td>
      </tr>
      <tr>
          <td>學習曲線</td>
          <td>陡 — SPL 表達力強但 idiom 多</td>
          <td>中 — KQL / EQL 較直觀</td>
          <td>緩 — 沿用 Datadog observability 語法</td>
          <td>中 — YARA-L 是新語法但結構清楚</td>
      </tr>
      <tr>
          <td>部署模型</td>
          <td>Self-hosted (Splunk Enterprise) / SaaS (Cloud)</td>
          <td>Self-hosted / Elastic Cloud / Serverless</td>
          <td>SaaS only</td>
          <td>SaaS only（Google Cloud）</td>
      </tr>
      <tr>
          <td>Detection content</td>
          <td>Splunk Security Content（最豐富、社群活躍）</td>
          <td>Elastic Prebuilt rules + Sigma 支援</td>
          <td>Datadog Security Rules（中等）</td>
          <td>Google YARA-L 內建 + Google threat intel</td>
      </tr>
      <tr>
          <td>SOAR / Response</td>
          <td>Splunk SOAR（前 Phantom、業界先驅）</td>
          <td>內建 Cases + Endpoint response（Elastic Defend）</td>
          <td>Workflow Automation（基本）</td>
          <td>SOAR 內建（前 Siemplify）</td>
      </tr>
      <tr>
          <td>跨來源 correlation</td>
          <td>強 — data model + SPL 支撐</td>
          <td>強 — EQL sequence + Lucene</td>
          <td>中 — log + metrics + trace 同 plane</td>
          <td>強 — UDM normalization + cross-tenant</td>
      </tr>
      <tr>
          <td>Multi-cloud</td>
          <td>強 — Add-on 覆蓋三大雲</td>
          <td>強 — Beats / Agent 跨雲</td>
          <td>強 — Datadog Agent 跨雲</td>
          <td>GCP-first、跨雲靠 Forwarder</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>Enterprise + 跨 on-prem / 多雲、預算允許</td>
          <td>OSS-friendly、中大型、Elastic stack 已用</td>
          <td>Cloud-native、observability 已用 Datadog</td>
          <td>超大規模 ingestion、Google 雲 + 多雲 SOC</td>
      </tr>
      <tr>
          <td>退場成本</td>
          <td>高 — SPL / detection content / dashboard 量多</td>
          <td>中 — Sigma / Lucene 較可移植</td>
          <td>中</td>
          <td>中</td>
      </tr>
  </tbody>
</table>
<p>選 Splunk 的核心訴求：<em>Enterprise scale + 跨 on-prem + detection content 跟 SOC tooling ecosystem 成熟</em>、且能投入預算（千萬美元級別 license + Cribl pre-filter + SmartStore 冷儲存治理）+ 有 SOC team 維護 correlation rule 跟 SOAR playbook。中等規模 cloud-native 直接走 Datadog / Google Security Ops 更划算。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Enterprise Security app 的 Risk-Based Alerting</strong>：RBA 把「事件 → alert」改成「事件 → risk score → 累積 → alert」、是 alert fatigue 的工程化解法。實作要決定 <em>risk decay window</em>（多久後 risk score 衰減）、<em>risk attribution</em>（同一台 EC2 上多 user 的 risk 怎麼分）、<em>per-asset vs per-user threshold</em>。配對 <a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/uber-2022-mfa-fatigue/" data-link-title="7.R7.1.1 Uber 2022：MFA 疲勞與內部工具擴散" data-link-desc="從社交工程到內部工具存取，拆解身分流程與權限邊界的失效點">Uber 2022 MFA Fatigue</a> 的 lesson：單一 MFA fail 不該 alert、5min 內 50 個 fail + 新裝置 + 異常地理就是 high risk。</p>
<p><strong>Common Information Model (CIM) + Data Model</strong>：Splunk CIM 把不同 source 的欄位 normalize 到統一 schema（authentication / network_traffic / web 等 data model）。意義是 SPL 跨 source 寫一次、不用為 Okta log / Azure AD log / CrowdStrike log 各寫一份。CIM 配合 Add-on 自動 mapping、organization 寫 custom source 需要自己定 CIM mapping。</p>
<p><strong>Multi-tenant deployment</strong>：MSSP / 大型集團多 BU 共用一個 Splunk 部署、用 <em>index</em>（隔離 data）+ <em>role / capability</em>（隔離 access）+ <em>App</em>（隔離 dashboard / search）三層。注意 <em>Splunk admin</em> 在跨 tenant 場景是高權限角色、應該走 break-glass 流程 + audit。</p>
<p><strong>Cisco 整合（2024+）</strong>：Cisco 收購後 Splunk 跟 Cisco XDR / Talos threat intel / Cisco Secure Endpoint 整合加速。對 Cisco-heavy 環境是 ecosystem 一致性增加；對非 Cisco 環境暫時影響有限、但長期 roadmap 會有 Cisco-specific 加值。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Alert volume 爆炸 / SOC 看不完</strong>：correlation rule 寫成 single-event alert、或 false positive baseline 沒調 — 用 RBA 改 risk-based、staging tenant 跑 48hr 觀察再 promote</li>
<li><strong>Detection coverage 出事故時才發現缺</strong>：critical log source 沒進 Splunk（為了省錢）— 補回 tier 1 log priority、用 Cribl Stream 對 tier 2 / 3 做 sampling 而非整批不 ingest</li>
<li><strong>Ingestion cost 暴衝</strong>：新 source 加入沒 review、debug log 直接打進 Splunk — Cribl Stream 前置 + license usage dashboard alert + indexer ingestion quota</li>
<li><strong>SPL search 慢 / 卡 search head</strong>：full-fidelity search on 1TB raw event、沒用 data model acceleration — 改用 accelerated data model、限定 time range、用 <code>tstats</code> 而非 <code>stats</code></li>
<li><strong>Correlation rule false positive 多</strong>：rule 寫得太寬、env-specific noise 沒 tune — staging tenant 跑 1 週統計 FP、tune threshold、加 lookup table 排除已知合法 source</li>
<li><strong>SOAR playbook 黑箱 fire-and-forget</strong>：自動 disable account 結果誤殺 CEO — playbook 走 <em>approval gate</em> for high-impact action、defaults to <em>containment</em> not <em>deletion</em></li>
<li><strong>Splunk admin 太多 / 沒 break-glass</strong>：日常運維用 admin token、admin compromise blast radius 太大 — 收 admin 角色、改 power user + 特定 capability、break-glass 走 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a></li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>OSS-friendly / 預算敏感</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a></td>
      </tr>
      <tr>
          <td>Cloud-native + observability 已用</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &#43; CSPM &#43; CWS &#43; AAP &#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Security</a></td>
      </tr>
      <tr>
          <td>超大規模 ingestion + Google 雲</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/google-security-operations/" data-link-title="Google Security Operations" data-link-desc="Google 雲原生 SIEM &#43; SOAR &#43; Mandiant threat intel 三合一（前 Chronicle）、UDM &#43; YARA-L、fixed-price by data tier、PB-scale 友善">Google Security Operations</a></td>
      </tr>
      <tr>
          <td>DLP / sensitive data discovery</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/google-dlp/" data-link-title="Google DLP" data-link-desc="GCP 原生 Sensitive Data Protection：infoType discovery &#43; transformation (mask / FPE / tokenize / k-anonymity)、整合 BigQuery / GCS / Cloud SQL">Google DLP</a> / <a href="/blog/backend/07-security-data-protection/vendors/microsoft-purview/" data-link-title="Microsoft Purview" data-link-desc="Microsoft 跨 M365 / Azure / endpoint 的 data governance &#43; information protection &#43; DLP &#43; insider risk 統合平台、label-driven">Microsoft Purview</a></td>
      </tr>
      <tr>
          <td>Endpoint detection 為主</td>
          <td>CrowdStrike Falcon / Microsoft Defender for Endpoint</td>
      </tr>
      <tr>
          <td>Pre-filter / log routing</td>
          <td>Cribl Stream（前置 forwarder、不是替代 SIEM）</td>
      </tr>
      <tr>
          <td>Incident routing</td>
          <td><a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>SPL 完整語法 reference、saved search 跟 macro 進階用法</li>
<li>Splunk Cloud Platform vs Splunk Enterprise 的功能對照細節</li>
<li>Splunk Observability Cloud（前 SignalFx 收購、跟 Datadog 直接競爭、屬 observability 不屬 security）</li>
<li>ITSI（IT Service Intelligence）— 屬 ITSM / observability、不在資安範圍</li>
<li>SOAR playbook 的具體實作（Phantom Python SDK）</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>Splunk 在 07 案例庫沒有直接 vendor-level 事件、但所有 detection-related case 都是 SIEM 偵測覆蓋率的對照：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 Splunk 的關係（對照啟示）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/uber-2022-mfa-fatigue/" data-link-title="7.R7.1.1 Uber 2022：MFA 疲勞與內部工具擴散" data-link-desc="從社交工程到內部工具存取，拆解身分流程與權限邊界的失效點">Uber 2022 MFA Fatigue</a></td>
          <td>MFA 請求密度應是 Splunk correlation rule first-class signal、5min window count &gt; N 直接 alert + RBA 升級高風險 user score</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/microsoft-storm-0558-2023-signing-key-chain/" data-link-title="7.R7.1.5 Microsoft Storm-0558 2023：簽章金鑰鏈與郵件存取" data-link-desc="從簽章金鑰保護失效到雲端郵件存取，拆解身分信任鏈的關鍵控制點">Microsoft Storm-0558 Signing Key Chain</a></td>
          <td>跨租戶 token 異常驗證需 Splunk Add-on for Azure AD + cloud control plane log 同時 ingest、跨來源 correlation 才能秒級偵測</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/data-exfiltration/snowflake-2024-credential-abuse/" data-link-title="7.R7.4.2 Snowflake 2024：憑證濫用與資料竊取" data-link-desc="外洩憑證與 MFA 缺口如何在資料平台形成高風險外送事件">Snowflake 2024 Credential Abuse</a></td>
          <td>資料平台 query volume + 跨 schema scan + 來源 IP 異常的複合 correlation rule、不只看 audit log 也要 query metrics correlation</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/solarwinds-2020-sunburst/" data-link-title="7.R7.2.1 SolarWinds 2020：更新鏈被濫用" data-link-desc="合法更新流程遭植入後，攻擊者如何長期潛伏與橫向擴散">SolarWinds 2020 Sunburst</a></td>
          <td>簽章驗證通過但 runtime 行為異常需 endpoint log + network log correlation、不靠 IoC-only 規則</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/blue-team/detection-engineering-lifecycle/" data-link-title="7.B5 Detection Engineering Lifecycle" data-link-desc="把偵測規則視為可維護資產，建立從來源、測試、調校到退場的完整生命週期">Detection Engineering Lifecycle (section)</a></td>
          <td>Splunk Security Content + 自家 custom rule 走 propose → staging tune → promote → review 的工程 lifecycle、不是 console 直改</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/blue-team/alert-fatigue-and-signal-quality/" data-link-title="7.B10 Alert Fatigue and Signal Quality" data-link-desc="建立告警疲勞治理方法，讓訊號品質、分級一致性與處置效率同步提升">Alert Fatigue and Signal Quality (section)</a></td>
          <td>RBA 是工程化解 alert fatigue、不是「忽略低風險」、要設 risk decay + threshold tuning lifecycle</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">7.13 偵測覆蓋率與訊號治理</a>、<a href="/blog/backend/07-security-data-protection/blue-team/detection-engineering-lifecycle/" data-link-title="7.B5 Detection Engineering Lifecycle" data-link-desc="把偵測規則視為可維護資產，建立從來源、測試、調校到退場的完整生命週期">Detection Engineering Lifecycle</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a>、<a href="/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &#43; CSPM &#43; CWS &#43; AAP &#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Security</a>、<a href="/blog/backend/07-security-data-protection/vendors/google-security-operations/" data-link-title="Google Security Operations" data-link-desc="Google 雲原生 SIEM &#43; SOAR &#43; Mandiant threat intel 三合一（前 Chronicle）、UDM &#43; YARA-L、fixed-price by data tier、PB-scale 友善">Google Security Operations</a></li>
<li>下游：<a href="/blog/backend/07-security-data-protection/vendors/google-dlp/" data-link-title="Google DLP" data-link-desc="GCP 原生 Sensitive Data Protection：infoType discovery &#43; transformation (mask / FPE / tokenize / k-anonymity)、整合 BigQuery / GCS / Cloud SQL">Google DLP</a> / <a href="/blog/backend/07-security-data-protection/vendors/microsoft-purview/" data-link-title="Microsoft Purview" data-link-desc="Microsoft 跨 M365 / Azure / endpoint 的 data governance &#43; information protection &#43; DLP &#43; insider risk 統合平台、label-driven">Microsoft Purview</a>（DLP signal 進 Splunk）</li>
<li>跨類：<a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a>（IdP log source）、<a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a>（SOAR playbook 拉 API）、<a href="/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &#43; DDoS &#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF</a>（WAF log + auto-block）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（Notable Event → IR routing）、<a href="/blog/backend/04-observability/" data-link-title="模組四：可觀測性平台" data-link-desc="整理 log、metric、trace、dashboard 與 alert 的後端操作實務">4 observability</a>（log pipeline 共用）</li>
<li>官方：<a href="https://docs.splunk.com/">Splunk Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>k6</title><link>https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/k6/</link><pubDate>Fri, 15 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/k6/</guid><description>&lt;p>k6 的核心責任是把 workload model 轉成可重跑、可版本化、可接到 CI 的壓測 scenario。它適合 API、HTTP、gRPC、WebSocket 與 browser-style flow 的負載驗證，重點在用程式化腳本描述使用者行為、負載階段、threshold 與結果輸出。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>k6 是 Grafana Labs 旗下的 scriptable load testing 工具、2021 年被 Grafana 收購。產品線分兩層：&lt;em>k6 OSS&lt;/em>（Go 寫的 engine + JS API 描述 scenario、CLI 為主、output 可丟 Prometheus / InfluxDB / JSON / CSV）跟 &lt;em>Grafana Cloud k6&lt;/em>（前 k6 Cloud、SaaS 多 region runner + 結果保存 + 跟 Grafana Cloud dashboard / Loki / Tempo 同 plane）。底層 engine 是 Go、不是 JS — JS 只是 scenario 描述層、runtime 由 Go 跑、所以單機 VU 容量比 Python-based 工具高出一個量級。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/jmeter/" data-link-title="Apache JMeter" data-link-desc="用 GUI、plugin 與多 protocol sampler 承接企業壓測資產的效能工程工具">JMeter&lt;/a> 比、k6 走 &lt;em>code-first + CI-friendly&lt;/em>、JMeter 走 &lt;em>XML / GUI + plugin ecosystem&lt;/em>；JMeter 在 protocol 廣度（JDBC / LDAP / JMS / FTP）跟非工程團隊操作勝出、k6 在版控、PR review、artifact pipeline 勝出。跟 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/locust/" data-link-title="Locust" data-link-desc="用 Python user behavior 與 distributed worker 表達高自訂負載模型的效能工程工具">Locust&lt;/a> 比、k6 用 JS、Locust 用 Python；Locust 對 Python team 自然、但 Python GIL 讓單機 VU 容量受限、需多 worker、k6 單機可跑數千 VU。跟 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/gatling/" data-link-title="Gatling" data-link-desc="用 JVM DSL、simulation 與 injection profile 表達複雜 scenario 的效能工程工具">Gatling&lt;/a> 比、Gatling 走 JVM + Scala/Java/Kotlin DSL、適合 JVM-heavy 團隊；k6 的 threshold + Grafana ecosystem 整合在 release gate 場景更直接。&lt;/p>
&lt;h2 id="定位">定位&lt;/h2>
&lt;p>k6 適合把壓測納入工程流程。當團隊已經能描述 traffic shape、endpoint mix、arrival rate、think time 與 stop condition，k6 可以把這些模型寫成腳本，讓每次 release、capacity review 或 peak-event readiness 都能重跑同一組驗證。&lt;/p>
&lt;p>這個定位讓 k6 接到三個主章。它從 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/workload-modeling/" data-link-title="9.2 Workload Modeling" data-link-desc="把 production traffic shape 翻成可重播的壓測模型">9.2 Workload Modeling&lt;/a> 接收流量模型，從 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/saturation-discovery/" data-link-title="9.4 Saturation Discovery" data-link-desc="找出 throughput plateau 與 latency knee 的方法">9.4 Saturation Discovery&lt;/a> 接收 ramp-up 與 knee point 判讀，從 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/production-validation/" data-link-title="9.10 Production-Side 驗證" data-link-desc="shadow traffic、dark launch、canary、production-like load test">9.10 Production-Side 驗證&lt;/a> 接收 canary、dark launch 或 production-like load test 的安全邊界。&lt;/p></description><content:encoded><![CDATA[<p>k6 的核心責任是把 workload model 轉成可重跑、可版本化、可接到 CI 的壓測 scenario。它適合 API、HTTP、gRPC、WebSocket 與 browser-style flow 的負載驗證，重點在用程式化腳本描述使用者行為、負載階段、threshold 與結果輸出。</p>
<h2 id="服務定位">服務定位</h2>
<p>k6 是 Grafana Labs 旗下的 scriptable load testing 工具、2021 年被 Grafana 收購。產品線分兩層：<em>k6 OSS</em>（Go 寫的 engine + JS API 描述 scenario、CLI 為主、output 可丟 Prometheus / InfluxDB / JSON / CSV）跟 <em>Grafana Cloud k6</em>（前 k6 Cloud、SaaS 多 region runner + 結果保存 + 跟 Grafana Cloud dashboard / Loki / Tempo 同 plane）。底層 engine 是 Go、不是 JS — JS 只是 scenario 描述層、runtime 由 Go 跑、所以單機 VU 容量比 Python-based 工具高出一個量級。</p>
<p>跟 <a href="/blog/backend/09-performance-capacity/vendors/jmeter/" data-link-title="Apache JMeter" data-link-desc="用 GUI、plugin 與多 protocol sampler 承接企業壓測資產的效能工程工具">JMeter</a> 比、k6 走 <em>code-first + CI-friendly</em>、JMeter 走 <em>XML / GUI + plugin ecosystem</em>；JMeter 在 protocol 廣度（JDBC / LDAP / JMS / FTP）跟非工程團隊操作勝出、k6 在版控、PR review、artifact pipeline 勝出。跟 <a href="/blog/backend/09-performance-capacity/vendors/locust/" data-link-title="Locust" data-link-desc="用 Python user behavior 與 distributed worker 表達高自訂負載模型的效能工程工具">Locust</a> 比、k6 用 JS、Locust 用 Python；Locust 對 Python team 自然、但 Python GIL 讓單機 VU 容量受限、需多 worker、k6 單機可跑數千 VU。跟 <a href="/blog/backend/09-performance-capacity/vendors/gatling/" data-link-title="Gatling" data-link-desc="用 JVM DSL、simulation 與 injection profile 表達複雜 scenario 的效能工程工具">Gatling</a> 比、Gatling 走 JVM + Scala/Java/Kotlin DSL、適合 JVM-heavy 團隊；k6 的 threshold + Grafana ecosystem 整合在 release gate 場景更直接。</p>
<h2 id="定位">定位</h2>
<p>k6 適合把壓測納入工程流程。當團隊已經能描述 traffic shape、endpoint mix、arrival rate、think time 與 stop condition，k6 可以把這些模型寫成腳本，讓每次 release、capacity review 或 peak-event readiness 都能重跑同一組驗證。</p>
<p>這個定位讓 k6 接到三個主章。它從 <a href="/blog/backend/09-performance-capacity/workload-modeling/" data-link-title="9.2 Workload Modeling" data-link-desc="把 production traffic shape 翻成可重播的壓測模型">9.2 Workload Modeling</a> 接收流量模型，從 <a href="/blog/backend/09-performance-capacity/saturation-discovery/" data-link-title="9.4 Saturation Discovery" data-link-desc="找出 throughput plateau 與 latency knee 的方法">9.4 Saturation Discovery</a> 接收 ramp-up 與 knee point 判讀，從 <a href="/blog/backend/09-performance-capacity/production-validation/" data-link-title="9.10 Production-Side 驗證" data-link-desc="shadow traffic、dark launch、canary、production-like load test">9.10 Production-Side 驗證</a> 接收 canary、dark launch 或 production-like load test 的安全邊界。</p>
<h2 id="適用場景">適用場景</h2>
<p>API 壓測是 k6 最穩定的入口。Checkout、login、search、order query、payment callback mock 與 internal API 都可以用 scenario 表達，並用 threshold 把 latency、error rate 與 throughput 轉成 pass / fail 訊號。</p>
<p>CI performance gate 是 k6 的常見價值。團隊可以在 merge、nightly、pre-release 或 game day 前跑固定 baseline，觀察 p95 / p99、error rate、throughput 與 regression trend，再把結果交給 <a href="/blog/backend/06-reliability/performance-regression-gate/" data-link-title="6.13 Performance Regression Gate" data-link-desc="把效能 baseline 從一次性壓測變成持續對齊的 release gate，涵蓋 baseline 設定、判讀方法、variance 控制與退化定位">6.13 Performance Regression Gate</a>。</p>
<p>Peak readiness rehearsal 適合用 k6 表達階段式負載。活動前可以用 ramping arrival rate 模擬 T-90、T-30、T-7、T-1 與 T-0 的負載階段，並把結果回寫到 <a href="/blog/backend/09-performance-capacity/peak-event-readiness/" data-link-title="9.11 高峰事件準備" data-link-desc="活動、季節性流量、推廣事件的 capacity readiness 流程">9.11 高峰事件準備</a>。</p>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 k6 deployment 是否健康、最少看四件事：</p>
<ul>
<li><strong>Scenario design</strong>：用 <code>executor: ramping-arrival-rate</code> 而非 <code>constant-vus</code>、把 RPS / arrival rate 設成 first-class、VU 由 engine 自動算；scenario 描述跟 <a href="/blog/backend/09-performance-capacity/workload-modeling/" data-link-title="9.2 Workload Modeling" data-link-desc="把 production traffic shape 翻成可重播的壓測模型">9.2 Workload Modeling</a> 的 endpoint mix、think time、cohort 對得起來</li>
<li><strong>Threshold gate</strong>：<code>thresholds</code> 區塊明確寫 p95 / p99 / error rate / throughput、CI fail 條件清楚、不靠人眼看 summary 判斷 pass / fail</li>
<li><strong>Output 進 observability stack</strong>：<code>--out experimental-prometheus-rw</code> 把 metric remote-write 到 Prometheus、Grafana dashboard 接 k6 同 datasource、結果跟 target service 的 saturation metric 在同一張圖上看</li>
<li><strong>k6 Cloud vs CLI 邊界</strong>：本地 CLI 跑 baseline + CI、Grafana Cloud k6 跑跨 region / 大規模 / 結果 retention；不要把 CI gate 放 Cloud（成本 + 時間不對）、也不要本地單機硬跑 100k VU（runner 自身瓶頸假象）</li>
</ul>
<p>四件事任一缺失、就是 scenario 已經寫得不完整、threshold gate 失效、或 runner 觀測缺失。</p>
<h2 id="選型判準">選型判準</h2>
<table>
  <thead>
      <tr>
          <th>判準</th>
          <th>k6 的價值</th>
          <th>需要補的能力</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>腳本化</td>
          <td>scenario、threshold、setup / teardown 可版本化</td>
          <td>production traffic 抽樣與模型校正</td>
      </tr>
      <tr>
          <td>CI 友善</td>
          <td>CLI 與 artifact 容易接 pipeline</td>
          <td>長期趨勢儲存與 release gate 語意</td>
      </tr>
      <tr>
          <td>API 導向</td>
          <td>HTTP / gRPC / WebSocket 等常見 API 場景清楚</td>
          <td>複雜瀏覽器互動與端到端資料準備</td>
      </tr>
      <tr>
          <td>團隊學習成本</td>
          <td>JavaScript 腳本容易被多數 backend 團隊接手</td>
          <td>大型分散式 runner 與測試資料治理</td>
      </tr>
  </tbody>
</table>
<p>腳本化價值來自可重跑。一次性的壓測只能回答當天配置能撐多少；可版本化 scenario 可以回答 release 後容量曲線有沒有漂移，並讓退化調查回到同一份 workload model。</p>
<p>CI 友善價值來自交接成本低。壓測結果要能轉成 artifact、threshold、trend 與 gate decision，才會從「工程師手動跑工具」變成 release 流程的一部分。</p>
<p>API 導向價值來自後端路徑明確。k6 很適合 checkout API、search API、internal API 與 webhook receiver；如果主要問題是完整 browser UX、第三方真實支付或多裝置同步，文章要把資料準備、side effect 與環境隔離另外寫清楚。</p>
<h2 id="跟其他工具的取捨">跟其他工具的取捨</h2>
<p>k6 和 JMeter 的主要差異是工作方式。k6 偏程式化腳本、CLI、CI artifact 與工程流程；JMeter 偏 GUI、protocol plugin、既有企業測試流程與非工程團隊協作。</p>
<p>k6 和 Gatling 的主要差異是生態與語言。k6 使用 JavaScript-style 腳本，Gatling 偏 JVM / Scala / Java / Kotlin 生態；團隊語言能力與既有 pipeline 會影響維護成本。</p>
<p>k6 和 Locust 的主要差異是團隊技能與模型表達。Locust 使用 Python，對 Python 團隊與 custom user behavior 很自然；k6 的 threshold、CLI 與雲端 / Grafana 生態讓 release gate 整合更直接。</p>
<p>k6 和 Vegeta 的主要差異是場景複雜度。Vegeta 適合簡單 HTTP load、CLI workflow 與快速 saturation 探測；k6 適合較完整的 multi-step scenario、threshold 與長期 baseline。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>k6</th>
          <th><a href="/blog/backend/09-performance-capacity/vendors/jmeter/" data-link-title="Apache JMeter" data-link-desc="用 GUI、plugin 與多 protocol sampler 承接企業壓測資產的效能工程工具">JMeter</a></th>
          <th><a href="/blog/backend/09-performance-capacity/vendors/locust/" data-link-title="Locust" data-link-desc="用 Python user behavior 與 distributed worker 表達高自訂負載模型的效能工程工具">Locust</a></th>
          <th><a href="/blog/backend/09-performance-capacity/vendors/gatling/" data-link-title="Gatling" data-link-desc="用 JVM DSL、simulation 與 injection profile 表達複雜 scenario 的效能工程工具">Gatling</a></th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Scenario 語言</td>
          <td>JavaScript（ES6+）</td>
          <td>XML（GUI 編輯）/ Groovy</td>
          <td>Python</td>
          <td>Scala / Java / Kotlin DSL</td>
      </tr>
      <tr>
          <td>Engine runtime</td>
          <td>Go</td>
          <td>JVM</td>
          <td>Python（gevent）</td>
          <td>JVM（Akka）</td>
      </tr>
      <tr>
          <td>單機 VU 容量</td>
          <td>高（thousands+）</td>
          <td>中（JVM heap-bound）</td>
          <td>中低（GIL、需 multi-worker）</td>
          <td>高（Akka actor）</td>
      </tr>
      <tr>
          <td>CI 友善度</td>
          <td>強 — CLI + threshold + JSON / Prometheus</td>
          <td>中 — 需 plugin / Jenkins integration</td>
          <td>中 — CLI 友善但 result reporting 較弱</td>
          <td>強 — CLI + HTML report + Maven/Gradle plugin</td>
      </tr>
      <tr>
          <td>Protocol 廣度</td>
          <td>HTTP / gRPC / WebSocket / Browser</td>
          <td>最廣（JDBC / LDAP / JMS / FTP / SMTP）</td>
          <td>HTTP 為主、其他靠 custom client</td>
          <td>HTTP / WebSocket / JMS / MQTT</td>
      </tr>
      <tr>
          <td>Browser test</td>
          <td>k6 Browser（Playwright-based）</td>
          <td>無原生（Selenium plugin）</td>
          <td>無原生</td>
          <td>無原生</td>
      </tr>
      <tr>
          <td>Distributed</td>
          <td>k6 Cloud / k6 Operator on k8s</td>
          <td>Master / Slave（運維重）</td>
          <td>Master / Worker</td>
          <td>Gatling Enterprise / FrontLine</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>API-first + CI gate + Grafana ecosystem</td>
          <td>企業 + protocol 多 + 非工程團隊</td>
          <td>Python team + custom user behavior</td>
          <td>JVM team + DSL 表達力</td>
      </tr>
  </tbody>
</table>
<p>選 k6 的核心訴求：API-first scenario + CI gate + Grafana / Prometheus ecosystem 已用、且團隊接受 JS DSL。Protocol 廣度需求大、走 JMeter；Python team、走 Locust；JVM-heavy、走 Gatling。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>k6 Browser</strong>：基於 Chromium + Playwright API、跑在 k6 同 scenario 內、可混 protocol-level 跟 browser-level load（前段 API call、後段真實 browser flow）。意義是「pure API load 跟 real user UX 在同一份 scenario」、不用維護兩套工具。但 browser VU 比 protocol VU 重幾十倍、runner cost 要重新算。</p>
<p><strong>xk6 extensions</strong>：用 Go 寫 k6 extension、補 protocol（Kafka / Redis / SQL / AMQP）或 output（custom backend）。<code>xk6 build</code> 生出客製 binary、organization 可維護自家 extension。意義是 k6 不只跑 HTTP — Kafka producer load / Redis hot-key probe 都能用同一個 scenario harness。</p>
<p><strong>Grafana Cloud k6（前 k6 Cloud）</strong>：SaaS 跑 multi-region runner、結果保存、跟 Grafana Cloud dashboard / Loki / Tempo / Prometheus 同 plane。適合 <em>跨 region 真實延遲驗證</em>、<em>大規模 distributed run</em>、<em>結果 retention + team share</em>。跟 Grafana Cloud 已用的團隊 ecosystem 一致；只用 OSS 的團隊走 k6 Operator on k8s。</p>
<p><strong>Distributed execution</strong>：自管 distributed 走 <a href="https://github.com/grafana/k6-operator">k6 Operator</a> on Kubernetes、scenario 拆 instance、結果 aggregate 到 output。意義是不需要 k6 Cloud 也能跑跨機器 load、但 runner pool 自管成本 + 結果 aggregation 自己處理。</p>
<p><strong>Output integration</strong>：<code>--out experimental-prometheus-rw</code> 直接 remote-write 到 Prometheus、Grafana dashboard 一張圖看 k6 client metric + target service saturation；<code>--out cloud</code> 上 Grafana Cloud k6；<code>--out json=...</code> 落地檔案給 CI artifact；<code>--out influxdb</code> 接 InfluxDB（legacy）。Loki 用來接 k6 console log、Tempo 用來接 k6 trace（若 scenario 帶 W3C trace context）。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>VU 跑不上去 / runner CPU 滿</strong>：scenario 寫了重 JS 邏輯（big JSON parse、複雜 regex、crypto）— 把 setup-once 邏輯搬 <code>setup()</code>、不要每 VU iteration 重算</li>
<li><strong>Resource throttling 假象</strong>：runner 機器 CPU / network bandwidth / file descriptor 自身瓶頸、target service 還沒到 saturation — 換大機 / 多 runner / 看 runner 自身 saturation metric 排除</li>
<li><strong>Threshold 設過嚴 / CI 一直 red</strong>：threshold 抄 production SLO 不留 budget — staging tenant 跑 5-10 次抓 baseline distribution、threshold 設 baseline + buffer、不是 SLO 直接搬</li>
<li><strong>p95 看起來好但 user 抱怨慢</strong>：scenario endpoint mix 跟 production traffic shape 不符 — 補 production endpoint distribution、按 weight 配 scenario、跟 <a href="/blog/backend/09-performance-capacity/workload-modeling/" data-link-title="9.2 Workload Modeling" data-link-desc="把 production traffic shape 翻成可重播的壓測模型">9.2 Workload Modeling</a> 對齊</li>
<li><strong>Script logic 太重 / VU iteration 不穩</strong>：在 scenario 內做 token refresh / large payload 處理、iteration 時間漂移 — 用 <code>executor: ramping-arrival-rate</code> 鎖 RPS 而非 VU count、iteration 時間漂移由 engine 吸收</li>
<li><strong>結果無法回放 / 找不到 baseline</strong>：output 沒落 artifact、Grafana dashboard 沒存 time range — 每次 run 強制 <code>--out json</code> + tag scenario version + push 到 evidence package</li>
</ul>
<h2 id="操作成本">操作成本</h2>
<p>k6 的主要成本是 workload model 維護。腳本本身容易寫，真正的成本在 production endpoint mix、資料分布、tenant / region / user cohort、think time 與 peak shape 的持續校正。</p>
<p>Runner 成本會隨負載規模上升。單機 runner 適合小型 API baseline；跨 region、數十萬 RPS 或長時間 soak test 需要分散式 runner、網路成本、目標服務隔離與觀測儲存。</p>
<p>測試資料治理是高風險成本。Checkout、payment、order、email、notification 與 webhook 路徑都可能產生 side effect，因此 scenario 要明確定義 test tenant、idempotency key、mock boundary、cleanup 與 stop condition。</p>
<h2 id="evidence-package">Evidence Package</h2>
<p>k6 結果應回寫到 evidence package。最小欄位包括 scenario version、target environment、time range、VUs / arrival rate、threshold、p95 / p99、error rate、throughput、target service saturation metric、known gap 與 owner。</p>
<table>
  <thead>
      <tr>
          <th>欄位</th>
          <th>k6 證據來源</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Source</td>
          <td>k6 summary、JSON output、dashboard link</td>
      </tr>
      <tr>
          <td>Time range</td>
          <td>test start / end</td>
      </tr>
      <tr>
          <td>Query link</td>
          <td>Grafana / Prometheus / APM 查詢連結</td>
      </tr>
      <tr>
          <td>Data quality</td>
          <td>scenario coverage、test data freshness</td>
      </tr>
      <tr>
          <td>Confidence</td>
          <td>production similarity、runner capacity</td>
      </tr>
      <tr>
          <td>Known gap</td>
          <td>未覆蓋 endpoint、未模擬第三方、資料偏差</td>
      </tr>
  </tbody>
</table>
<p>Evidence package 的核心用途是讓 release gate 能判斷。k6 的 threshold pass 只是其中一個訊號；gate 還要看 target service 的 CPU、connection、DB latency、cache hit rate、queue lag 與 cloud cost。</p>
<h2 id="案例回寫">案例回寫</h2>
<p>k6 目前在 09 案例庫中主要作為工具類承接點，案例主角仍是負載形狀與驗證節奏。它可回寫到 <a href="/blog/backend/09-performance-capacity/cases/tixcraft-ticketing-flash-sale-spike/" data-link-title="9.C15 拓元 Tixcraft：售票搶購的瞬間爆量架構" data-link-desc="拓元用 DynamoDB 當寫入緩衝 &#43; 傳統伺服器當慢速消費者、承受 100K&#43; 同時選位 &#43; 30 秒從 6 台擴到 800 台">9.C15 Tixcraft 售票壓測</a> 的 pre-event load test 判讀、<a href="/blog/backend/09-performance-capacity/cases/aws-prime-day-extreme-scale-2025/" data-link-title="9.C1 AWS Prime Day 2025：可預期極端峰值的 dogfood" data-link-desc="Amazon 自家服務在 Prime Day 2025 的峰值數字 — 一年一次可預期峰值的容量設計參考">9.C1 Prime Day readiness</a> 的 staged validation、<a href="/blog/backend/09-performance-capacity/cases/fanduel-dual-peak-betting-streaming/" data-link-title="9.C28 FanDuel：體育直播 &#43; 投注的雙重峰值" data-link-desc="FanDuel 3.5M MAU、Super Bowl 期間擴容 5-10 倍、用 AWS Local Zones &#43; Wavelength &#43; Outposts 處理 20&#43; 州的雙重峰值">9.C28 FanDuel 雙峰 workload</a> 的多模型壓測需求、<a href="/blog/backend/09-performance-capacity/cases/gr8-tech-ai-predicted-betting-peak/" data-link-title="9.C2 GR8 Tech：AI 預測式自動擴容下的體育博彩高峰" data-link-desc="AI 預測 &#43; EKS 自動擴容怎麼在 25ms p95 下承載 54000 TPS 體育博彩峰值流量">9.C2 GR8 Tech FIFA World Cup readiness</a> 的 54000 TPS @ 25ms p95 驗證、以及 <a href="/blog/backend/09-performance-capacity/cases/lyft-microservice-eight-x-peak/" data-link-title="9.C7 Lyft：100&#43; 微服務在 8 倍峰值下的 Auto Scaling" data-link-desc="Lyft 用 AWS Auto Scaling 跨 100&#43; 個微服務承載 8 倍峰值流量、跨 200&#43; 城市">9.C7 Lyft 8x peak</a> 跨 100+ 微服務的獨立 threshold 設計。</p>
<p>這些案例提供的是負載形狀與工程節奏。k6 頁引用案例時，要把 case 轉成 workload model、ramp-up、threshold、runner 規模與 stop condition，並讓工具回到可替換的承載選項 — 例如 GR8 Tech 25ms p95 是 threshold pass / fail 的硬目標、Lyft 的「8x 是特定服務、不是全部 8x」要拆成 per-service scenario。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/09-performance-capacity/workload-modeling/" data-link-title="9.2 Workload Modeling" data-link-desc="把 production traffic shape 翻成可重播的壓測模型">9.2 Workload Modeling</a></li>
<li>上游：<a href="/blog/backend/09-performance-capacity/load-test-tooling/" data-link-title="9.3 壓測工具選型" data-link-desc="k6 / JMeter / Gatling / Locust / Vegeta / Production Replay 的工程選型">9.3 壓測工具選型</a></li>
<li>上游：<a href="/blog/backend/09-performance-capacity/saturation-discovery/" data-link-title="9.4 Saturation Discovery" data-link-desc="找出 throughput plateau 與 latency knee 的方法">9.4 Saturation Discovery</a></li>
<li>跨模組：<a href="/blog/backend/06-reliability/performance-regression-gate/" data-link-title="6.13 Performance Regression Gate" data-link-desc="把效能 baseline 從一次性壓測變成持續對齊的 release gate，涵蓋 baseline 設定、判讀方法、variance 控制與退化定位">6.13 Performance Regression Gate</a></li>
<li>官方：<a href="https://grafana.com/docs/k6/latest/">Grafana k6 documentation</a></li>
</ul>
]]></content:encoded></item><item><title>PostgreSQL</title><link>https://tarrragon.github.io/blog/backend/01-database/vendors/postgresql/</link><pubDate>Wed, 13 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/01-database/vendors/postgresql/</guid><description>&lt;p>PostgreSQL 是 backend 預設關聯式資料庫的安全選擇。生態完整、SQL 功能豐富、MVCC 跟 transaction 模型穩定、新版本仍積極演進（pg17 加入 JSON_TABLE、平行 vacuum；pg18 加入 io_uring async）。Aurora（AWS managed）、CockroachDB、Aurora DSQL（2024-12 preview / 2025-05 GA）、Spanner（2024 PostgreSQL dialect）都把 PostgreSQL wire protocol 當作相容標的 — 它是 SQL DB 世界的 lingua franca。&lt;/p>
&lt;h2 id="教學路線sql-baseline-與交易演進">教學路線：SQL baseline 與交易演進&lt;/h2>
&lt;p>PostgreSQL 服務頁的教學目標是建立 SQL baseline。讀者讀完後要能用 PostgreSQL 理解 transaction、schema evolution、query boundary、connection pressure 與 managed / distributed SQL 的比較基準。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>學習段&lt;/th>
 &lt;th>核心問題&lt;/th>
 &lt;th>對應段落&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>SQL baseline&lt;/td>
 &lt;td>PostgreSQL 為什麼常作為 OLTP 預設比較基準&lt;/td>
 &lt;td>定位、適用場景&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>容量邊界&lt;/td>
 &lt;td>connection、write throughput、replica、storage 如何限制服務&lt;/td>
 &lt;td>容量特性、容量規劃要點&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>交易與查詢&lt;/td>
 &lt;td>複雜 SQL、JSONB、GIS、全文檢索如何影響資料模型&lt;/td>
 &lt;td>適用場景、跟其他 vendor 的取捨&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>演進與維護&lt;/td>
 &lt;td>vacuum、partition、index、replication 如何成為長期責任&lt;/td>
 &lt;td>容量規劃要點、常見陷阱&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>替代路由&lt;/td>
 &lt;td>何時轉 Aurora、CockroachDB、Spanner、DynamoDB 或 OLAP&lt;/td>
 &lt;td>不適用場景、跟其他 vendor 的取捨&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="定位oltp-預設sql-工程深度">定位：OLTP 預設、SQL 工程深度&lt;/h2>
&lt;p>PostgreSQL 跟 MySQL 是兩大 SQL OLTP 主流、但設計取捨明顯不同：&lt;/p>
&lt;ul>
&lt;li>PostgreSQL 偏 &lt;em>特性深度&lt;/em> — JSON、GIS、full-text search、partial index、CTE、window function 都成熟&lt;/li>
&lt;li>MySQL 偏 &lt;em>簡單 query 效能 + 分片生態&lt;/em> — Vitess / PlanetScale 提供超大規模 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">database sharding&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>選 PostgreSQL 的核心訴求：需要進階 SQL 特性、需要長期 schema evolution 彈性、信任 community-driven 演進、想避免單一 vendor lock-in（PostgreSQL 是 open source、可跨雲 / on-prem）。&lt;/p>
&lt;h2 id="容量特性">容量特性&lt;/h2>
&lt;p>PostgreSQL 沒有「vendor 給的容量數字」、要靠 instance 配置 + tuning 推估。但有幾個工程上限要知道：&lt;/p>
&lt;p>&lt;strong>單一 primary 寫吞吐&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>一般 m5.4xlarge 級 instance：5K-10K WPS（依 schema、index、commit fsync）&lt;/li>
&lt;li>高階 r6i.16xlarge + io2 storage：30K-50K WPS&lt;/li>
&lt;li>超過這個級別 → 應用層 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">database sharding&lt;/a> 或換 Aurora / Spanner&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Connection 上限&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>預設 100 connection、每個 connection ~10MB RAM&lt;/li>
&lt;li>1000+ connection 必須 pgBouncer / PgCat 共享 pool&lt;/li>
&lt;li>對應 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/ntt-docomo-lemino-japanese-streaming/" data-link-title="9.C29 NTT DOCOMO Lemino：3 個月達 500 萬 MAU 的串流後端" data-link-desc="Lemino 用 DynamoDB &amp;#43; AWS Media Services 撐 30 channels live &amp;#43; 5M MAU、工程工時下降 90%">9.C29 Lemino case&lt;/a> — RDB connection limit 是 surge 場景的隱性 bottleneck&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Read replica&lt;/strong>：&lt;/p></description><content:encoded><![CDATA[<p>PostgreSQL 是 backend 預設關聯式資料庫的安全選擇。生態完整、SQL 功能豐富、MVCC 跟 transaction 模型穩定、新版本仍積極演進（pg17 加入 JSON_TABLE、平行 vacuum；pg18 加入 io_uring async）。Aurora（AWS managed）、CockroachDB、Aurora DSQL（2024-12 preview / 2025-05 GA）、Spanner（2024 PostgreSQL dialect）都把 PostgreSQL wire protocol 當作相容標的 — 它是 SQL DB 世界的 lingua franca。</p>
<h2 id="教學路線sql-baseline-與交易演進">教學路線：SQL baseline 與交易演進</h2>
<p>PostgreSQL 服務頁的教學目標是建立 SQL baseline。讀者讀完後要能用 PostgreSQL 理解 transaction、schema evolution、query boundary、connection pressure 與 managed / distributed SQL 的比較基準。</p>
<table>
  <thead>
      <tr>
          <th>學習段</th>
          <th>核心問題</th>
          <th>對應段落</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>SQL baseline</td>
          <td>PostgreSQL 為什麼常作為 OLTP 預設比較基準</td>
          <td>定位、適用場景</td>
      </tr>
      <tr>
          <td>容量邊界</td>
          <td>connection、write throughput、replica、storage 如何限制服務</td>
          <td>容量特性、容量規劃要點</td>
      </tr>
      <tr>
          <td>交易與查詢</td>
          <td>複雜 SQL、JSONB、GIS、全文檢索如何影響資料模型</td>
          <td>適用場景、跟其他 vendor 的取捨</td>
      </tr>
      <tr>
          <td>演進與維護</td>
          <td>vacuum、partition、index、replication 如何成為長期責任</td>
          <td>容量規劃要點、常見陷阱</td>
      </tr>
      <tr>
          <td>替代路由</td>
          <td>何時轉 Aurora、CockroachDB、Spanner、DynamoDB 或 OLAP</td>
          <td>不適用場景、跟其他 vendor 的取捨</td>
      </tr>
  </tbody>
</table>
<h2 id="定位oltp-預設sql-工程深度">定位：OLTP 預設、SQL 工程深度</h2>
<p>PostgreSQL 跟 MySQL 是兩大 SQL OLTP 主流、但設計取捨明顯不同：</p>
<ul>
<li>PostgreSQL 偏 <em>特性深度</em> — JSON、GIS、full-text search、partial index、CTE、window function 都成熟</li>
<li>MySQL 偏 <em>簡單 query 效能 + 分片生態</em> — Vitess / PlanetScale 提供超大規模 <a href="/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">database sharding</a></li>
</ul>
<p>選 PostgreSQL 的核心訴求：需要進階 SQL 特性、需要長期 schema evolution 彈性、信任 community-driven 演進、想避免單一 vendor lock-in（PostgreSQL 是 open source、可跨雲 / on-prem）。</p>
<h2 id="容量特性">容量特性</h2>
<p>PostgreSQL 沒有「vendor 給的容量數字」、要靠 instance 配置 + tuning 推估。但有幾個工程上限要知道：</p>
<p><strong>單一 primary 寫吞吐</strong>：</p>
<ul>
<li>一般 m5.4xlarge 級 instance：5K-10K WPS（依 schema、index、commit fsync）</li>
<li>高階 r6i.16xlarge + io2 storage：30K-50K WPS</li>
<li>超過這個級別 → 應用層 <a href="/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">database sharding</a> 或換 Aurora / Spanner</li>
</ul>
<p><strong>Connection 上限</strong>：</p>
<ul>
<li>預設 100 connection、每個 connection ~10MB RAM</li>
<li>1000+ connection 必須 pgBouncer / PgCat 共享 pool</li>
<li>對應 <a href="/blog/backend/09-performance-capacity/cases/ntt-docomo-lemino-japanese-streaming/" data-link-title="9.C29 NTT DOCOMO Lemino：3 個月達 500 萬 MAU 的串流後端" data-link-desc="Lemino 用 DynamoDB &#43; AWS Media Services 撐 30 channels live &#43; 5M MAU、工程工時下降 90%">9.C29 Lemino case</a> — RDB connection limit 是 surge 場景的隱性 bottleneck</li>
</ul>
<p><strong>Read replica</strong>：</p>
<ul>
<li>streaming replication：1 個 primary + 多個 standby（async / sync）</li>
<li>跨 AZ replication lag 通常 &lt; 100ms、跨 region 可能秒級</li>
<li>跟 Aurora 比、自管 PostgreSQL replication lag 較大</li>
</ul>
<p><strong>Storage 上限</strong>：</p>
<ul>
<li>單一 table 32 TB（PostgreSQL 設計上限）</li>
<li>實務上單表超過 1 TB 開始有 vacuum / index 問題、建議 partition</li>
</ul>
<h2 id="適用場景">適用場景</h2>
<p><strong>1. 多用途 OLTP、複雜查詢</strong>：</p>
<ul>
<li>複雜 JOIN、CTE、window function、subquery</li>
<li>訂單系統、會員系統、訂閱方案、權限 RBAC</li>
<li>需要 strong consistency + ACID transaction</li>
</ul>
<p><strong>2. JSON / 半結構化資料</strong>：</p>
<ul>
<li>JSONB column 支援 indexing、partial query</li>
<li>比 MongoDB 適合 <em>主要結構化 + 部分 JSON</em> workload</li>
<li>不適合主要 document workload（用 MongoDB / Cosmos DB）</li>
</ul>
<p><strong>3. 地理 / 全文檢索</strong>：</p>
<ul>
<li>PostGIS 是業界標準 GIS extension</li>
<li>全文檢索（ts_vector）對中等規模夠用、超大規模用 Elasticsearch</li>
</ul>
<p><strong>4. 進階特性需求</strong>：</p>
<ul>
<li>partial index（WHERE 條件下才建 index）</li>
<li>exclusion constraints（避免 booking 重疊）</li>
<li>range types（時間 / 數字範圍）</li>
<li>logical decoding / CDC（Debezium、pgcapture）</li>
<li>foreign data wrapper（query 跨 DB）</li>
</ul>
<p><strong>5. 跨雲 / on-prem 部署</strong>：</p>
<ul>
<li>不想 vendor lock-in</li>
<li>可用 Patroni / Stolon / pg_auto_failover 做 HA</li>
<li>對應 <a href="/blog/backend/01-database/global-distributed-oltp/" data-link-title="1.11 全球分散式 OLTP" data-link-desc="Spanner / Aurora DSQL / Cosmos DB multi-region write / CockroachDB / TiDB 的全球一致性取捨">1.11 全球分散式 OLTP</a> 的 CockroachDB / Aurora DSQL 比較段</li>
</ul>
<p><strong>6. 中小規模高峰場景</strong>：</p>
<ul>
<li>流量 &lt; 10K WPS 級別、PostgreSQL 自管或 RDS 通常夠</li>
<li>流量更高、考慮 Aurora（同 wire protocol、storage 升級）</li>
</ul>
<h2 id="不適用場景">不適用場景</h2>
<p><strong>1. 極高寫入吞吐（單機 &gt; 50K WPS）</strong>：</p>
<ul>
<li>必須進入 <a href="/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">database sharding</a> 或分散式 SQL</li>
<li>替代：CockroachDB、TiDB、Spanner、應用層 sharding</li>
</ul>
<p><strong>2. 全球 multi-region active-active write</strong>：</p>
<ul>
<li>PostgreSQL 是 single primary、不支援 multi-region active-active</li>
<li>替代：Aurora DSQL、Spanner、CockroachDB multi-region</li>
</ul>
<p><strong>3. KV 簡單查詢 + sub-10ms p99</strong>：</p>
<ul>
<li>PostgreSQL connection 開銷 + parsing + planning 已經 1-3ms</li>
<li>KV-pattern workload 用 DynamoDB / Redis / Cosmos DB 更便宜更快</li>
</ul>
<p><strong>4. 大規模 OLAP</strong>：</p>
<ul>
<li>PostgreSQL 定位在 OLTP，analytics workload 交給 OLAP 系統</li>
<li>大數據分析用 ClickHouse / BigQuery / Snowflake / Redshift / Synapse</li>
</ul>
<p><strong>5. 連線量極大 SaaS（每個用戶一個 connection）</strong>：</p>
<ul>
<li>即使有 pgBouncer、超大連線量仍是 PostgreSQL 結構性限制</li>
<li>對應 <a href="/blog/backend/09-performance-capacity/cases/ntt-docomo-lemino-japanese-streaming/" data-link-title="9.C29 NTT DOCOMO Lemino：3 個月達 500 萬 MAU 的串流後端" data-link-desc="Lemino 用 DynamoDB &#43; AWS Media Services 撐 30 channels live &#43; 5M MAU、工程工時下降 90%">9.C29 Lemino</a> 案例 — 流量上升 connection 爆是換 DynamoDB 的主因</li>
</ul>
<h2 id="跟其他-vendor-的取捨">跟其他 vendor 的取捨</h2>
<p><strong>vs MySQL</strong>：</p>
<ul>
<li>PostgreSQL：SQL 特性深、JSON / GIS / window 完整、replication 較簡單但 lag 較大</li>
<li>MySQL：簡單 query 效能好、replication 機制成熟、Vitess 分片生態強</li>
<li>選 PostgreSQL：需要進階 SQL、複雜 query、JSON workload</li>
<li>選 MySQL：高併發簡單 query、需要 sharding、已用 MySQL 生態</li>
</ul>
<p><strong>vs Aurora（同 PostgreSQL wire protocol）</strong>：</p>
<ul>
<li>PostgreSQL：自管 / RDS、特性接近 upstream、跨雲可用</li>
<li>Aurora：AWS managed、storage / compute 分離、更多 read replica</li>
<li>選 PostgreSQL：跨雲、想最新特性、預算敏感</li>
<li>選 Aurora：AWS 生態、需要更快 failover + 更多 read replica</li>
<li>詳見 <a href="/blog/backend/01-database/vendors/aurora/" data-link-title="AWS Aurora" data-link-desc="AWS managed PostgreSQL / MySQL、storage / compute 分離、&#43;75% 效能改善的 production 證據">Aurora vendor page</a></li>
</ul>
<p><strong>vs CockroachDB（PostgreSQL wire protocol 相容）</strong>：</p>
<ul>
<li>PostgreSQL：single-primary OLTP、SQL 特性完整</li>
<li>CockroachDB：multi-region 強一致 SQL、PostgreSQL wire 相容但部分特性缺</li>
<li>選 PostgreSQL：single-region 或 read replica 跨 region 夠</li>
<li>選 CockroachDB：必須 multi-region active-active write</li>
<li>詳見 <a href="/blog/backend/01-database/global-distributed-oltp/" data-link-title="1.11 全球分散式 OLTP" data-link-desc="Spanner / Aurora DSQL / Cosmos DB multi-region write / CockroachDB / TiDB 的全球一致性取捨">1.11 全球分散式 OLTP</a></li>
</ul>
<p><strong>vs Spanner / Aurora DSQL（全球分散式 SQL）</strong>：</p>
<ul>
<li>PostgreSQL：傳統設計、跨 region 是 async replication</li>
<li>Spanner / Aurora DSQL：全球線性化、跨 region 強一致</li>
<li>選 PostgreSQL：90% 場景夠用、便宜、容易</li>
<li>選 Spanner / Aurora DSQL：金融交易、ticketing inventory、必須全球強一致</li>
</ul>
<p><strong>vs DynamoDB</strong>：</p>
<ul>
<li>詳見 <a href="/blog/backend/01-database/kv-document-capacity-planning/" data-link-title="1.10 KV / Document DB 容量規劃" data-link-desc="DynamoDB / Cosmos DB / Bigtable / MongoDB 等 KV / Document DB 的容量設計、partition key 取捨、capacity mode 選擇">1.10 KV / Document DB 容量規劃</a> 的 connection model 對比段</li>
</ul>
<p><strong>vs Neon（PostgreSQL serverless）</strong>：</p>
<ul>
<li>PostgreSQL：standard、自管或 RDS</li>
<li>Neon：branch-based、scale-to-zero、適合 dev / preview environment</li>
<li>選 Neon：dev / preview、稀疏 workload、CI 用</li>
<li>選 PostgreSQL：production sustained workload</li>
</ul>
<h2 id="容量規劃要點">容量規劃要點</h2>
<p><strong>1. Connection pool 必須有</strong>：</p>
<ul>
<li>直接連 1000+ connection 會壓垮 PostgreSQL</li>
<li>pgBouncer（最簡單、transaction pooling）</li>
<li>PgCat（rust 寫的進階替代、支援 sharding）</li>
<li>application 層 pool（HikariCP、SQLAlchemy pool）</li>
<li>通常組合使用：application pool 30-50 connection × 多 instance → pgBouncer 共享 → PostgreSQL 200 connection</li>
<li>對應 <a href="/blog/backend/knowledge-cards/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">Connection Pool 卡片</a></li>
</ul>
<p><strong>2. Replication 配置</strong>：</p>
<ul>
<li>streaming replication：async / sync / <a href="/blog/backend/knowledge-cards/quorum/" data-link-title="Quorum" data-link-desc="分散式系統以多數節點同意作為提交或讀取有效性的門檻">quorum</a></li>
<li>跨 AZ async：lag 通常 &lt; 100ms、failover 1-2 分鐘</li>
<li>跨 AZ sync：lag 接近 0、但寫入要等 standby ack、會降寫吞吐</li>
<li>跨 region 通常 async</li>
<li>HA 工具：Patroni（最常見）、pg_auto_failover、Stolon</li>
</ul>
<p><strong>3. Vacuum 跟 bloat 治理</strong>：</p>
<ul>
<li>PostgreSQL MVCC 會留下 dead tuples、必須 vacuum</li>
<li>autovacuum 配置：throttle 大表、避免在 peak 跑</li>
<li>bloat 監控：pg_stat_user_tables 看 dead_tup ratio</li>
<li>大表 vacuum 可能要 hours、影響 maintenance window</li>
</ul>
<p><strong>4. 大表 partitioning</strong>：</p>
<ul>
<li>單表 &gt; 1 TB 建議 partition（按時間、按 tenant）</li>
<li>partition pruning 讓 query 只掃需要的 partition</li>
<li>partition 限制：cross-partition unique constraint、跨 partition join 較慢</li>
</ul>
<p><strong>5. Index 策略</strong>：</p>
<ul>
<li>預設 B-tree、適合大多數 query</li>
<li>partial index 對 boolean / status column 特別有用</li>
<li>GIN / GiST 對 JSON / full-text / GIS</li>
<li>index 太多會拖累寫入、定期 review 未用 index（pg_stat_user_indexes）</li>
</ul>
<h2 id="安全dr-與角色分工">安全、DR 與角色分工</h2>
<p>PostgreSQL 的 production 完整性不只來自 SQL 特性，也來自資料存取、備份復原、升級責任與事故證據的分工。這一段補上 PG baseline 原本留在 limitation 的三個缺口：Security / RLS / audit logging、cross-region DR、application developer vs DBA / SRE 視角。</p>
<table>
  <thead>
      <tr>
          <th>責任面</th>
          <th>PostgreSQL 要回答的問題</th>
          <th>主要引用路徑</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Access control / RLS</td>
          <td>table、row、function、extension 與 service account 權限如何切</td>
          <td><a href="security-rls-audit-logging/">Security / RLS / Audit Logging</a>、<a href="/blog/backend/07-security-data-protection/data-protection-and-masking-governance/" data-link-title="7.4 資料保護與遮罩治理" data-link-desc="以問題驅動方式整理資料分級、遮罩、匯出與備份治理">7.4 Data Protection</a>、<a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">Audit Log</a></td>
      </tr>
      <tr>
          <td>TLS / credential</td>
          <td>application 連線、DB user、憑證與 secret rotation 如何治理</td>
          <td><a href="/blog/backend/knowledge-cards/tls-mtls/" data-link-title="TLS / mTLS" data-link-desc="說明傳輸加密與雙向憑證驗證如何保護跨邊界資料流">TLS / mTLS</a>、<a href="/blog/backend/knowledge-cards/credential/" data-link-title="Credential" data-link-desc="整理身分驗證與系統存取用秘密資料">Credential</a>、<a href="/blog/backend/knowledge-cards/secret-management/" data-link-title="Secret Management" data-link-desc="說明 token、key、password 與憑證如何保存、輪替與撤銷">Secret Management</a></td>
      </tr>
      <tr>
          <td>Cross-region DR</td>
          <td>region 失效時要 async replica、PITR、Aurora Global Database 還是 distributed SQL</td>
          <td><a href="cross-region-dr/">Cross-region DR</a>、<a href="/blog/backend/knowledge-cards/rpo/" data-link-title="RPO" data-link-desc="說明恢復點目標如何定義可接受資料損失範圍">RPO</a>、<a href="/blog/backend/knowledge-cards/rto/" data-link-title="RTO" data-link-desc="說明恢復時間目標如何約束事故回復策略">RTO</a>、<a href="/blog/backend/knowledge-cards/failover/" data-link-title="Failover" data-link-desc="說明主要服務或節點失效時如何切換到備援能力">Failover</a>、<a href="pitr-wal-archiving/">PITR + WAL Archiving</a></td>
      </tr>
      <tr>
          <td>Developer / DBA split</td>
          <td>application schema、migration、query、index 與 rollback 誰負責</td>
          <td><a href="developer-dba-responsibility-split/">Developer / DBA Responsibility Split</a>、<a href="/blog/backend/01-database/schema-design/" data-link-title="1.2 Schema Design 與資料建模" data-link-desc="整理 table、index、key、partition、denormalization 與命名規則">1.2 Schema Design</a>、<a href="/blog/backend/01-database/database-migration-playbook/" data-link-title="1.6 資料庫轉換實作：雙寫、回填、切流與回滾" data-link-desc="同 DB 內 schema 演進與資料變更的可分段驗證流程、跟 1.12 cross-DB migration 分工">1.6 Migration Playbook</a></td>
      </tr>
      <tr>
          <td>Incident evidence</td>
          <td>資料事故中要留下哪些 query、timeline、restore 與 decision evidence</td>
          <td><a href="/blog/backend/04-observability/observability-evidence-package/" data-link-title="4.20 Observability Evidence Package" data-link-desc="把 log、metric、trace、audit 與資料品質限制包成可交接證據">4.20 Observability Evidence Package</a>、<a href="/blog/backend/08-incident-response/incident-decision-log/" data-link-title="8.19 Incident Decision Log" data-link-desc="把事中假設、決策、證據、回退條件與責任人留下可復盤紀錄">8.19 Incident Decision Log</a></td>
      </tr>
  </tbody>
</table>
<p>Access control / RLS 的判讀重點是把資料責任放在資料層與 application 層之間分工。PostgreSQL 支援 role、grant、schema、function security 與 row-level security；但 RLS 會把授權邏輯拉進 database，適合 multi-tenant row isolation、資料平台或共享 reporting schema，日常 OLTP 仍要保留 application authorization 與 audit trail。</p>
<p>TLS / credential 的判讀重點是連線安全與憑證生命週期。Self-managed PostgreSQL 要處理 server cert、client cert、DB user rotation 與 <a href="/blog/backend/knowledge-cards/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">connection pool</a> 重連；managed PostgreSQL 常把 certificate、IAM auth 或 secret integration 交給平台，但 application pool、migration tool 與 read replica 仍要一起更新。</p>
<p>Cross-region DR 的判讀重點是 <a href="/blog/backend/knowledge-cards/rpo/" data-link-title="RPO" data-link-desc="說明恢復點目標如何定義可接受資料損失範圍">RPO</a> / <a href="/blog/backend/knowledge-cards/rto/" data-link-title="RTO" data-link-desc="說明恢復時間目標如何約束事故回復策略">RTO</a> 與資料一致性。自管 PostgreSQL 可用 streaming replication、WAL archiving、PITR 與 Patroni 做 region <a href="/blog/backend/knowledge-cards/failover/" data-link-title="Failover" data-link-desc="說明主要服務或節點失效時如何切換到備援能力">failover</a>；Aurora 把 backup、PITR 與 Global Database 交給 AWS；真正 active-active 或 global strong consistency 需求要回到 CockroachDB、Spanner 或 Aurora DSQL，single-primary PostgreSQL 保留為 region failover 與 async DR 路線。</p>
<p>Developer / DBA split 的判讀重點是把日常責任寫進流程。Application developer 擁有 query shape、transaction boundary、repository adapter 與 migration contract；DBA / SRE 擁有 backup、replication、pooler、extension、vacuum、index maintenance 與 DR drill；release gate 需要把兩邊 evidence 合在同一份 decision log。</p>
<h2 id="managed-pg-與相容變體路由">Managed PG 與相容變體路由</h2>
<p>PostgreSQL wire protocol 已成為 managed SQL 與 distributed SQL 的相容目標。選型時要區分「PostgreSQL 本體」、「managed PostgreSQL」、「PostgreSQL-compatible distributed SQL」與「PostgreSQL extension ecosystem」四種不同責任。</p>
<table>
  <thead>
      <tr>
          <th>變體</th>
          <th>適合情境</th>
          <th>主要代價 / 檢查點</th>
          <th>下一步路由</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>RDS / self-managed PG</td>
          <td>想接近 upstream、保留跨雲與 extension 彈性</td>
          <td>團隊承擔 HA、backup、upgrade、vacuum 與 pooler</td>
          <td><a href="patroni-ha/">Patroni HA</a>、<a href="pitr-wal-archiving/">PITR + WAL Archiving</a></td>
      </tr>
      <tr>
          <td>Aurora PostgreSQL</td>
          <td>AWS 內 production OLTP、想轉移 HA / storage ops</td>
          <td>extension whitelist、cost model、cluster endpoint</td>
          <td><a href="migrate-to-aurora/">→ Aurora</a>、<a href="/blog/backend/01-database/vendors/aurora/" data-link-title="AWS Aurora" data-link-desc="AWS managed PostgreSQL / MySQL、storage / compute 分離、&#43;75% 效能改善的 production 證據">Aurora vendor</a></td>
      </tr>
      <tr>
          <td>Cloud SQL / AlloyDB</td>
          <td>GCP 內 managed PostgreSQL 與 Google operation model</td>
          <td>extension / version matrix、IAM / backup / cost model</td>
          <td><a href="managed-pg-comparison/">Managed PG Comparison</a></td>
      </tr>
      <tr>
          <td>Azure Cosmos DB for PostgreSQL</td>
          <td>Citus-based distributed PostgreSQL、tenant / shard workload</td>
          <td>coordinator / worker topology、Citus 語意</td>
          <td><a href="citus-distributed/">Citus distributed</a>、<a href="/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">Database Sharding</a>、<a href="/blog/backend/01-database/vendors/cosmosdb/" data-link-title="Azure Cosmos DB" data-link-desc="全球分散式 multi-model DB、5 個 consistency levels、Microsoft 自家 dogfood 證據">Cosmos DB vendor</a></td>
      </tr>
      <tr>
          <td>Neon / serverless PG</td>
          <td>preview、branch、稀疏 workload、dev environment</td>
          <td>cold start、connection、production sustained workload</td>
          <td>本頁 vs Neon 段、後續 serverless PG comparison</td>
      </tr>
      <tr>
          <td>Aurora DSQL / CockroachDB</td>
          <td>global write、distributed SQL、region resiliency</td>
          <td>transaction retry、extension gap、latency / cost</td>
          <td><a href="migrate-to-aurora-dsql/">→ Aurora DSQL</a>、<a href="migrate-to-cockroachdb/">→ CockroachDB</a></td>
      </tr>
  </tbody>
</table>
<p>Managed PG 變體的引用規則是先查 compatibility，再談 migration。Extension whitelist、backup / restore API、logical replication 支援、connection endpoint 行為與 pricing 都是時間敏感 claim；實作前要回到官方文件確認版本，並把確認日期留在 migration plan 或 decision log。</p>
<h2 id="deep-article--migration-playbook已完成">Deep article + Migration playbook（已完成）</h2>
<table>
  <thead>
      <tr>
          <th>主題</th>
          <th>文章</th>
          <th>類型</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Streaming replication topology + LSN + slot</td>
          <td><a href="replication-topology/">replication-topology</a></td>
          <td>Deep article</td>
      </tr>
      <tr>
          <td>pg_repack / pg-osc 跟 PG 內建 ALTER 行為</td>
          <td><a href="online-schema-change/">online-schema-change</a></td>
          <td>Deep article</td>
      </tr>
      <tr>
          <td>Process-per-connection model + pooler 必要性</td>
          <td><a href="connection-scaling/">connection-scaling</a></td>
          <td>Deep article</td>
      </tr>
      <tr>
          <td>pgBouncer + PgCat connection pool</td>
          <td><a href="pgbouncer-config/">pgbouncer-config</a></td>
          <td>Deep article</td>
      </tr>
      <tr>
          <td>Patroni HA + DCS-based failover</td>
          <td><a href="patroni-ha/">patroni-ha</a></td>
          <td>Deep article</td>
      </tr>
      <tr>
          <td>Autovacuum tuning + bloat 治理</td>
          <td><a href="autovacuum-tuning/">autovacuum-tuning</a></td>
          <td>Deep article</td>
      </tr>
      <tr>
          <td>Logical replication + Debezium CDC</td>
          <td><a href="logical-replication-debezium/">logical-replication-debezium</a></td>
          <td>Deep article</td>
      </tr>
      <tr>
          <td>Citus distributed extension</td>
          <td><a href="citus-distributed/">citus-distributed</a></td>
          <td>Deep article</td>
      </tr>
      <tr>
          <td>BDR / pgEdge / Bucardo multi-master</td>
          <td><a href="bdr-multi-master/">bdr-multi-master</a></td>
          <td>Deep article</td>
      </tr>
      <tr>
          <td>MVCC + lock model（PG 並行控制核心）</td>
          <td><a href="mvcc-lock-model/">mvcc-lock-model</a></td>
          <td>Deep article</td>
      </tr>
      <tr>
          <td>EXPLAIN / auto_explain / pg_hint_plan</td>
          <td><a href="query-optimization/">query-optimization</a></td>
          <td>Deep article</td>
      </tr>
      <tr>
          <td>Index method 選型決策樹（B-tree / GIN / GiST / BRIN）</td>
          <td><a href="index-selection/">index-selection</a></td>
          <td>Deep article</td>
      </tr>
      <tr>
          <td>Declarative partitioning + pg_partman</td>
          <td><a href="declarative-partitioning/">declarative-partitioning</a></td>
          <td>Deep article</td>
      </tr>
      <tr>
          <td>JSONB binary storage + GIN index</td>
          <td><a href="jsonb-deep-dive/">jsonb-deep-dive</a></td>
          <td>Deep article</td>
      </tr>
      <tr>
          <td>Full-text search（tsvector + pg_trgm）</td>
          <td><a href="full-text-search/">full-text-search</a></td>
          <td>Deep article</td>
      </tr>
      <tr>
          <td>Extension ecosystem（pgvector / TimescaleDB 等）</td>
          <td><a href="extension-ecosystem/">extension-ecosystem</a></td>
          <td>Deep article</td>
      </tr>
      <tr>
          <td>TimescaleDB hypertable + CAGG + compression</td>
          <td><a href="timescaledb-deep-dive/">timescaledb-deep-dive</a></td>
          <td>Deep article</td>
      </tr>
      <tr>
          <td>pgvector HNSW / IVFFlat ANN search</td>
          <td><a href="pgvector-deep-dive/">pgvector-deep-dive</a></td>
          <td>Deep article</td>
      </tr>
      <tr>
          <td>PostGIS geometry / geography + GiST</td>
          <td><a href="postgis-deep-dive/">postgis-deep-dive</a></td>
          <td>Deep article</td>
      </tr>
      <tr>
          <td>PITR + WAL archiving</td>
          <td><a href="pitr-wal-archiving/">pitr-wal-archiving</a></td>
          <td>Deep article</td>
      </tr>
      <tr>
          <td>Replication slot management（含 PG 17 failover slot）</td>
          <td><a href="replication-slot-management/">replication-slot-management</a></td>
          <td>Deep article</td>
      </tr>
      <tr>
          <td>SQL features baseline + MySQL 對比</td>
          <td><a href="sql-features-baseline/">sql-features-baseline</a></td>
          <td>Deep article</td>
      </tr>
      <tr>
          <td>Hands-on 操作路線</td>
          <td><a href="hands-on/">hands-on</a></td>
          <td>操作型章節群</td>
      </tr>
      <tr>
          <td>Major version upgrade（N → N+1 pg_upgrade）</td>
          <td><a href="major-version-upgrade/">major-version-upgrade</a></td>
          <td>Migration playbook（5-type 漏類 / 接近 Type B 但需 upgrade-specific audit）</td>
      </tr>
      <tr>
          <td>→ Aurora PostgreSQL</td>
          <td><a href="migrate-to-aurora/">migrate-to-aurora</a></td>
          <td>Migration playbook（Type C）</td>
      </tr>
      <tr>
          <td>→ Aurora DSQL（PG wire-compat distributed）</td>
          <td><a href="migrate-to-aurora-dsql/">migrate-to-aurora-dsql</a></td>
          <td>Migration playbook（Type E）</td>
      </tr>
      <tr>
          <td>→ CockroachDB</td>
          <td><a href="migrate-to-cockroachdb/">migrate-to-cockroachdb</a></td>
          <td>Migration playbook（Type E）</td>
      </tr>
      <tr>
          <td>Multi-region + GDPR rollout</td>
          <td><a href="multi-region-gdpr-rollout/">multi-region-gdpr-rollout</a></td>
          <td>Migration playbook（Type F）</td>
      </tr>
      <tr>
          <td>Partition redesign</td>
          <td><a href="partition-redesign/">partition-redesign</a></td>
          <td>Migration playbook（Type F）</td>
      </tr>
  </tbody>
</table>
<h2 id="補充正文路由">補充正文路由</h2>
<p>當前 deep article、migration playbook、補充正文與 hands-on 已 cover replication / HA / OSC / connection / CDC / sharding / multi-master / MVCC / query opt / index / partitioning / JSONB / FTS / extension（含 TimescaleDB / pgvector / PostGIS）/ backup / slot / SQL features / upgrade / migration / security / DR / managed variant 等維度。下列補充正文用來承接 overview 中提到的延伸議題：</p>
<ul>
<li><strong><a href="logical-decoding-plugins/">Logical decoding plugins deep dive</a></strong>：wal2json / pgoutput / decoderbufs 對位、CDC pipeline 整合</li>
<li><strong><a href="pg-partman-advanced/">pg_partman advanced</a></strong>：retention 跟 child partition 自動 management</li>
<li><strong><a href="connection-pooler-comparison/">Connection pooler comparison</a></strong>：PgBouncer vs Pgcat vs Odyssey 細部對比</li>
<li><strong><a href="aurora-io-optimized-cost/">Aurora I/O-Optimized vs standard</a></strong>：cost model 取捨</li>
<li><strong><a href="managed-pg-comparison/">AlloyDB / Cloud SQL 比較</a></strong>：GCP managed PG 選型</li>
</ul>
<p>上述補充篇已完成正文，並保留既有引用路徑。Logical decoding 接 <a href="logical-replication-debezium/">Logical Replication + Debezium</a> 與 <a href="replication-slot-management/">Replication Slot Management</a>；pg_partman advanced 接 <a href="declarative-partitioning/">Declarative Partitioning</a>；pooler comparison 接 <a href="connection-scaling/">Connection Scaling</a> 與 <a href="pgbouncer-config/">pgBouncer Config</a>；Aurora cost 接 <a href="migrate-to-aurora/">→ Aurora</a>；AlloyDB / Cloud SQL 接 <a href="managed-pg-comparison/">Managed PG Comparison</a>。</p>
<h2 id="案例對照">案例對照</h2>
<p>PostgreSQL 沒有直接的 09 case（多數 09 case 用 managed vendor）、但作為 <em>baseline 跟遷移源頭</em> 在許多 case 出現：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 PostgreSQL 的關係</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/cases/netflix-aurora-consolidation/" data-link-title="9.C23 Netflix：把關聯式 DB 統一到 Aurora、效能 &#43;75%、成本 -28%" data-link-desc="Netflix 把多套關聯式 DB 統一到 Aurora、效能提升 75%、成本下降 28%、串流數十億小時">9.C23 Netflix Aurora consolidation</a></td>
          <td>從多套 RDBMS（含 PostgreSQL）統一到 Aurora</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/cases/clearent-azure-sql-hyperscale-payments/" data-link-title="9.C32 Clearent：Azure SQL Hyperscale 撐每年 5 億筆支付交易" data-link-desc="Clearent 在 Azure SQL Hyperscale 上處理每年 5 億筆支付交易、autoscale &#43; 微服務架構">9.C32 Clearent Azure SQL Hyperscale</a></td>
          <td>Azure 生態替代 PostgreSQL 的選擇</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/cases/ntt-docomo-lemino-japanese-streaming/" data-link-title="9.C29 NTT DOCOMO Lemino：3 個月達 500 萬 MAU 的串流後端" data-link-desc="Lemino 用 DynamoDB &#43; AWS Media Services 撐 30 channels live &#43; 5M MAU、工程工時下降 90%">9.C29 Lemino RDB connection limit</a></td>
          <td>PostgreSQL/MySQL 都有的 connection 限制</td>
      </tr>
  </tbody>
</table>
<h2 id="已知-limitation-與-audit-紀錄">已知 Limitation 與 Audit 紀錄</h2>
<p>本 vendor 頁的 22 篇 deep article + 6 篇 migration playbook 經過 4-reviewer audit（A 寫作規範 / B 跨檔一致性 / C 技術準確性 / D 框架偏誤）、Phase 1-3 修法完成。承認以下 limitation：</p>
<ul>
<li><strong>PG narrative bias</strong>：pgvector / TimescaleDB / extension-ecosystem / Citus 四篇對「PG 取代專業 DB」描述偏 PG-favoring；對手 vendor（Pinecone / InfluxDB / Vitess）的優勢段相對簡短。讀者選型時、請以 cost / ops / scale 三軸綜合判斷、不依本 vendor 頁單一視角。</li>
<li><strong>Anti-recommendation 深度不一</strong>：bdr-multi-master / extension-ecosystem 有「99% 不需要」明確邊界、其他篇章邊界較柔（如「Vector 量 &gt; 5-20M」是粗略門檻）。實際 production 決策請參考多 vendor 對照 + 自家 workload 量測。</li>
<li><strong>Sibling cross-link 狀態</strong>：MySQL ↔ PG sibling、PG 既有 ↔ 新章節 cross-link 已補（refer <a href="/blog/report/sibling-vendor-cross-link-bidirectionality-audit/" data-link-title="Sibling Vendor Cross-Link 雙向性 Audit：寫 Vendor Batch 結束必跑" data-link-desc="當寫 sibling vendor batch（A vs B）、cross-link 容易單向 — A 提 B 多次、B 沒回提 A、形成 navigation asymmetry。Case：MySQL 18 篇對 PG sibling cross-link 9 條、PG 對 MySQL cross-link 0 條。機制：寫第二個 batch 時 reference 第一個 batch 是自然行為、但 reverse direction 必須主動補。修法：vendor batch 結束跑 bidirectional link audit、`A → B` 跟 `B → A` 對比、缺一邊就補。">#136 卡</a>）；本輪同步補 Aurora / CockroachDB / Spanner / Cosmos DB / DynamoDB vendor 頁的反向 sibling 路由，剩餘精修可在各 migration playbook 補更細的 step-by-step 對照。</li>
<li><strong>時間敏感 vendor claim</strong>：Aurora DSQL（2024-12 preview / 2025-05 GA）/ pgvector（0.8 iterative scan）/ TimescaleDB version matrix / DSQL extension 支援範圍持續演進、本 vendor 頁以 2025-2026 公開狀態為準、實作前請以 vendor 官方 docs 為準（refer <a href="/blog/report/vendor-feature-time-sensitivity-claim-verification/" data-link-title="Vendor Feature 時間敏感性：Claim Verification 必跑、寫作日期必標" data-link-desc="寫 vendor article 時、feature limitation claim（『不支援 X』『最多 Y』『預設 Z』）有時間敏感性 — vendor 持續演進、寫作後 N 個月可能 invalidate 整段 audit 邏輯。Case：PlanetScale FK 不支援是 2022 年的事實、2023 末 Vitess 18 加 FK 支援、寫作時若不 verify、Phase 1 audit「FK audit &#43; 全 drop」整段過時。機制：LLM training cutoff vs vendor changelog 速度差、且 LLM 預設不標 claim 的時間性。修法：每篇 vendor article 標 *Last verified* date、limitation claim 必要時加 *as of N* 註、claim 反轉 invalidates 整段 audit 時必須重寫不是修補。">#137 卡</a>）。</li>
<li><strong>補充維度已正文化</strong>：<a href="security-rls-audit-logging/">Security / RLS / audit logging</a>、<a href="cross-region-dr/">cross-region DR</a>、<a href="developer-dba-responsibility-split/">application developer vs DBA 視角分工</a>、<a href="migrate-to-yugabytedb-tidb/">YugabyteDB / TiDB migration playbook</a>、<a href="specialized-pg-variants/">specialized PG variants</a> 已補成正文。本輪也補上跨 vendor 反向連結與時間敏感 claim 路由；下一輪可集中在 migration playbook 的操作步驟與 lab 化。</li>
</ul>
<p>詳細 audit findings 跟修法見 <a href="/blog/report/sibling-vendor-cross-link-bidirectionality-audit/" data-link-title="Sibling Vendor Cross-Link 雙向性 Audit：寫 Vendor Batch 結束必跑" data-link-desc="當寫 sibling vendor batch（A vs B）、cross-link 容易單向 — A 提 B 多次、B 沒回提 A、形成 navigation asymmetry。Case：MySQL 18 篇對 PG sibling cross-link 9 條、PG 對 MySQL cross-link 0 條。機制：寫第二個 batch 時 reference 第一個 batch 是自然行為、但 reverse direction 必須主動補。修法：vendor batch 結束跑 bidirectional link audit、`A → B` 跟 `B → A` 對比、缺一邊就補。">#136 Sibling Vendor Cross-Link Bidirectionality</a> / <a href="/blog/report/vendor-feature-time-sensitivity-claim-verification/" data-link-title="Vendor Feature 時間敏感性：Claim Verification 必跑、寫作日期必標" data-link-desc="寫 vendor article 時、feature limitation claim（『不支援 X』『最多 Y』『預設 Z』）有時間敏感性 — vendor 持續演進、寫作後 N 個月可能 invalidate 整段 audit 邏輯。Case：PlanetScale FK 不支援是 2022 年的事實、2023 末 Vitess 18 加 FK 支援、寫作時若不 verify、Phase 1 audit「FK audit &#43; 全 drop」整段過時。機制：LLM training cutoff vs vendor changelog 速度差、且 LLM 預設不標 claim 的時間性。修法：每篇 vendor article 標 *Last verified* date、limitation claim 必要時加 *as of N* 註、claim 反轉 invalidates 整段 audit 時必須重寫不是修補。">#137 Vendor Feature 時間敏感性</a> / <a href="/blog/report/cross-reviewer-convergence-priority-weighting/" data-link-title="Cross-Reviewer Convergence：多 Reviewer 收斂的 finding 比單 Reviewer flag 信號強" data-link-desc="Multi-reviewer audit（4-reviewer / N-reviewer parallel）後、finding priority 不該是 *N 個 reviewer 報告平均合併*、應該按 *跨 reviewer convergence* 加權 — 兩個獨立 reviewer 從不同 axis 各自發現同一 finding 是 *信號收斂*、比單 reviewer flag 信號強 5-10x。Case：MySQL 17 篇 4-reviewer audit、Reviewer A（寫作規範）跟 Reviewer B（跨檔一致性）獨立 flag 同一 finding『4 篇 migration playbook 缺 weight &#43; banner』、是跨軸 convergence、是最 high-priority fix。機制：N 個獨立 axis 隨機 hit 同一 finding 的機率隨 N 增加而 exponential decline、convergence 排除噪音、是 signal-to-noise 的最高比訊號。修法：multi-reviewer audit 後做 *cross-reviewer matrix*、convergence column 自動標 priority bump。">#138 Cross-Reviewer Convergence</a>。</p>
<h2 id="常見陷阱">常見陷阱</h2>
<ul>
<li><strong>connection 沒 pool 直接連</strong>：1000 application instance × 30 connection = 30K connection、PostgreSQL 撐不住</li>
<li><strong>沒 vacuum 治理</strong>：dead tuple 累積、table bloat、query 變慢</li>
<li><strong>大表沒 partition</strong>：&gt; 1 TB 單表的 vacuum / index rebuild 變成事故</li>
<li><strong>index 不 review</strong>：寫吞吐被舊 index 拖垮</li>
<li><strong>跨 AZ sync replication 給寫入吞吐高的 workload</strong>：每次 commit 等 standby ack、寫吞吐減半</li>
<li><strong>logical replication 拖太多 publication</strong>：可能造成 primary WAL 堆積、disk 爆</li>
</ul>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>完整 T1 對照：<a href="/blog/backend/01-database/vendors/" data-link-title="資料庫 Vendor 清單" data-link-desc="規劃 SQL、managed SQL、document、KV 與 distributed SQL 的服務頁撰寫順序與教學大綱">01-database vendors index</a></li>
<li>平行：<a href="/blog/backend/01-database/vendors/mysql/" data-link-title="MySQL" data-link-desc="高併發網路服務常用關聯式資料庫、Vitess / PlanetScale 分片生態、GitHub / Shopify / Facebook 規模驗證">MySQL vendor</a>、<a href="/blog/backend/01-database/vendors/aurora/" data-link-title="AWS Aurora" data-link-desc="AWS managed PostgreSQL / MySQL、storage / compute 分離、&#43;75% 效能改善的 production 證據">Aurora vendor</a>（managed PostgreSQL）</li>
<li>操作：<a href="/blog/backend/01-database/vendors/postgresql/hands-on/" data-link-title="PostgreSQL Hands-on 操作路線" data-link-desc="PostgreSQL local lab、connection pool、PITR restore drill、schema migration evidence 與 HA failover 的操作型章節設計">PostgreSQL Hands-on</a>（local lab、pool、PITR、migration evidence、HA drill）</li>
<li>上游：<a href="/blog/backend/01-database/high-concurrency-access/" data-link-title="1.1 高併發下的 SQL 讀寫邊界" data-link-desc="說明高併發服務如何共用資料庫 client、控制 transaction、管理 connection pool、避免資料庫成為瓶頸">1.1 高併發資料存取</a>、<a href="/blog/backend/01-database/transaction-boundary/" data-link-title="1.3 Transaction 與一致性邊界" data-link-desc="交易邊界、isolation level、retry 策略、distributed transaction（2PC、Saga）與跨 region 強一致取捨">1.3 Transaction Boundary</a></li>
<li>下游：<a href="/blog/backend/01-database/kv-document-capacity-planning/" data-link-title="1.10 KV / Document DB 容量規劃" data-link-desc="DynamoDB / Cosmos DB / Bigtable / MongoDB 等 KV / Document DB 的容量設計、partition key 取捨、capacity mode 選擇">1.10 KV / Document DB 容量規劃</a>（PostgreSQL 不適用時的替代）/ <a href="/blog/backend/01-database/global-distributed-oltp/" data-link-title="1.11 全球分散式 OLTP" data-link-desc="Spanner / Aurora DSQL / Cosmos DB multi-region write / CockroachDB / TiDB 的全球一致性取捨">1.11 全球分散式 OLTP</a>（PostgreSQL 不夠用時的升級路徑）</li>
<li>跨模組：<a href="/blog/backend/09-performance-capacity/bottleneck-localization/" data-link-title="9.5 瓶頸定位流程" data-link-desc="從 app 到 DB / cache / broker / 第三方 quota 的逐層瓶頸定位">9.5 瓶頸定位流程</a> — connection / replication lag / vacuum 都是 PostgreSQL 常見 bottleneck 源</li>
<li>官方：<a href="https://www.postgresql.org/docs/">PostgreSQL Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>GitHub Actions</title><link>https://tarrragon.github.io/blog/backend/06-reliability/vendors/github-actions/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/06-reliability/vendors/github-actions/</guid><description>&lt;p>GitHub Actions 是 GitHub 原生的 CI/CD 工具、承擔三個責任：PR check workflow（test / lint / coverage）、release 自動化 + environment protection rules、跨 platform matrix testing。設計取捨偏向「跟 GitHub 深度整合 + marketplace action 生態 + OIDC 認證雲端 + self-hosted runner」、是 GitHub-hosted 專案的預設 CI 選擇。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>寫 workflow（.github/workflows/*.yml）&lt;/li>
&lt;li>設計 PR check + matrix testing&lt;/li>
&lt;li>用 reusable workflows / composite actions 復用&lt;/li>
&lt;li>配置 environment protection + approval gate&lt;/li>
&lt;li>用 OIDC + cloud auth（無 long-lived secret）&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑5-分鐘把-github-actions-跑起來">最短路徑：5 分鐘把 GitHub Actions 跑起來&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c"># .github/workflows/ci.yml&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">CI&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">on&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="l">pull_request]&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">jobs&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">test&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">runs-on&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">ubuntu-latest&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">steps&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">uses&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">actions/checkout@v4&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">9&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">run&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">npm test&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="日常操作與決策形狀">日常操作與決策形狀&lt;/h2>
&lt;h3 id="workflow-設計">Workflow 設計&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>on triggers（push / pull_request / schedule / workflow_dispatch / repository_dispatch）&lt;/li>
&lt;li>job / step / action&lt;/li>
&lt;li>Matrix（OS / language version / test split）&lt;/li>
&lt;li>對應指令範例：&lt;code>gh workflow run&lt;/code>、&lt;code>gh run list&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="cache-策略">Cache 策略&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>actions/cache（語言依賴 / build cache）&lt;/li>
&lt;li>Cache key 設計（hashFiles + version）&lt;/li>
&lt;li>Cache scope（per branch / per repo）&lt;/li>
&lt;li>對應 build speed optimization&lt;/li>
&lt;/ul>
&lt;h3 id="reusable-workflows--composite-actions">Reusable workflows / composite actions&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>Reusable workflow：跨 repo 引用整個 workflow&lt;/li>
&lt;li>Composite action：把多 step 包成 action&lt;/li>
&lt;li>對應 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/" data-link-title="Knowledge Cards" data-link-desc="用原子化卡片整理後端服務選型前需要理解的 domain knowhow">knowledge cards reusable-action&lt;/a> (對應 DRY)&lt;/li>
&lt;/ul>
&lt;h2 id="進階主題按需閱讀">進階主題（按需閱讀）&lt;/h2>
&lt;h3 id="self-hosted-runner">Self-hosted runner&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>內網資源 / 特殊硬體（GPU）/ macOS&lt;/li>
&lt;li>Runner group + scaling&lt;/li>
&lt;li>Security：ephemeral runner（每次新建）&lt;/li>
&lt;li>對應 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/" data-link-title="模組七：資安與資料保護" data-link-desc="以問題驅動方式擴充資安知識網：先定義服務環節問題，再以案例作為觸發式參考">07 security&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="oidc--cloud-auth">OIDC + cloud auth&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>GitHub OIDC provider&lt;/li>
&lt;li>AWS / GCP / Azure 信任 GitHub&lt;/li>
&lt;li>無 long-lived access key&lt;/li>
&lt;li>對應 supply chain security&lt;/li>
&lt;/ul>
&lt;h3 id="environment-protection">Environment protection&lt;/h3>
&lt;p>子議題：&lt;/p></description><content:encoded><![CDATA[<p>GitHub Actions 是 GitHub 原生的 CI/CD 工具、承擔三個責任：PR check workflow（test / lint / coverage）、release 自動化 + environment protection rules、跨 platform matrix testing。設計取捨偏向「跟 GitHub 深度整合 + marketplace action 生態 + OIDC 認證雲端 + self-hosted runner」、是 GitHub-hosted 專案的預設 CI 選擇。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>寫 workflow（.github/workflows/*.yml）</li>
<li>設計 PR check + matrix testing</li>
<li>用 reusable workflows / composite actions 復用</li>
<li>配置 environment protection + approval gate</li>
<li>用 OIDC + cloud auth（無 long-lived secret）</li>
</ol>
<h2 id="最短路徑5-分鐘把-github-actions-跑起來">最短路徑：5 分鐘把 GitHub Actions 跑起來</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="ln">1</span><span class="cl"><span class="c"># .github/workflows/ci.yml</span><span class="w">
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="w"></span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">CI</span><span class="w">
</span></span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="w"></span><span class="nt">on</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="l">pull_request]</span><span class="w">
</span></span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="w"></span><span class="nt">jobs</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="w">  </span><span class="nt">test</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="w">    </span><span class="nt">runs-on</span><span class="p">:</span><span class="w"> </span><span class="l">ubuntu-latest</span><span class="w">
</span></span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="w">    </span><span class="nt">steps</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="w">      </span>- <span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">actions/checkout@v4</span><span class="w">
</span></span></span><span class="line"><span class="ln">9</span><span class="cl"><span class="w">      </span>- <span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="l">npm test</span></span></span></code></pre></div><h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="workflow-設計">Workflow 設計</h3>
<p>子議題：</p>
<ul>
<li>on triggers（push / pull_request / schedule / workflow_dispatch / repository_dispatch）</li>
<li>job / step / action</li>
<li>Matrix（OS / language version / test split）</li>
<li>對應指令範例：<code>gh workflow run</code>、<code>gh run list</code></li>
</ul>
<h3 id="cache-策略">Cache 策略</h3>
<p>子議題：</p>
<ul>
<li>actions/cache（語言依賴 / build cache）</li>
<li>Cache key 設計（hashFiles + version）</li>
<li>Cache scope（per branch / per repo）</li>
<li>對應 build speed optimization</li>
</ul>
<h3 id="reusable-workflows--composite-actions">Reusable workflows / composite actions</h3>
<p>子議題：</p>
<ul>
<li>Reusable workflow：跨 repo 引用整個 workflow</li>
<li>Composite action：把多 step 包成 action</li>
<li>對應 <a href="/blog/backend/knowledge-cards/" data-link-title="Knowledge Cards" data-link-desc="用原子化卡片整理後端服務選型前需要理解的 domain knowhow">knowledge cards reusable-action</a> (對應 DRY)</li>
</ul>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<h3 id="self-hosted-runner">Self-hosted runner</h3>
<p>子議題：</p>
<ul>
<li>內網資源 / 特殊硬體（GPU）/ macOS</li>
<li>Runner group + scaling</li>
<li>Security：ephemeral runner（每次新建）</li>
<li>對應 <a href="/blog/backend/07-security-data-protection/" data-link-title="模組七：資安與資料保護" data-link-desc="以問題驅動方式擴充資安知識網：先定義服務環節問題，再以案例作為觸發式參考">07 security</a></li>
</ul>
<h3 id="oidc--cloud-auth">OIDC + cloud auth</h3>
<p>子議題：</p>
<ul>
<li>GitHub OIDC provider</li>
<li>AWS / GCP / Azure 信任 GitHub</li>
<li>無 long-lived access key</li>
<li>對應 supply chain security</li>
</ul>
<h3 id="environment-protection">Environment protection</h3>
<p>子議題：</p>
<ul>
<li>environment（dev / staging / prod）</li>
<li>Required reviewers</li>
<li>Wait timer</li>
<li>Secrets per-environment</li>
<li>對應 <a href="/blog/backend/06-reliability/release-gate/" data-link-title="6.8 Release Gate 與變更節奏" data-link-desc="把驗證、migration、相容性納入放行判準">6.8 Release Gate</a></li>
</ul>
<h3 id="workflow-security">Workflow security</h3>
<p>子議題：</p>
<ul>
<li>pull_request vs pull_request_target（後者有 secrets / 危險）</li>
<li>third-party action pinning（commit SHA）</li>
<li>GITHUB_TOKEN permissions（最小化）</li>
</ul>
<h3 id="deploy-workflow">Deploy workflow</h3>
<p>子議題：</p>
<ul>
<li>Deploy on tag / release</li>
<li>Rolling deploy / blue-green / canary</li>
<li>Rollback action</li>
</ul>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<h3 id="workflow-沒觸發">Workflow 沒觸發</h3>
<p>操作原則：on trigger 配置 / branch filter / paths filter。判讀：Actions tab 看 trigger event。</p>
<h3 id="permission-denied">Permission denied</h3>
<p>操作原則：GITHUB_TOKEN permissions 不夠。判讀：workflow 加 permissions: 區段。</p>
<h3 id="cache-miss">Cache miss</h3>
<p>操作原則：cache key 不穩定 / hashFiles input 變化。</p>
<h3 id="secret-沒生效">Secret 沒生效</h3>
<p>操作原則：secret name / environment 不對 / pull_request from fork 不能用 secret。</p>
<h3 id="self-hosted-runner-卡住">Self-hosted runner 卡住</h3>
<p>操作原則：runner offline / job queue 滿 / runner group 配置不對。</p>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>進階 cache / parallelism</td>
          <td><a href="/blog/backend/06-reliability/vendors/circleci/" data-link-title="CircleCI" data-link-desc="CI/CD 平台、強 cache 與 parallelism">CircleCI</a></td>
      </tr>
      <tr>
          <td>非 GitHub-hosted</td>
          <td>GitLab CI / Bitbucket Pipelines / CircleCI</td>
      </tr>
      <tr>
          <td>Self-hosted enterprise</td>
          <td>Jenkins / Buildkite / Tekton</td>
      </tr>
      <tr>
          <td>複雜 pipeline DAG</td>
          <td>Tekton / Argo Workflows</td>
      </tr>
      <tr>
          <td>Bazel-native CI</td>
          <td>BuildBuddy / EngFlow</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>各 Marketplace action 細節</li>
<li>GitHub Enterprise self-host</li>
<li>Actions pricing</li>
<li>各語言 setup-* action 細節</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<table>
  <thead>
      <tr>
          <th>案例方向</th>
          <th>對應主題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/06-reliability/cases/google/error-budget-policy-and-release-gating/" data-link-title="Google：Error Budget 政策如何決定發布節奏" data-link-desc="把 SLO 消耗量轉成 release gate，讓可靠性與交付速度共用同一套決策語言。">Google：Error Budget 與 Release Gating</a></td>
          <td>把 SLO 消耗轉成 release gate / freeze 的 workflow 入口</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/06-reliability/cases/stripe/idempotency-and-zero-downtime-migration/" data-link-title="Stripe：Idempotency 與零停機遷移的交易安全設計" data-link-desc="把 API 重試與資料遷移放在同一套安全模型，維持支付交易的一致結果。">Stripe：Idempotency 與零停機遷移</a></td>
          <td>canary deploy / staged rollout 的 CI 節奏</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/06-reliability/cases/microsoft/change-management-and-reliability-governance/" data-link-title="Microsoft：變更治理與可靠性門檻" data-link-desc="透過分層變更管理與發布閘門，降低大型 SaaS 平台的系統性回歸風險。">Microsoft：變更治理與可靠性門檻</a></td>
          <td>environment protection + approval gate 對應變更分層</td>
      </tr>
  </tbody>
</table>
<p><strong>待補 GitHub Actions customer case</strong>：大規模 monorepo Actions 採用、OIDC migration、self-hosted runner scaling 案例。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游概念：<a href="/blog/backend/06-reliability/release-gate/" data-link-title="6.8 Release Gate 與變更節奏" data-link-desc="把驗證、migration、相容性納入放行判準">6.8 Release Gate</a></li>
<li>平行 vendor：<a href="/blog/backend/06-reliability/vendors/circleci/" data-link-title="CircleCI" data-link-desc="CI/CD 平台、強 cache 與 parallelism">CircleCI</a></li>
<li>下游能力：<a href="/blog/backend/07-security-data-protection/" data-link-title="模組七：資安與資料保護" data-link-desc="以問題驅動方式擴充資安知識網：先定義服務環節問題，再以案例作為觸發式參考">07 security</a>（supply chain）、<a href="/blog/backend/05-deployment-platform/" data-link-title="模組五：部署平台與網路入口" data-link-desc="整理 Kubernetes、systemd、load balancer、container 與服務生命週期合約">5 deployment</a>（deploy gate）</li>
</ul>
]]></content:encoded></item><item><title>Kubernetes</title><link>https://tarrragon.github.io/blog/backend/05-deployment-platform/vendors/kubernetes/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/05-deployment-platform/vendors/kubernetes/</guid><description>&lt;p>Kubernetes 是 container orchestration 事實標準、承擔三個責任：workload lifecycle（pod / deployment / probe / rolling update）、cluster networking（service / ingress / DNS）、resource scheduling（resource limit / QoS / autoscaling）。設計取捨偏向「declarative + control loop + extensible」、是 cloud-native 生態的核心抽象。可自管或用 cloud managed（GKE / EKS / AKS）。&lt;/p>
&lt;p>對「多服務多實例 container orchestration、需要 rolling update / blue-green / canary、跨雲 / 跨環境統一抽象」這條路徑、Kubernetes 是首選。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>用 kubectl 部署 Deployment + Service、配置 probe / resource limit&lt;/li>
&lt;li>設計 rolling update / pod disruption budget 避免服務中斷&lt;/li>
&lt;li>選 Ingress controller（nginx / traefik / GLBC / ALB Controller）&lt;/li>
&lt;li>看懂 pod stuck / probe fail / OOMKilled / drain timeout 訊號&lt;/li>
&lt;li>評估 managed（GKE / EKS / AKS）vs 自管 vs Operator 進階場景&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑5-分鐘把-kubernetes-跑起來">最短路徑：5 分鐘把 Kubernetes 跑起來&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 1. 本機跑 kind（需先安裝 kind + docker）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">kind create cluster --name dev
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="c1"># 2. 部署 Deployment + Service&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">kubectl create deployment nginx --image&lt;span class="o">=&lt;/span>nginx:stable-alpine
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">kubectl expose deployment nginx --port&lt;span class="o">=&lt;/span>&lt;span class="m">80&lt;/span> --type&lt;span class="o">=&lt;/span>ClusterIP
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="c1"># 3. 驗證&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">kubectl get pods,svc,deploy
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">kubectl port-forward svc/nginx 8080:80&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="日常操作與決策形狀">日常操作與決策形狀&lt;/h2>
&lt;h3 id="kubectl-核心指令">kubectl 核心指令&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>資源生命週期：apply / create / delete / get / describe / logs / exec&lt;/li>
&lt;li>Rolling update：set image / rollout status / rollout undo&lt;/li>
&lt;li>Debug：events / port-forward / cp / top&lt;/li>
&lt;li>對應指令範例：&lt;code>kubectl get pods -A&lt;/code>、&lt;code>kubectl describe pod &amp;lt;name&amp;gt;&lt;/code>、&lt;code>kubectl logs -f&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="workload-設計">Workload 設計&lt;/h3>
&lt;p>Pod lifecycle 是 K8s 的核心抽象。子議題：&lt;/p></description><content:encoded><![CDATA[<p>Kubernetes 是 container orchestration 事實標準、承擔三個責任：workload lifecycle（pod / deployment / probe / rolling update）、cluster networking（service / ingress / DNS）、resource scheduling（resource limit / QoS / autoscaling）。設計取捨偏向「declarative + control loop + extensible」、是 cloud-native 生態的核心抽象。可自管或用 cloud managed（GKE / EKS / AKS）。</p>
<p>對「多服務多實例 container orchestration、需要 rolling update / blue-green / canary、跨雲 / 跨環境統一抽象」這條路徑、Kubernetes 是首選。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>用 kubectl 部署 Deployment + Service、配置 probe / resource limit</li>
<li>設計 rolling update / pod disruption budget 避免服務中斷</li>
<li>選 Ingress controller（nginx / traefik / GLBC / ALB Controller）</li>
<li>看懂 pod stuck / probe fail / OOMKilled / drain timeout 訊號</li>
<li>評估 managed（GKE / EKS / AKS）vs 自管 vs Operator 進階場景</li>
</ol>
<h2 id="最短路徑5-分鐘把-kubernetes-跑起來">最短路徑：5 分鐘把 Kubernetes 跑起來</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># 1. 本機跑 kind（需先安裝 kind + docker）</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">kind create cluster --name dev
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c1"># 2. 部署 Deployment + Service</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">kubectl create deployment nginx --image<span class="o">=</span>nginx:stable-alpine
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">kubectl expose deployment nginx --port<span class="o">=</span><span class="m">80</span> --type<span class="o">=</span>ClusterIP
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="c1"># 3. 驗證</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">kubectl get pods,svc,deploy
</span></span><span class="line"><span class="ln">10</span><span class="cl">kubectl port-forward svc/nginx 8080:80</span></span></code></pre></div><h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="kubectl-核心指令">kubectl 核心指令</h3>
<p>子議題：</p>
<ul>
<li>資源生命週期：apply / create / delete / get / describe / logs / exec</li>
<li>Rolling update：set image / rollout status / rollout undo</li>
<li>Debug：events / port-forward / cp / top</li>
<li>對應指令範例：<code>kubectl get pods -A</code>、<code>kubectl describe pod &lt;name&gt;</code>、<code>kubectl logs -f</code></li>
</ul>
<h3 id="workload-設計">Workload 設計</h3>
<p>Pod lifecycle 是 K8s 的核心抽象。子議題：</p>
<ul>
<li>Deployment（stateless）/ StatefulSet（stateful）/ DaemonSet（per-node）/ Job / CronJob</li>
<li>Pod 多 container（sidecar / init container）</li>
<li>對應 <a href="/blog/backend/05-deployment-platform/kubernetes-deployment/" data-link-title="5.2 Kubernetes 部署策略" data-link-desc="整理 deployment、probe 與 rolling update">5.2 K8s deployment</a></li>
</ul>
<h3 id="probe--resource-limit--qos">Probe / Resource limit / QoS</h3>
<p>子議題：</p>
<ul>
<li>Liveness（活著嗎）/ Readiness（接流量嗎）/ Startup（啟動完了嗎）— 三 probe 各自責任</li>
<li>Resource limit（requests / limits）+ QoS class（Guaranteed / Burstable / BestEffort）</li>
<li>對應 <a href="/blog/backend/05-deployment-platform/platform-lifecycle-contract/" data-link-title="5.6 Platform Lifecycle Contract" data-link-desc="說明 runtime、startup、readiness、liveness、shutdown 與 drain 如何組成平台生命週期合約。">Platform lifecycle contract</a></li>
</ul>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<h3 id="rolling-update--disruption-budget">Rolling update / disruption budget</h3>
<p>對應案例 <a href="/blog/backend/05-deployment-platform/cases/failure-platform-cutover-without-drain/" data-link-title="5.C9 反例：平台切流未先 Draining" data-link-desc="切流時忽略連線清退造成請求錯誤與重試風暴。">5.C9 反例：cutover without drain</a>。子議題：</p>
<ul>
<li>maxSurge / maxUnavailable 配置</li>
<li>PodDisruptionBudget 限制 voluntary disruption</li>
<li>Preemption / priority class</li>
</ul>
<h3 id="ingress--service-mesh-integration">Ingress / Service mesh integration</h3>
<p>子議題：</p>
<ul>
<li>Ingress controller 選擇（<a href="/blog/backend/05-deployment-platform/vendors/nginx/" data-link-title="nginx" data-link-desc="HTTP server / reverse proxy / LB / ingress">nginx</a> / <a href="/blog/backend/05-deployment-platform/vendors/traefik/" data-link-title="Traefik" data-link-desc="Cloud-native ingress / reverse proxy、auto-discovery">Traefik</a> / ALB Controller）</li>
<li>Gateway API（next gen Ingress）</li>
<li>Service mesh integration（<a href="/blog/backend/05-deployment-platform/vendors/envoy/" data-link-title="Envoy" data-link-desc="Cloud-native service proxy、xDS dynamic config、Istio / Gateway 底層">Envoy</a>-based Istio / Linkerd）</li>
<li>對應 <a href="/blog/backend/05-deployment-platform/cases/airbnb-istio-upgrade-governance/" data-link-title="5.C7 Airbnb：Istio 升級治理" data-link-desc="service mesh 升級在大規模環境下如何保持高可用。">5.C7 Airbnb Istio</a></li>
</ul>
<h3 id="operator-pattern--crd">Operator pattern / CRD</h3>
<p>子議題：</p>
<ul>
<li>CRD（CustomResourceDefinition）+ Controller 模式</li>
<li>Operator framework（OperatorSDK / kubebuilder）</li>
<li>常見 Operator：Prometheus / Cert-manager / Argo CD</li>
</ul>
<h3 id="managed-vs-self-managed">Managed vs self-managed</h3>
<p>對應案例 <a href="/blog/backend/05-deployment-platform/cases/tradeshift-self-managed-k8s-to-eks/" data-link-title="5.C1 Tradeshift：self-managed Kubernetes 遷移到 EKS" data-link-desc="零停機平台遷移的分段策略案例。">5.C1 Tradeshift self-managed → EKS</a>、<a href="/blog/backend/05-deployment-platform/cases/conde-nast-platform-modernization-eks/" data-link-title="5.C2 Condé Nast：EKS 平台整併與標準化" data-link-desc="多地區異質 Kubernetes 平台整併為統一控制面的案例。">5.C2 Condé Nast EKS</a>、<a href="/blog/backend/05-deployment-platform/cases/orbitera-managed-kubernetes-migration/" data-link-title="5.C3 Orbitera：遷移到 Managed Kubernetes" data-link-desc="平台重置時如何讓產品不中斷地完成編排層轉換。">5.C3 Orbitera managed K8s</a>、<a href="/blog/backend/05-deployment-platform/cases/mobileye-workloads-to-eks/" data-link-title="5.C4 Mobileye：Workloads 遷移到 EKS" data-link-desc="大規模工作負載遷移到 managed Kubernetes 的分段治理案例。">5.C4 Mobileye EKS</a>、<a href="/blog/backend/05-deployment-platform/cases/miro-managed-eks-migration/" data-link-title="5.C5 Miro：Managed EKS 遷移" data-link-desc="從自維運平台轉向 managed EKS 的組織與技術協同案例。">5.C5 Miro EKS</a>。子議題：</p>
<ul>
<li>Self-managed（kubeadm / Cluster API）的 control plane 維運成本</li>
<li>Managed（GKE / EKS / AKS）的限制（版本鎖定 / managed addon）</li>
<li>遷移路徑跟回退設計</li>
</ul>
<h3 id="multi-cluster--federation">Multi-cluster / Federation</h3>
<p>子議題：</p>
<ul>
<li>Federation v2 / Cluster API multi-cluster</li>
<li>Cross-cluster service mesh（Istio multi-cluster）</li>
<li>對應 <a href="/blog/backend/05-deployment-platform/cases/airbnb-kubernetes-cluster-scaling-evolution/" data-link-title="5.C6 Airbnb：Kubernetes 叢集擴縮演進" data-link-desc="從手動擴縮走向自動化容量治理的部署平台案例。">5.C6 Airbnb cluster scaling</a></li>
</ul>
<h3 id="cluster-autoscaling">Cluster autoscaling</h3>
<p>子議題：</p>
<ul>
<li>Horizontal Pod Autoscaler / Vertical Pod Autoscaler</li>
<li>Cluster Autoscaler / Karpenter</li>
<li>跟 <a href="/blog/backend/09-performance-capacity/" data-link-title="模組九：效能工程與容量規劃" data-link-desc="把『目前配置能撐多少、要加多少機器』變成可量化、可驗證、可改進的工程流程">09 performance capacity</a> 對照</li>
</ul>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<h3 id="pod-stuckpending--crashloopbackoff">Pod stuck（Pending / CrashLoopBackOff）</h3>
<p>操作原則：先 <code>kubectl describe pod</code> 看 events、再 <code>kubectl logs</code> 看 container 訊息。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">kubectl describe pod &lt;name&gt;           <span class="c1"># 看 Events 段的 scheduling / pull / probe 訊息</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">kubectl logs &lt;name&gt; --previous        <span class="c1"># 看 crash 前一輪的 container log</span></span></span></code></pre></div><p>判讀路徑：Pending → resource 不足 / nodeSelector 不匹配；CrashLoopBackOff → exit code + log 找原因。</p>
<h3 id="probe-failure-造成不停-restart">Probe failure 造成不停 restart</h3>
<p>操作原則：probe path / initial delay / timeout 配置錯。判讀：<code>describe pod</code> 看 probe events。</p>
<h3 id="oomkilled">OOMKilled</h3>
<p>操作原則：memory limit 太低、container 被殺。判讀：<code>describe pod</code> 看 last state reason。修法：raise limit 或優化 application memory。</p>
<h3 id="rolling-update-stuck">Rolling update stuck</h3>
<p>對應 <a href="/blog/backend/05-deployment-platform/cases/failure-platform-cutover-without-drain/" data-link-title="5.C9 反例：平台切流未先 Draining" data-link-desc="切流時忽略連線清退造成請求錯誤與重試風暴。">5.C9 反例</a>。判讀路徑：新 pod 起不來 → readiness 失敗 → 舊 pod 不下線 → 卡住。</p>
<h3 id="drain-timeout">Drain timeout</h3>
<p>操作原則：<code>kubectl drain</code> 失敗、PDB 限制太緊。判讀：<code>kubectl describe pdb</code>。</p>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>單機服務（VM / bare metal）</td>
          <td><a href="/blog/backend/05-deployment-platform/vendors/systemd/" data-link-title="systemd" data-link-desc="Linux init system、VM / 單機 service lifecycle">systemd</a></td>
      </tr>
      <tr>
          <td>Local dev / CI</td>
          <td><a href="/blog/backend/05-deployment-platform/vendors/docker/" data-link-title="Docker" data-link-desc="Container runtime / image 標準">Docker</a> Compose</td>
      </tr>
      <tr>
          <td>AWS managed runtime（不要 K8s）</td>
          <td>ECS / Fargate</td>
      </tr>
      <tr>
          <td>極簡 PaaS</td>
          <td>Cloud Run / Heroku / Fly.io</td>
      </tr>
      <tr>
          <td>替代 orchestrator</td>
          <td>Nomad / Rancher</td>
      </tr>
      <tr>
          <td>Edge / IoT 場景</td>
          <td>K3s / MicroK8s</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>完整 kubectl 指令 reference</li>
<li>YAML manifest 完整 schema</li>
<li>各 Operator 細節</li>
<li>各語言 client-go API</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<h3 id="直接相關案例">直接相關案例</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>主討論議題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/05-deployment-platform/cases/tradeshift-self-managed-k8s-to-eks/" data-link-title="5.C1 Tradeshift：self-managed Kubernetes 遷移到 EKS" data-link-desc="零停機平台遷移的分段策略案例。">5.C1 Tradeshift self-managed → EKS</a></td>
          <td>自管 K8s 遷 managed、零停機切流</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/05-deployment-platform/cases/conde-nast-platform-modernization-eks/" data-link-title="5.C2 Condé Nast：EKS 平台整併與標準化" data-link-desc="多地區異質 Kubernetes 平台整併為統一控制面的案例。">5.C2 Condé Nast EKS</a></td>
          <td>多團隊異質集群整併到單一控制面</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/05-deployment-platform/cases/orbitera-managed-kubernetes-migration/" data-link-title="5.C3 Orbitera：遷移到 Managed Kubernetes" data-link-desc="平台重置時如何讓產品不中斷地完成編排層轉換。">5.C3 Orbitera managed K8s</a></td>
          <td>平台重置不中斷產品的能力遷移</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/05-deployment-platform/cases/mobileye-workloads-to-eks/" data-link-title="5.C4 Mobileye：Workloads 遷移到 EKS" data-link-desc="大規模工作負載遷移到 managed Kubernetes 的分段治理案例。">5.C4 Mobileye EKS</a></td>
          <td>大規模 workload 分批遷 EKS</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/05-deployment-platform/cases/miro-managed-eks-migration/" data-link-title="5.C5 Miro：Managed EKS 遷移" data-link-desc="從自維運平台轉向 managed EKS 的組織與技術協同案例。">5.C5 Miro EKS</a></td>
          <td>Managed K8s 跟團隊維運模型對齊</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/05-deployment-platform/cases/airbnb-kubernetes-cluster-scaling-evolution/" data-link-title="5.C6 Airbnb：Kubernetes 叢集擴縮演進" data-link-desc="從手動擴縮走向自動化容量治理的部署平台案例。">5.C6 Airbnb cluster scaling</a></td>
          <td>手動擴縮 → 自動化容量治理</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/05-deployment-platform/cases/airbnb-istio-upgrade-governance/" data-link-title="5.C7 Airbnb：Istio 升級治理" data-link-desc="service mesh 升級在大規模環境下如何保持高可用。">5.C7 Airbnb Istio</a></td>
          <td>Service mesh 升級分批治理</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/05-deployment-platform/cases/failure-platform-cutover-without-drain/" data-link-title="5.C9 反例：平台切流未先 Draining" data-link-desc="切流時忽略連線清退造成請求錯誤與重試風暴。">5.C9 反例：cutover without drain</a></td>
          <td>Rolling update / drain 沒做的傷</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/05-deployment-platform/cases/contrast-platform-migration-by-scale/" data-link-title="5.C10 對照：規模差異下的平台遷移" data-link-desc="平台遷移策略在小中大型組織下的差異。">5.C10 規模對照</a></td>
          <td>小型 systemd → 中型 K8s → 大型 multi-cluster</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游概念：<a href="/blog/backend/05-deployment-platform/kubernetes-deployment/" data-link-title="5.2 Kubernetes 部署策略" data-link-desc="整理 deployment、probe 與 rolling update">5.2 K8s deployment</a></li>
<li>平行 vendor：<a href="/blog/backend/05-deployment-platform/vendors/docker/" data-link-title="Docker" data-link-desc="Container runtime / image 標準">Docker</a>、<a href="/blog/backend/05-deployment-platform/vendors/envoy/" data-link-title="Envoy" data-link-desc="Cloud-native service proxy、xDS dynamic config、Istio / Gateway 底層">Envoy</a></li>
<li>下游能力：<a href="/blog/backend/06-reliability/" data-link-title="模組六：可靠性驗證流程" data-link-desc="用 SRE 領域詞彙建問題節點、以服務級案例庫累積驗證脈絡，先建概念與案例庫再進實作交接">6 reliability</a>（release gate）、<a href="/blog/backend/08-incident-response/" data-link-title="模組八：事故處理與復盤" data-link-desc="用 IR 領域詞彙建問題節點、以服務級案例庫累積事故脈絡，先建概念與案例庫再進實作交接">8 incident response</a></li>
</ul>
]]></content:encoded></item><item><title>OpenTelemetry</title><link>https://tarrragon.github.io/blog/backend/04-observability/vendors/opentelemetry/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/04-observability/vendors/opentelemetry/</guid><description>&lt;p>OpenTelemetry（OTel）是 CNCF 開放標準、承擔三個責任：定義 traces / metrics / logs 的資料模型（spec）、提供 vendor-neutral 的 SDK 跟 auto-instrumentation、以 OTel Collector 作為 instrumentation 跟 backend 之間的抽象層。設計取捨偏向「抽象優於 vendor-specific feature」、避免 vendor lock-in 是核心動機。多數現代 observability 平台（Datadog / Honeycomb / Grafana Cloud / Cloud Operations）都接受 OTLP。&lt;/p>
&lt;p>本頁先給最短路徑、再展開日常 instrumentation 跟 Collector 部署、最後進階治理（sampling / semantic conventions / logs 成熟度）跟排錯。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>用 OTel SDK 或 auto-instrumentation 對應用程式做 instrumentation&lt;/li>
&lt;li>配置 OTLP exporter 把 telemetry 送到任一 backend&lt;/li>
&lt;li>部署 OTel Collector（agent / gateway 模式）作為 backend 切換抽象層&lt;/li>
&lt;li>區分 head-based vs tail-based sampling、選擇對應策略&lt;/li>
&lt;li>評估從 vendor SDK 遷移到 OTel SDK 的相容性風險&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑5-分鐘把-otel-跑起來">最短路徑：5 分鐘把 OTel 跑起來&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 1. 應用程式加 auto-instrumentation（範例：Python）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: opentelemetry-bootstrap -a install&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: opentelemetry-instrument --traces_exporter otlp --metrics_exporter otlp python app.py&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">&lt;span class="c1"># 2. 啟動 OTel Collector&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: docker run -p 4317:4317 -p 4318:4318 otel/opentelemetry-collector-contrib&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl">&lt;span class="c1"># 3. Collector 配置範例&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">9&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: otel-collector-config.yaml with otlp receiver + exporter to backend&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>最短路徑驗證 telemetry 從 app → Collector → backend 串通。實際 production 要評估 sampling、retention、cardinality。&lt;/p>
&lt;h2 id="日常操作與決策形狀">日常操作與決策形狀&lt;/h2>
&lt;h3 id="instrumentation-模式">Instrumentation 模式&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>Auto-instrumentation：Java / Python / Node / .NET / Ruby / Go 各語言成熟度不同&lt;/li>
&lt;li>Manual instrumentation：開發者寫 trace span / metric instrument&lt;/li>
&lt;li>Library instrumentation：opentelemetry-instrumentation-&lt;lib>（HTTP client / DB / framework）&lt;/li>
&lt;/ul>
&lt;h3 id="otlp-exporter-配置">OTLP exporter 配置&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>OTLP gRPC（4317）vs HTTP（4318）&lt;/li>
&lt;li>Endpoint / headers / authentication 配置&lt;/li>
&lt;li>對應指令範例：環境變數 &lt;code>OTEL_EXPORTER_OTLP_ENDPOINT&lt;/code>、&lt;code>OTEL_EXPORTER_OTLP_HEADERS&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="collector-部署模式">Collector 部署模式&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Agent&lt;/strong>：跟應用程式同 host / pod、做 local buffer + enrichment&lt;/li>
&lt;li>&lt;strong>Gateway&lt;/strong>：集中部署、跨多 agent 接收、做 sampling / routing&lt;/li>
&lt;li>&lt;strong>Sidecar&lt;/strong>：K8s sidecar pattern、跟 pod 同生命週期&lt;/li>
&lt;li>對應配置：receivers / processors / exporters pipeline&lt;/li>
&lt;/ul>
&lt;p>深入：&lt;a href="https://tarrragon.github.io/blog/backend/04-observability/vendors/opentelemetry/collector-deployment-patterns/" data-link-title="OTel Collector 部署模式：agent / gateway / sidecar 與 pipeline 設計" data-link-desc="說明 OpenTelemetry Collector 三種部署位置的責任分工、receivers/processors/exporters pipeline 設計，以及 collector 失效、記憶體壓力與 backpressure 的故障演練與容量邊界">OTel Collector 部署模式：agent / gateway / sidecar 與 pipeline 設計&lt;/a>（三種位置責任分工、pipeline 設計、collector 失效 / 記憶體壓力 / backpressure 故障演練、容量成本邊界）。&lt;/p></description><content:encoded><![CDATA[<p>OpenTelemetry（OTel）是 CNCF 開放標準、承擔三個責任：定義 traces / metrics / logs 的資料模型（spec）、提供 vendor-neutral 的 SDK 跟 auto-instrumentation、以 OTel Collector 作為 instrumentation 跟 backend 之間的抽象層。設計取捨偏向「抽象優於 vendor-specific feature」、避免 vendor lock-in 是核心動機。多數現代 observability 平台（Datadog / Honeycomb / Grafana Cloud / Cloud Operations）都接受 OTLP。</p>
<p>本頁先給最短路徑、再展開日常 instrumentation 跟 Collector 部署、最後進階治理（sampling / semantic conventions / logs 成熟度）跟排錯。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>用 OTel SDK 或 auto-instrumentation 對應用程式做 instrumentation</li>
<li>配置 OTLP exporter 把 telemetry 送到任一 backend</li>
<li>部署 OTel Collector（agent / gateway 模式）作為 backend 切換抽象層</li>
<li>區分 head-based vs tail-based sampling、選擇對應策略</li>
<li>評估從 vendor SDK 遷移到 OTel SDK 的相容性風險</li>
</ol>
<h2 id="最短路徑5-分鐘把-otel-跑起來">最短路徑：5 分鐘把 OTel 跑起來</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 1. 應用程式加 auto-instrumentation（範例：Python）</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># TODO: opentelemetry-bootstrap -a install</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="c1"># TODO: opentelemetry-instrument --traces_exporter otlp --metrics_exporter otlp python app.py</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="c1"># 2. 啟動 OTel Collector</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="c1"># TODO: docker run -p 4317:4317 -p 4318:4318 otel/opentelemetry-collector-contrib</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl">
</span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="c1"># 3. Collector 配置範例</span>
</span></span><span class="line"><span class="ln">9</span><span class="cl"><span class="c1"># TODO: otel-collector-config.yaml with otlp receiver + exporter to backend</span></span></span></code></pre></div><p>最短路徑驗證 telemetry 從 app → Collector → backend 串通。實際 production 要評估 sampling、retention、cardinality。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="instrumentation-模式">Instrumentation 模式</h3>
<p>子議題：</p>
<ul>
<li>Auto-instrumentation：Java / Python / Node / .NET / Ruby / Go 各語言成熟度不同</li>
<li>Manual instrumentation：開發者寫 trace span / metric instrument</li>
<li>Library instrumentation：opentelemetry-instrumentation-<lib>（HTTP client / DB / framework）</li>
</ul>
<h3 id="otlp-exporter-配置">OTLP exporter 配置</h3>
<p>子議題：</p>
<ul>
<li>OTLP gRPC（4317）vs HTTP（4318）</li>
<li>Endpoint / headers / authentication 配置</li>
<li>對應指令範例：環境變數 <code>OTEL_EXPORTER_OTLP_ENDPOINT</code>、<code>OTEL_EXPORTER_OTLP_HEADERS</code></li>
</ul>
<h3 id="collector-部署模式">Collector 部署模式</h3>
<p>子議題：</p>
<ul>
<li><strong>Agent</strong>：跟應用程式同 host / pod、做 local buffer + enrichment</li>
<li><strong>Gateway</strong>：集中部署、跨多 agent 接收、做 sampling / routing</li>
<li><strong>Sidecar</strong>：K8s sidecar pattern、跟 pod 同生命週期</li>
<li>對應配置：receivers / processors / exporters pipeline</li>
</ul>
<p>深入：<a href="/blog/backend/04-observability/vendors/opentelemetry/collector-deployment-patterns/" data-link-title="OTel Collector 部署模式：agent / gateway / sidecar 與 pipeline 設計" data-link-desc="說明 OpenTelemetry Collector 三種部署位置的責任分工、receivers/processors/exporters pipeline 設計，以及 collector 失效、記憶體壓力與 backpressure 的故障演練與容量邊界">OTel Collector 部署模式：agent / gateway / sidecar 與 pipeline 設計</a>（三種位置責任分工、pipeline 設計、collector 失效 / 記憶體壓力 / backpressure 故障演練、容量成本邊界）。</p>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<h3 id="auto-instrumentation-跨語言成熟度">Auto-instrumentation 跨語言成熟度</h3>
<p>子議題：</p>
<ul>
<li>Java：最成熟、auto-instrumentation 廣度最大</li>
<li>Python：成熟、覆蓋主流 framework</li>
<li>Node：成熟、async context propagation 較複雜</li>
<li>Go：較弱（runtime 不支援 monkey patching）、多用 manual</li>
<li>.NET：成熟、跟 Application Insights 對齊</li>
<li>Ruby / PHP：相對較弱、覆蓋主流 framework</li>
</ul>
<h3 id="sampling-策略">Sampling 策略</h3>
<p>對應案例 <a href="/blog/backend/04-observability/cases/datadog-otel-migration-practice/" data-link-title="4.C7 Datadog：OTel 相容遷移實務" data-link-desc="APM 採集從專有代理轉向 OTel 相容模式的治理案例。">4.C7 Datadog OTel migration</a>。子議題：</p>
<ul>
<li><strong>Head-based sampling</strong>：trace 開始時決定保留與否、低成本但 lose context</li>
<li><strong>Tail-based sampling</strong>：trace 完成後決定（依錯誤 / 延遲）、Collector 要 buffer 整個 trace</li>
<li>Sampling rate 配置（global / per-service / probabilistic）</li>
<li>對應工具：OTel Collector 的 tail_sampling processor、Refinery（Honeycomb）</li>
</ul>
<h3 id="semantic-conventions">Semantic conventions</h3>
<p>子議題：</p>
<ul>
<li>HTTP / DB / messaging / RPC 等的 attribute 命名規範</li>
<li>Resource attributes（service.name / service.version / deployment.environment）</li>
<li>Span name / status code convention</li>
<li>Migration：應用層用 OTel semantic conventions、避免 vendor-specific naming</li>
</ul>
<h3 id="logs-in-otel">Logs in OTel</h3>
<p>子議題：</p>
<ul>
<li>Logs 比 metrics / traces 較晚進 OTel spec（v1.0 較新）</li>
<li>Log signal 設計：log record 跟 span 關聯（trace_id / span_id）</li>
<li>跟 Loki / Elastic / CloudWatch 的整合</li>
<li>從現有 logging library 移轉的路徑（log-forwarding vs SDK）</li>
</ul>
<h3 id="vendor-sdk-vs-otel-sdk-遷移">Vendor SDK vs OTel SDK 遷移</h3>
<p>對應案例 <a href="/blog/backend/04-observability/cases/xray-to-opentelemetry-migration/" data-link-title="4.C4 AWS：X-Ray 到 OpenTelemetry 轉換" data-link-desc="觀測儀表從 vendor-specific SDK 轉向 OpenTelemetry 的治理重點。">4.C4 X-Ray to OpenTelemetry</a> 與 <a href="/blog/backend/04-observability/cases/datadog-otel-migration-practice/" data-link-title="4.C7 Datadog：OTel 相容遷移實務" data-link-desc="APM 採集從專有代理轉向 OTel 相容模式的治理案例。">4.C7 Datadog OTel</a>。子議題：</p>
<ul>
<li>動機：避免 vendor lock-in、多 backend 並存、開源治理</li>
<li>風險：vendor-specific feature 損失（profiling / RUM 整合）</li>
<li>遷移路徑：dual ship → cutover → cleanup</li>
<li>對應 <a href="/blog/backend/04-observability/cases/failure-otel-migration-signal-drift/" data-link-title="4.C9 反例：OTel 遷移後訊號漂移" data-link-desc="雙軌採集未對齊導致告警與 SLO 判讀失真。">4.C9 反例：OTel migration signal drift</a></li>
</ul>
<h3 id="resource-detection">Resource detection</h3>
<p>子議題：</p>
<ul>
<li>自動偵測 cloud provider（AWS / GCP / Azure）resource attributes</li>
<li>K8s resource detector（pod / namespace / cluster）</li>
<li>Container resource detector</li>
<li>對應配置：<code>OTEL_RESOURCE_ATTRIBUTES</code></li>
</ul>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<h3 id="telemetry-沒到-backend">Telemetry 沒到 backend</h3>
<p>操作原則：先確認 SDK 配置正確、再看 Collector 是否收到、最後看 exporter 是否成功。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># TODO: 設 OTEL_LOG_LEVEL=debug 看 SDK 內部 log</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># TODO: 看 Collector internal metrics（zPages / Prometheus exporter）</span></span></span></code></pre></div><p>判讀路徑：SDK → Collector → backend、三段各自獨立、要逐層 isolate。</p>
<h3 id="cardinality-explosion">Cardinality explosion</h3>
<p>操作原則：metric attribute 含 high-cardinality 值（user_id / session_id）會爆 backend 成本。判讀：看 backend 的 series 數量、找 attribute 來源。</p>
<h3 id="trace-span-gap">Trace span gap</h3>
<p>操作原則：trace 不完整、看 context propagation 是否在跨 service / 跨 thread 邊界丟失。</p>
<h3 id="auto-instrumentation-不生效">Auto-instrumentation 不生效</h3>
<p>操作原則：確認 SDK 版本跟 library version 對應、agent 啟動方式正確。對應 <a href="/blog/backend/04-observability/cases/datadog-otel-migration-practice/" data-link-title="4.C7 Datadog：OTel 相容遷移實務" data-link-desc="APM 採集從專有代理轉向 OTel 相容模式的治理案例。">4.C7 Datadog OTel migration</a> 的踩坑經驗。</p>
<h3 id="sampling-過頭--不足">Sampling 過頭 / 不足</h3>
<p>操作原則：sampling rate 跟 backend 預算 + debug 需求對齊。判讀：debug 時找不到 trace（sampling 過頭）vs backend 成本爆（sampling 不足）。</p>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>需要 metrics 後端</td>
          <td><a href="/blog/backend/04-observability/vendors/prometheus/" data-link-title="Prometheus" data-link-desc="Pull-based metrics 主流 OSS、PromQL 與 alerting">Prometheus</a> / Mimir</td>
      </tr>
      <tr>
          <td>需要 SaaS APM 整合</td>
          <td><a href="/blog/backend/04-observability/vendors/datadog/" data-link-title="Datadog" data-link-desc="All-in-one SaaS 觀測平台、APM / Logs / Metrics / RUM / Security">Datadog</a> / New Relic</td>
      </tr>
      <tr>
          <td>需要 logs 後端</td>
          <td><a href="/blog/backend/04-observability/vendors/elastic-stack/" data-link-title="Elastic Stack" data-link-desc="ELK：Elasticsearch / Logstash / Kibana &#43; Beats / APM">Elastic Stack</a> / Loki</td>
      </tr>
      <tr>
          <td>需要 high-cardinality debug</td>
          <td><a href="/blog/backend/04-observability/vendors/honeycomb/" data-link-title="Honeycomb" data-link-desc="High-cardinality observability 平台、events-based 模型">Honeycomb</a></td>
      </tr>
      <tr>
          <td>AWS-native</td>
          <td><a href="/blog/backend/04-observability/vendors/aws-cloudwatch/" data-link-title="AWS CloudWatch" data-link-desc="AWS 原生觀測性服務、Logs / Metrics / Traces (X-Ray)">CloudWatch</a> + X-Ray</td>
      </tr>
      <tr>
          <td>GCP-native</td>
          <td><a href="/blog/backend/04-observability/vendors/gcp-cloud-operations/" data-link-title="GCP Cloud Operations" data-link-desc="GCP 原生觀測性套件（前 Stackdriver）：Logging / Monitoring / Trace / Profiler">Cloud Operations</a></td>
      </tr>
      <tr>
          <td>Error tracking</td>
          <td><a href="/blog/backend/04-observability/vendors/sentry/" data-link-title="Sentry" data-link-desc="Error tracking 主流、APM / Profiling / Session Replay 擴展">Sentry</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>各語言 SDK 完整 API</li>
<li>OTLP protocol binary format</li>
<li>各 backend 的 OTel 整合細節（見各 backend vendor 頁）</li>
<li>OTel project governance / sig 細節</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<h3 id="直接相關案例">直接相關案例</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>主討論議題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/xray-to-opentelemetry-migration/" data-link-title="4.C4 AWS：X-Ray 到 OpenTelemetry 轉換" data-link-desc="觀測儀表從 vendor-specific SDK 轉向 OpenTelemetry 的治理重點。">4.C4 X-Ray to OTel</a></td>
          <td>從 vendor SDK 遷出 OTel</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/cloud-trace-otlp-adoption/" data-link-title="4.C5 Google Cloud：Cloud Trace 導入 OTLP 入口" data-link-desc="觀測平台從專有入口擴展到 OTLP 標準通道的案例。">4.C5 Cloud Trace OTLP</a></td>
          <td>GCP Cloud Trace 接受 OTLP</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/adot-eks-observability-pipeline-migration/" data-link-title="4.C6 AWS：ADOT on EKS 管線遷移" data-link-desc="從分散式 agent 組合轉成 OpenTelemetry collector 管線治理。">4.C6 ADOT EKS pipeline</a></td>
          <td>AWS Distro for OTel + EKS</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/datadog-otel-migration-practice/" data-link-title="4.C7 Datadog：OTel 相容遷移實務" data-link-desc="APM 採集從專有代理轉向 OTel 相容模式的治理案例。">4.C7 Datadog OTel migration</a></td>
          <td>OTLP ingestion / vendor SDK 移轉</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/failure-otel-migration-signal-drift/" data-link-title="4.C9 反例：OTel 遷移後訊號漂移" data-link-desc="雙軌採集未對齊導致告警與 SLO 判讀失真。">4.C9 OTel migration signal drift</a></td>
          <td>（反例）雙軌遷移期的 signal 漂移</td>
      </tr>
  </tbody>
</table>
<h3 id="跨-vendor-對照">跨 vendor 對照</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>對 OTel 的對應</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/airbnb-observability-k8s-scale-signals/" data-link-title="4.C8 Airbnb：Kubernetes 規模化下的觀測訊號治理" data-link-desc="叢集擴縮與工作負載變動如何回寫觀測模型。">4.C8 Airbnb K8s scale signals</a></td>
          <td>K8s 規模化下 OTel Collector 拓撲 / 資源訊號分層</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/contrast-observability-rollout-by-scale/" data-link-title="4.C10 對照：規模差異下的觀測遷移" data-link-desc="觀測遷移在不同規模團隊下的流程與風險差異。">4.C10 規模對照</a></td>
          <td>小型直接 SDK / 中型加 Collector / 大型 multi-backend</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游概念：<a href="/blog/backend/04-observability/telemetry-data-quality/" data-link-title="4.17 Telemetry Data Quality" data-link-desc="把 missing signal、schema drift、sampling bias 與 timestamp skew 變成資料品質問題">4.17 Telemetry Data Quality</a></li>
<li>平行 vendor：所有 04 vendor 都可作 OTel backend</li>
<li>下游能力：<a href="/blog/backend/04-observability/observability-evidence-package/" data-link-title="4.20 Observability Evidence Package" data-link-desc="把 log、metric、trace、audit 與資料品質限制包成可交接證據">4.20 Observability Evidence Package</a></li>
</ul>
]]></content:encoded></item><item><title>PagerDuty</title><link>https://tarrragon.github.io/blog/backend/08-incident-response/vendors/pagerduty/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/08-incident-response/vendors/pagerduty/</guid><description>&lt;p>PagerDuty 是 on-call / alerting 的事實標準 SaaS、承擔三個責任：alert routing + escalation policy + schedule、incident workflow + response play + runbook automation、postmortem 整合（Jeli 收購）。從 paging 工具演化成完整 IR 平台。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>PagerDuty 的核心定位是 &lt;em>signal → human → action&lt;/em> 的中介層、把 alert source（觀測、SIEM、合成監控、cloud control plane）變成具體某個人手機震動 + 24 小時內可追蹤的 incident timeline。它是 &lt;em>routing engine + on-call schedule 的事實標準&lt;/em>、定位有別於 alert source 和溝通平台。&lt;/p>
&lt;p>跟上游 07 章的 detection stack 是直接 wire：&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &amp;#43; indexer &amp;#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk&lt;/a> ES app 產生的 Notable Event 透過 &lt;em>Splunk-PagerDuty integration&lt;/em> 或 SOAR playbook 變成 PagerDuty incident、severity 直接帶過來；&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &amp;#43; DDoS &amp;#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF&lt;/a> 的高分 rate-limit / bot block 透過 webhook 進 PagerDuty Event API v2、再經 Event Orchestration 判斷是丟 SecOps schedule 還是 platform schedule。這條鏈最常壞在 &lt;em>severity 對應不一致&lt;/em>（Splunk medium 在 PagerDuty 變 P1）、跟 &lt;em>integration 沒 deduplication key&lt;/em>（一次 attack 100 個 Notable Event 各起 100 個 incident）。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/vendors/opsgenie/" data-link-title="Opsgenie" data-link-desc="Atlassian on-call、跟 Jira / Statuspage 套件整合、JSM Premium migration 議題">Opsgenie&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/vendors/incident-io/" data-link-title="incident.io" data-link-desc="Slack-native IR 平台、整合 paging / response / retro">incident.io&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/vendors/grafana-oncall/" data-link-title="Grafana OnCall" data-link-desc="OSS-friendly on-call 平台、Grafana Labs 維護、Apache 2.0、Grafana IRM bundle 把 OnCall &amp;#43; Incident 收進一個 alert-to-resolve 流程">Grafana OnCall&lt;/a> 的差異在 &lt;em>ecosystem 跟 IR 模型&lt;/em> — PagerDuty 走 enterprise + AIOps + Process Automation 重資料堆疊、incident.io 走 Slack-native + collab-first、Opsgenie 綁 Atlassian、Grafana OnCall 是 OSS 自管。選 PagerDuty 的核心理由通常是 &lt;em>AIOps + Process Automation + Jeli postmortem 整合的 ecosystem maturity&lt;/em>、不是 paging 功能本身。&lt;/p></description><content:encoded><![CDATA[<p>PagerDuty 是 on-call / alerting 的事實標準 SaaS、承擔三個責任：alert routing + escalation policy + schedule、incident workflow + response play + runbook automation、postmortem 整合（Jeli 收購）。從 paging 工具演化成完整 IR 平台。</p>
<h2 id="服務定位">服務定位</h2>
<p>PagerDuty 的核心定位是 <em>signal → human → action</em> 的中介層、把 alert source（觀測、SIEM、合成監控、cloud control plane）變成具體某個人手機震動 + 24 小時內可追蹤的 incident timeline。它是 <em>routing engine + on-call schedule 的事實標準</em>、定位有別於 alert source 和溝通平台。</p>
<p>跟上游 07 章的 detection stack 是直接 wire：<a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> ES app 產生的 Notable Event 透過 <em>Splunk-PagerDuty integration</em> 或 SOAR playbook 變成 PagerDuty incident、severity 直接帶過來；<a href="/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &#43; DDoS &#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF</a> 的高分 rate-limit / bot block 透過 webhook 進 PagerDuty Event API v2、再經 Event Orchestration 判斷是丟 SecOps schedule 還是 platform schedule。這條鏈最常壞在 <em>severity 對應不一致</em>（Splunk medium 在 PagerDuty 變 P1）、跟 <em>integration 沒 deduplication key</em>（一次 attack 100 個 Notable Event 各起 100 個 incident）。</p>
<p>跟 <a href="/blog/backend/08-incident-response/vendors/opsgenie/" data-link-title="Opsgenie" data-link-desc="Atlassian on-call、跟 Jira / Statuspage 套件整合、JSM Premium migration 議題">Opsgenie</a> / <a href="/blog/backend/08-incident-response/vendors/incident-io/" data-link-title="incident.io" data-link-desc="Slack-native IR 平台、整合 paging / response / retro">incident.io</a> / <a href="/blog/backend/08-incident-response/vendors/grafana-oncall/" data-link-title="Grafana OnCall" data-link-desc="OSS-friendly on-call 平台、Grafana Labs 維護、Apache 2.0、Grafana IRM bundle 把 OnCall &#43; Incident 收進一個 alert-to-resolve 流程">Grafana OnCall</a> 的差異在 <em>ecosystem 跟 IR 模型</em> — PagerDuty 走 enterprise + AIOps + Process Automation 重資料堆疊、incident.io 走 Slack-native + collab-first、Opsgenie 綁 Atlassian、Grafana OnCall 是 OSS 自管。選 PagerDuty 的核心理由通常是 <em>AIOps + Process Automation + Jeli postmortem 整合的 ecosystem maturity</em>、不是 paging 功能本身。</p>
<p>關鍵張力：<em>alert volume</em> ↔ <em>responder burnout</em> 是 PagerDuty 客戶最常見 trade-off。為了「不漏 alert」把 grouping / deduplication 設很寬、結果 on-call 一週被叫醒 20 次、3 個月後人員流失。要看清楚自己 <em>容忍多少漏報換多少 responder sustainability</em>、不是把 alert source 全開到 PagerDuty 當保險。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>PagerDuty 在 alert pipeline 中承擔哪一段（routing / schedule / incident workflow）、哪些要外接（Slack 通訊、Jeli postmortem、Process Automation 對接 runbook）</li>
<li>Service / escalation policy / schedule 的 ownership 設計（誰建 service、誰改 escalation、誰能 override schedule）</li>
<li>Event Orchestration 的 deduplication / grouping / dynamic routing 設計、跟上游 SIEM 的 severity mapping 一致性</li>
<li>何時用 PagerDuty、何時走 Opsgenie / incident.io / Grafana OnCall 的取捨</li>
</ol>
<p>本頁不教 PagerDuty console 操作步驟、也不列 pricing tier — 那些 vendor 官方文件已經完整。本頁重點在 <em>判讀問題</em>：怎麼看一個 PagerDuty deployment 健康與否、哪些 config 是 high blast radius、跟上下游（07 detection / 04 observability / Jeli postmortem）怎麼接。</p>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 PagerDuty deployment 是否健康、最少看四件事：</p>
<ul>
<li><strong>誰能 ack / escalate / resolve</strong>：on-call rotation 有沒有人、escalation policy 第二層第三層是不是同一個人、有沒有 break-glass 流程（primary 失聯時誰補位）。schedule override 是否走 PR / approval、還是 console 直改沒留痕。</li>
<li><strong>Escalation policy 設計</strong>：每層 escalation timeout（5min / 10min / 15min）是否符合 SLO、是否有 <em>無人 ack 自動上報主管</em> 規則、跨時區 schedule 是否避免半夜 page 給 off-shift 區域</li>
<li><strong>Event Orchestration 設定</strong>：alert deduplication key 是否正確（同一 host + 同一 alert type 合併）、grouping rule 是否避免 alert storm、dynamic routing 是否依 service / severity / time 分軌到不同 schedule</li>
<li><strong>SOAR / Process Automation playbook 觸發點</strong>：哪些 incident 自動觸發 runbook（restart / rotate token / scale up）、approval gate 是否設在高風險動作、playbook 失敗有沒有 fallback 回 human page</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/08-incident-response/drills-and-oncall-readiness/" data-link-title="8.6 演練與值班能力建設" data-link-desc="用演練與值班訓練提升事故反應品質">Drills and On-call Readiness</a> 的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="service--team--escalation">Service / team / escalation</h3>
<p>PagerDuty 的 <em>service</em> 對應一個應用 / component、是 incident 的最小 ownership 單位。一個 service 綁一個 <em>escalation policy</em>（N 層、每層 X 分鐘 timeout）、一個 <em>schedule</em>（rotation + override）。production 部署用 <em>Terraform PagerDuty provider</em> 進版控、不在 console 直改 — 因為 schedule / escalation 是高 blast radius config、誤改可能讓半夜 alert 漏掉。Service 通常按 Service Ownership 對齊組織結構、不是按技術 stack 切：把一個微服務 stack 拆成 10 個 service 看似乾淨、但 incident 起來時 responder 要同時 ack 10 個 incident 對 SLO 不利、合理粒度通常是 <em>一個 product team 一個 service</em>。</p>
<h3 id="event-orchestration--response-play">Event Orchestration + Response Play</h3>
<p>Event Orchestration 是 alert → incident 的工程化路由層、處理 <em>deduplication / grouping / dynamic routing</em> 三件事。deduplication 用 <em>dedup_key</em>（同 host + 同 check type 合併、避免 100 個 alert 起 100 個 incident）、grouping 用 <em>time window + tag</em>（同一服務 5min 內多個 alert 合一）、dynamic routing 依 severity / time / service tag 分軌到不同 schedule。Response Play 則是 incident 起來後自動執行的動作 bundle — page additional responder、建 Slack channel、發 status page、call conference bridge。Response Play 應該走 PR review、不能 console 直加 — 一個誤設的 Response Play 可能在每個 P1 自動 page 整個 leadership。</p>
<h3 id="severity-mapping-跟上游一致性">Severity mapping 跟上游一致性</h3>
<p>上游 source（Splunk Notable Event / Datadog monitor / Cloudflare WAF alert）的 severity 跟 PagerDuty incident urgency 要 <em>對應表化</em>、不是各自為政。常見錯位：Splunk medium 在 PagerDuty 變成 high urgency（半夜被吵醒）、或 Cloudflare 高分 bot block 進來只標 low（真實 attack 漏報）。實務做法是寫一張 <em>severity translation table</em> 進 Event Orchestration、source severity → PagerDuty urgency 一對一寫死、變更走 PR review。對應 <a href="/blog/backend/08-incident-response/incident-severity-trigger/" data-link-title="8.1 事故分級與啟動條件" data-link-desc="建立統一分級標準與事故啟動門檻">Incident Severity Trigger</a> 的判讀標準。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>PagerDuty</th>
          <th>Opsgenie</th>
          <th>incident.io</th>
          <th>Grafana OnCall</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>定位</td>
          <td>Enterprise IR platform、AIOps + automation</td>
          <td>Atlassian 生態 paging</td>
          <td>Slack-native IR collaboration</td>
          <td>OSS / 自管 OnCall</td>
      </tr>
      <tr>
          <td>部署模型</td>
          <td>SaaS only</td>
          <td>SaaS（Atlassian Cloud）</td>
          <td>SaaS only</td>
          <td>Self-hosted（Grafana stack）/ SaaS</td>
      </tr>
      <tr>
          <td>Alert routing</td>
          <td>Event Orchestration（dedup + group + dyn）</td>
          <td>Alert policy + integration</td>
          <td>Slack-first、簡化 routing</td>
          <td>Integrations + routes（OSS 等效）</td>
      </tr>
      <tr>
          <td>Schedule</td>
          <td>強 — rotation / override / multi-tz</td>
          <td>強 — 跟 Jira / Confluence 整合</td>
          <td>中 — schedule 較簡化</td>
          <td>中 — 基本 rotation</td>
      </tr>
      <tr>
          <td>Workflow / Play</td>
          <td>Response Play + Process Automation</td>
          <td>Atlassian Automation</td>
          <td>Slack-driven workflow（強）</td>
          <td>基本 webhook</td>
      </tr>
      <tr>
          <td>Postmortem</td>
          <td>Jeli（收購、深度整合）</td>
          <td>Confluence template</td>
          <td>內建 postmortem + learning loop</td>
          <td>外接</td>
      </tr>
      <tr>
          <td>AIOps</td>
          <td>Machine Learning alert clustering、PRCC</td>
          <td>基本 grouping</td>
          <td>無</td>
          <td>無</td>
      </tr>
      <tr>
          <td>Pricing</td>
          <td>Per-user + 按 feature tier、enterprise 貴</td>
          <td>按 user、Atlassian bundle 划算</td>
          <td>Per-responder、中等</td>
          <td>OSS 免費 / Grafana Cloud 按 active</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>Enterprise + 多 service + AIOps 需求</td>
          <td>Atlassian 已用 + 預算敏感</td>
          <td>Startup / mid-size + Slack-first 文化</td>
          <td>OSS-friendly + Grafana stack 已用</td>
      </tr>
      <tr>
          <td>退場成本</td>
          <td>高 — schedule / policy / Play 量多</td>
          <td>中 — Atlassian 內可遷</td>
          <td>中 — Slack 工作流綁深</td>
          <td>低 — OSS、可帶走 config</td>
      </tr>
  </tbody>
</table>
<p>選 PagerDuty 的核心訴求：<em>多 service 大組織 + AIOps 對 alert storm 有 ROI + Process Automation 對接 runbook + Jeli postmortem 整合需求</em>。Slack-first 小組直接 incident.io、Atlassian-heavy 走 Opsgenie、預算敏感 OSS 走 Grafana OnCall。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Event Orchestration deduplication / grouping</strong>：deduplication 跟 grouping 是兩個層次 — dedup 是 <em>同一事件多次發送只算一個</em>（用 dedup_key）、grouping 是 <em>多個相關事件合成一個 incident</em>（用 time window + service / tag）。設定太寬會漏 alert（不同 root cause 被合併、漏報重要事件）、設定太窄會 alert storm。實務做法是 <em>先寬後窄</em> — 上線初期用較寬 grouping 觀察、再依 false-merge 案例收窄。</p>
<p><strong>AIOps Machine Learning</strong>：PagerDuty AIOps 用 ML 做 <em>alert clustering + probable root cause + change correlation</em> — 多個 alert 自動歸成 cluster、推測 root cause、跟近期 deploy / config change 對照。風險是 <em>黑箱</em>：ML 把不相關 alert 合一、SOC analyst 看不到原始事件就 ack；或把真實 incident 歸到 noise cluster。production 應該開、但 <em>保留 manual ungroup 機制 + 定期 audit cluster accuracy</em>。</p>
<p><strong>Process Automation + Splunk SOAR 整合</strong>：PagerDuty Process Automation（前 Rundeck）做 runbook 自動執行 — restart / scale / rollback / rotate token。對接 <a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk SOAR</a> 形成 <em>incident enrichment + auto-remediation</em> 鏈：Splunk SOAR 在 incident 起來時自動拉 context（user / host / IP recent activity）寫進 PagerDuty incident note、再依 playbook 觸發 PagerDuty Process Automation 做動作。高風險動作（disable account、rotate prod credential）必走 <em>approval gate</em>、不能 fire-and-forget。</p>
<p><strong>Jeli postmortem 整合（2023 收購後）</strong>：PagerDuty incident resolve 後可以一鍵 import 進 Jeli、自動帶 timeline / responder list / Slack transcript、開始做 interview + narrative。對應 <a href="/blog/backend/08-incident-response/vendors/jeli/" data-link-title="Jeli" data-link-desc="Post-incident learning 平台、2023 被 PagerDuty 收購、強調 interview-driven narrative 而非 timeline-only retro">Jeli vendor</a> — Jeli 走「learning from incident」方法論、不是只生 root cause report、強調 <em>near miss</em> 跟 <em>human factor</em> 也要分析。</p>
<p><strong>Service ownership / Service Standards</strong>：PagerDuty Service Standards 把 service 的 <em>escalation policy / runbook link / business criticality / oncall coverage</em> 做成 checklist、organization 可以看哪些 service 沒達標。對 platform team 是治理工具、避免某 service「沒人 oncall 但有 alert source」。配對 <a href="/blog/backend/08-incident-response/repeated-incident-toil/" data-link-title="8.13 Repeated Incident 與 Toil 治理" data-link-desc="把同型事故反覆發生與重複手動修復作為工程化治理對象">Repeated Incident Toil</a> 的反模式：service 沒人 own 但 alert 一直響、最後變 noise 被全部靜音、真實 incident 進來時也漏報。</p>
<p><strong>Status page 整合</strong>：PagerDuty incident 可以自動同步到 <a href="/blog/backend/08-incident-response/vendors/atlassian-statuspage/" data-link-title="Atlassian Statuspage" data-link-desc="公開狀態頁 SaaS、Atlassian 出品、enterprise polish &#43; Atlassian 生態整合、subscriber notification &#43; component dependency 是核心責任">Atlassian Statuspage</a> / <a href="/blog/backend/08-incident-response/vendors/instatus/" data-link-title="Instatus" data-link-desc="輕量 status page SaaS、現代 UI、價格敏感替代">Instatus</a> 對外 status page、但 <em>自動同步</em> 是雙刃刀 — internal P1 不一定是 customer-facing、誤公告影響品牌。實務做法是 <em>只同步 customer-facing severity 的 incident</em>、用 Event Orchestration 加 tag (<code>customer_facing: true</code>) 才觸發 statuspage update、其他 incident 走人工 publish。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Escalation 漏配 / primary 失聯沒人補</strong>：escalation policy 第二層第三層是同一個人、或 off-shift 時無人 ack — 改成跨層異人 + break-glass policy（自動 page manager-on-call）+ 半年 audit</li>
<li><strong>Schedule 跨時區算錯</strong>：把 UTC schedule 套到亞太工程師、結果半夜 page off-shift — schedule 用 follow-the-sun rotation、或在 schedule layer 加 time restriction</li>
<li><strong>Event Orchestration deduplication 太寬</strong>：不同 root cause 的 alert 被 dedup 成同一 incident、漏報 — 收窄 dedup_key（加 service + alert_type）、保留 manual unmerge</li>
<li><strong>Event Orchestration grouping 太窄</strong>：同一事故 100 個 alert 各起 100 個 incident、alert storm、on-call 看不完 — 放寬 time window grouping、或開 AIOps clustering</li>
<li><strong>AIOps ML 黑箱誤合</strong>：真實 incident 被歸到 noise cluster、responder 沒看到 — 開 ML cluster audit dashboard、每月 sample review、保留 manual ungroup 機制</li>
<li><strong>Slack notification stale</strong>：PagerDuty Slack app token 過期 / channel 改名、incident 通知沒進 Slack — Slack integration health check + fallback channel + on-call 應該收 mobile push 不只看 Slack</li>
<li><strong>Response Play 自動誤觸</strong>：Play 設成 P1 自動 page leadership、結果一個 noise P1 把整個 C-level 半夜叫起來 — Play 必走 PR review、defaults to <em>additional engineer</em> not <em>leadership</em>、leadership page 走人工升級</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<p>PagerDuty 不是所有 IR 場景都適合：</p>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Atlassian 生態</td>
          <td><a href="/blog/backend/08-incident-response/vendors/opsgenie/" data-link-title="Opsgenie" data-link-desc="Atlassian on-call、跟 Jira / Statuspage 套件整合、JSM Premium migration 議題">Opsgenie</a></td>
      </tr>
      <tr>
          <td>OSS / 預算敏感</td>
          <td><a href="/blog/backend/08-incident-response/vendors/grafana-oncall/" data-link-title="Grafana OnCall" data-link-desc="OSS-friendly on-call 平台、Grafana Labs 維護、Apache 2.0、Grafana IRM bundle 把 OnCall &#43; Incident 收進一個 alert-to-resolve 流程">Grafana OnCall</a></td>
      </tr>
      <tr>
          <td>Slack-first IR</td>
          <td><a href="/blog/backend/08-incident-response/vendors/incident-io/" data-link-title="incident.io" data-link-desc="Slack-native IR 平台、整合 paging / response / retro">incident.io</a></td>
      </tr>
      <tr>
          <td>Microsoft Teams</td>
          <td><a href="/blog/backend/08-incident-response/vendors/firehydrant/" data-link-title="FireHydrant" data-link-desc="IR &#43; retrospective 平台、Slack / Teams 整合、service catalog &#43; runbook automation 為核心">FireHydrant</a></td>
      </tr>
      <tr>
          <td>No-code workflow + AI</td>
          <td><a href="/blog/backend/08-incident-response/vendors/rootly/" data-link-title="Rootly" data-link-desc="IR 自動化平台、no-code workflow &#43; AI investigation、Slack-native &#43; 200&#43; integration">Rootly</a></td>
      </tr>
      <tr>
          <td>Postmortem only</td>
          <td><a href="/blog/backend/08-incident-response/vendors/jeli/" data-link-title="Jeli" data-link-desc="Post-incident learning 平台、2023 被 PagerDuty 收購、強調 interview-driven narrative 而非 timeline-only retro">Jeli</a></td>
      </tr>
      <tr>
          <td>Status page only</td>
          <td><a href="/blog/backend/08-incident-response/vendors/atlassian-statuspage/" data-link-title="Atlassian Statuspage" data-link-desc="公開狀態頁 SaaS、Atlassian 出品、enterprise polish &#43; Atlassian 生態整合、subscriber notification &#43; component dependency 是核心責任">Atlassian Statuspage</a> / <a href="/blog/backend/08-incident-response/vendors/instatus/" data-link-title="Instatus" data-link-desc="輕量 status page SaaS、現代 UI、價格敏感替代">Instatus</a></td>
      </tr>
  </tbody>
</table>
<p>選對需求形狀比選 vendor 重要：startup 一開始走 Slack-native incident.io、規模上來 alert storm 多了再評 PagerDuty AIOps、Atlassian 重度用戶 Opsgenie bundle 划算。</p>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>各 integration 完整 setup / Pricing 細節 / AIOps ML 內部演算法</li>
<li>Response Play 跟 Process Automation 的具體 playbook 實作（Rundeck DSL）</li>
<li>Jeli 的 narrative + interview workflow（屬 postmortem 章節）</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>PagerDuty 公開 customer 多為大型 SaaS / 平台、下列案例可作為「paging 設計如何影響事故 detect → ack → mitigate 時間 + 怎麼跟 07 detection 鏈起來」的閱讀脈絡：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 PagerDuty 的關係（對照啟示）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/08-incident-response/cases/github/" data-link-title="GitHub" data-link-desc="GitHub 重大事故時間線與架構脈絡">GitHub cases</a></td>
          <td>大型平台事故的多輪 paging 與輪值、Event Orchestration grouping 設計 + 跨 service escalation</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/08-incident-response/cases/cloudflare/" data-link-title="Cloudflare" data-link-desc="Cloudflare 全球 edge 事故時間線與架構脈絡">Cloudflare cases</a></td>
          <td>控制面 vs data plane 的 paging 分軌、不同 severity 走不同 schedule + Response Play</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/08-incident-response/cases/slack/" data-link-title="Slack" data-link-desc="Slack 通訊服務事故與外部狀態頁設計">Slack cases</a></td>
          <td>通訊平台失效時 paging 通道的退路、PagerDuty mobile push 是 Slack-first IR 的 fallback</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/08-incident-response/cases/datadog/" data-link-title="Datadog" data-link-desc="Datadog 監控服務事故、客戶觀測落差">Datadog cases</a></td>
          <td>觀測平台事故的 self-paging 與外部 fallback、AIOps clustering 避免 self-incident alert storm</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/microsoft-storm-0558-2023-signing-key-chain/" data-link-title="7.R7.1.5 Microsoft Storm-0558 2023：簽章金鑰鏈與郵件存取" data-link-desc="從簽章金鑰保護失效到雲端郵件存取，拆解身分信任鏈的關鍵控制點">Microsoft Storm-0558 Signing Key Chain</a></td>
          <td>Splunk Notable Event 進 PagerDuty incident、SOAR playbook 自動 rotate Azure AD app credential、approval gate 在 force re-auth 動作</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/data-exfiltration/snowflake-2024-credential-abuse/" data-link-title="7.R7.4.2 Snowflake 2024：憑證濫用與資料竊取" data-link-desc="外洩憑證與 MFA 缺口如何在資料平台形成高風險外送事件">Snowflake 2024 Credential Abuse</a></td>
          <td>異常 query volume 進 PagerDuty、Process Automation 觸發 Snowflake user disable + IP block、Response Play 同步 page legal / customer success</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/08-incident-response/cases/microsoft-365/2023-suite-wide-authentication-incident/" data-link-title="Microsoft 365：套件級身分驗證事故" data-link-desc="企業套件在身份依賴失效時，如何同步處理跨產品影響與對外揭露。">Microsoft 365 2023 Auth Incident</a></td>
          <td>認證鏈事故跨多 service、Event Orchestration grouping + dynamic routing 把 auth alert 集中到 identity team schedule</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/08-incident-response/drills-and-oncall-readiness/" data-link-title="8.6 演練與值班能力建設" data-link-desc="用演練與值班訓練提升事故反應品質">Drills and On-call Readiness</a>、<a href="/blog/backend/08-incident-response/incident-severity-trigger/" data-link-title="8.1 事故分級與啟動條件" data-link-desc="建立統一分級標準與事故啟動門檻">Incident Severity Trigger</a></li>
<li>平行：<a href="/blog/backend/08-incident-response/vendors/opsgenie/" data-link-title="Opsgenie" data-link-desc="Atlassian on-call、跟 Jira / Statuspage 套件整合、JSM Premium migration 議題">Opsgenie</a>、<a href="/blog/backend/08-incident-response/vendors/grafana-oncall/" data-link-title="Grafana OnCall" data-link-desc="OSS-friendly on-call 平台、Grafana Labs 維護、Apache 2.0、Grafana IRM bundle 把 OnCall &#43; Incident 收進一個 alert-to-resolve 流程">Grafana OnCall</a>、<a href="/blog/backend/08-incident-response/vendors/incident-io/" data-link-title="incident.io" data-link-desc="Slack-native IR 平台、整合 paging / response / retro">incident.io</a></li>
<li>下游：<a href="/blog/backend/08-incident-response/incident-decision-log/" data-link-title="8.19 Incident Decision Log" data-link-desc="把事中假設、決策、證據、回退條件與責任人留下可復盤紀錄">Incident Decision Log</a>、<a href="/blog/backend/08-incident-response/vendors/jeli/" data-link-title="Jeli" data-link-desc="Post-incident learning 平台、2023 被 PagerDuty 收購、強調 interview-driven narrative 而非 timeline-only retro">Jeli</a>（postmortem 接手）</li>
<li>跨類：<a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a>（Notable Event source）、<a href="/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &#43; DDoS &#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF</a>（WAF alert source）</li>
<li>官方：<a href="https://support.pagerduty.com/">PagerDuty Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>RabbitMQ</title><link>https://tarrragon.github.io/blog/backend/03-message-queue/vendors/rabbitmq/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/03-message-queue/vendors/rabbitmq/</guid><description>&lt;p>RabbitMQ 是 AMQP 協議實作的 classic broker、承擔三個責任：訊息持久化與重試（durable queue + ack/nack）、靈活路由（exchange + routing key + binding）、跨服務任務分派（worker pool + DLQ）。設計取捨偏向「處理即承諾、broker 負責重新投遞、consumer 負責 idempotency」、可靠性建立在 ack 機制而非 replication。&lt;/p>
&lt;p>對「任務隊列、worker pool、複雜 routing、RPC over messaging」這條路徑、RabbitMQ 是業界主流。本頁先給最短路徑、再展開日常 publisher / consumer 操作與 exchange 設計、最後進階治理（quorum queue、cluster、federation）跟排錯。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>用 docker 跑起 RabbitMQ + management UI、驗證 broker 健康&lt;/li>
&lt;li>用 CLI / Management API 建 exchange、queue、binding&lt;/li>
&lt;li>設計 exchange type（direct / fanout / topic / headers）對齊路由需求&lt;/li>
&lt;li>看懂 queue depth、unacked、connection / channel 數量訊號、定位故障層&lt;/li>
&lt;li>評估 quorum queue、stream、federation、shovel 等規模化議題&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑5-分鐘把-rabbitmq-跑起來">最短路徑：5 分鐘把 RabbitMQ 跑起來&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 1. 啟動 RabbitMQ + management plugin&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">docker run -d --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:3-management
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="c1"># 2. 建 exchange / queue / binding（rabbitmqadmin 可重現、Management UI 在 http://localhost:15672、預設 guest/guest）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">docker &lt;span class="nb">exec&lt;/span> rabbitmq rabbitmqadmin &lt;span class="nb">declare&lt;/span> exchange &lt;span class="nv">name&lt;/span>&lt;span class="o">=&lt;/span>demo.direct &lt;span class="nv">type&lt;/span>&lt;span class="o">=&lt;/span>direct
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">docker &lt;span class="nb">exec&lt;/span> rabbitmq rabbitmqadmin &lt;span class="nb">declare&lt;/span> queue &lt;span class="nv">name&lt;/span>&lt;span class="o">=&lt;/span>demo.q
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">docker &lt;span class="nb">exec&lt;/span> rabbitmq rabbitmqadmin &lt;span class="nb">declare&lt;/span> binding &lt;span class="nv">source&lt;/span>&lt;span class="o">=&lt;/span>demo.direct &lt;span class="nv">destination&lt;/span>&lt;span class="o">=&lt;/span>demo.q &lt;span class="nv">routing_key&lt;/span>&lt;span class="o">=&lt;/span>demo
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="c1"># 3. 用 rabbitmqctl 驗證 broker 狀態&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">docker &lt;span class="nb">exec&lt;/span> rabbitmq rabbitmqctl list_queues
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">docker &lt;span class="nb">exec&lt;/span> rabbitmq rabbitmqctl list_exchanges
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">docker &lt;span class="nb">exec&lt;/span> rabbitmq rabbitmqctl list_bindings&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>最短路徑驗證「broker 起來、UI 能訪、能 enqueue/dequeue」。實際寫程式用 AMQP client、見&lt;a href="#%e6%97%a5%e5%b8%b8%e6%93%8d%e4%bd%9c%e8%88%87%e6%b1%ba%e7%ad%96%e5%bd%a2%e7%8b%80">日常操作&lt;/a>。&lt;/p>
&lt;h2 id="日常操作與決策形狀">日常操作與決策形狀&lt;/h2>
&lt;h3 id="cli-與-client-api">CLI 與 client API&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>CLI 指令對照表（rabbitmqctl / rabbitmq-diagnostics / rabbitmqadmin）&lt;/li>
&lt;li>Management API 形狀（HTTP API、適合自動化）&lt;/li>
&lt;li>AMQP client 配置：connection / channel / consumer prefetch / publisher confirm&lt;/li>
&lt;li>對應指令範例：&lt;code>rabbitmqctl list_queues name messages messages_unacknowledged consumers&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="exchange-types-與-routing-設計">Exchange types 與 routing 設計&lt;/h3>
&lt;p>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">Exchange&lt;/a> 承擔訊息分流責任、不同 type 對應不同路由語意。子議題：&lt;/p></description><content:encoded><![CDATA[<p>RabbitMQ 是 AMQP 協議實作的 classic broker、承擔三個責任：訊息持久化與重試（durable queue + ack/nack）、靈活路由（exchange + routing key + binding）、跨服務任務分派（worker pool + DLQ）。設計取捨偏向「處理即承諾、broker 負責重新投遞、consumer 負責 idempotency」、可靠性建立在 ack 機制而非 replication。</p>
<p>對「任務隊列、worker pool、複雜 routing、RPC over messaging」這條路徑、RabbitMQ 是業界主流。本頁先給最短路徑、再展開日常 publisher / consumer 操作與 exchange 設計、最後進階治理（quorum queue、cluster、federation）跟排錯。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>用 docker 跑起 RabbitMQ + management UI、驗證 broker 健康</li>
<li>用 CLI / Management API 建 exchange、queue、binding</li>
<li>設計 exchange type（direct / fanout / topic / headers）對齊路由需求</li>
<li>看懂 queue depth、unacked、connection / channel 數量訊號、定位故障層</li>
<li>評估 quorum queue、stream、federation、shovel 等規模化議題</li>
</ol>
<h2 id="最短路徑5-分鐘把-rabbitmq-跑起來">最短路徑：5 分鐘把 RabbitMQ 跑起來</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># 1. 啟動 RabbitMQ + management plugin</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">docker run -d --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:3-management
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c1"># 2. 建 exchange / queue / binding（rabbitmqadmin 可重現、Management UI 在 http://localhost:15672、預設 guest/guest）</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">docker <span class="nb">exec</span> rabbitmq rabbitmqadmin <span class="nb">declare</span> exchange <span class="nv">name</span><span class="o">=</span>demo.direct <span class="nv">type</span><span class="o">=</span>direct
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">docker <span class="nb">exec</span> rabbitmq rabbitmqadmin <span class="nb">declare</span> queue <span class="nv">name</span><span class="o">=</span>demo.q
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">docker <span class="nb">exec</span> rabbitmq rabbitmqadmin <span class="nb">declare</span> binding <span class="nv">source</span><span class="o">=</span>demo.direct <span class="nv">destination</span><span class="o">=</span>demo.q <span class="nv">routing_key</span><span class="o">=</span>demo
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="c1"># 3. 用 rabbitmqctl 驗證 broker 狀態</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">docker <span class="nb">exec</span> rabbitmq rabbitmqctl list_queues
</span></span><span class="line"><span class="ln">11</span><span class="cl">docker <span class="nb">exec</span> rabbitmq rabbitmqctl list_exchanges
</span></span><span class="line"><span class="ln">12</span><span class="cl">docker <span class="nb">exec</span> rabbitmq rabbitmqctl list_bindings</span></span></code></pre></div><p>最短路徑驗證「broker 起來、UI 能訪、能 enqueue/dequeue」。實際寫程式用 AMQP client、見<a href="#%e6%97%a5%e5%b8%b8%e6%93%8d%e4%bd%9c%e8%88%87%e6%b1%ba%e7%ad%96%e5%bd%a2%e7%8b%80">日常操作</a>。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="cli-與-client-api">CLI 與 client API</h3>
<p>子議題：</p>
<ul>
<li>CLI 指令對照表（rabbitmqctl / rabbitmq-diagnostics / rabbitmqadmin）</li>
<li>Management API 形狀（HTTP API、適合自動化）</li>
<li>AMQP client 配置：connection / channel / consumer prefetch / publisher confirm</li>
<li>對應指令範例：<code>rabbitmqctl list_queues name messages messages_unacknowledged consumers</code></li>
</ul>
<h3 id="exchange-types-與-routing-設計">Exchange types 與 routing 設計</h3>
<p><a href="/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">Exchange</a> 承擔訊息分流責任、不同 type 對應不同路由語意。子議題：</p>
<ul>
<li>Direct：精準 routing key 匹配（point-to-point）</li>
<li>Fanout：忽略 routing key、廣播到所有 binding queue</li>
<li>Topic：層級式 routing key（<code>*</code> 單層、<code>#</code> 多層萬用字元）</li>
<li>Headers：依 message header 路由（少用）</li>
<li>對應指令：宣告 exchange / queue / binding 的 CLI 與 client 範例</li>
</ul>
<h3 id="queue-設計與-acknack-策略">Queue 設計與 ack/nack 策略</h3>
<p><a href="/blog/backend/knowledge-cards/ack-nack/" data-link-title="Ack / Nack" data-link-desc="說明 consumer 如何向 broker 回報訊息處理結果">Ack/nack</a> 是 RabbitMQ 的 delivery 控制點。子議題：</p>
<ul>
<li>Durable queue vs transient queue</li>
<li>Manual ack vs auto ack（後者等同 at-most-once）</li>
<li>Prefetch 設定（<a href="/blog/backend/knowledge-cards/backpressure/" data-link-title="Backpressure" data-link-desc="說明下游處理速度不足時系統如何讓上游依下游能力送出工作">backpressure</a> + 併發控制）</li>
<li><a href="/blog/backend/knowledge-cards/dead-letter-queue/" data-link-title="Dead-Letter Queue" data-link-desc="說明 dead-letter queue 如何隔離多次處理失敗的訊息">Dead-letter exchange</a>（DLX）配置</li>
<li>Message TTL 與 queue length limit</li>
</ul>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<p>本段主題已展開為 deep article：<a href="queue-types-classic-quorum-stream/">classic vs quorum vs stream 選型</a>、<a href="network-partition-clustering/">network partition 與 cluster 一致性</a>、<a href="dlq-retry-escalation/">DLQ retry escalation</a>。下列子議題段保留選題判讀入口。</p>
<h3 id="classic-queue-vs-quorum-queue-vs-stream">Classic queue vs Quorum queue vs Stream</h3>
<p>子議題：</p>
<ul>
<li>Classic queue：原生持久化 queue、mirrored queue 已 deprecated</li>
<li>Quorum queue：Raft-based、取代 mirrored、跨節點一致性</li>
<li>Stream（3.9+）：append-only log、log-based 模型、類似 Kafka 但仍是 RabbitMQ 體系</li>
<li>三種模型的選擇判讀（throughput、retention、replay 需求）</li>
</ul>
<h3 id="federation-與-shovel">Federation 與 Shovel</h3>
<p>子議題：</p>
<ul>
<li>Federation：upstream / downstream broker 鏈接、適合鬆耦合跨資料中心</li>
<li>Shovel：點對點轉發、適合單純訊息搬運</li>
<li>跨區 / 多 cluster 場景的選擇</li>
</ul>
<h3 id="erlang-clustering-與-network-partition">Erlang clustering 與 network partition</h3>
<p>子議題：</p>
<ul>
<li>Cluster 拓樸（disc node、ram node）</li>
<li><code>cluster_partition_handling</code> 策略（ignore、autoheal、pause_minority）</li>
<li>腦裂偵測與處理</li>
</ul>
<h3 id="多-vhost--多租戶">多 vhost / 多租戶</h3>
<p>子議題：</p>
<ul>
<li>Vhost 隔離（namespace、ACL、user permission）</li>
<li>User / Role / Permission 設計</li>
<li>Per-vhost resource limit（max connection、max queue）</li>
</ul>
<h3 id="prefetch-與-consumer-併發控制">Prefetch 與 consumer 併發控制</h3>
<p>子議題：</p>
<ul>
<li>Prefetch count 對 throughput / fairness 的影響</li>
<li>Channel-level vs Consumer-level prefetch</li>
<li>配合 <a href="/blog/backend/knowledge-cards/retry-budget/" data-link-title="Retry Budget" data-link-desc="說明重試次數如何受整體容量與錯誤預算限制">retry budget</a> 控制重試壓力</li>
</ul>
<h3 id="rabbitmq-cluster-operatork8s">RabbitMQ Cluster Operator（K8s）</h3>
<p>子議題：</p>
<ul>
<li>Cluster Operator vs 自管 StatefulSet</li>
<li>持久化卷（PVC）與資料保護</li>
<li>升級流程（rolling restart 與資料完整性）</li>
</ul>
<h3 id="plugin-機制與多協議">Plugin 機制與多協議</h3>
<p>子議題：</p>
<ul>
<li>MQTT plugin（IoT 場景、橋接 device-to-broker）</li>
<li>STOMP plugin</li>
<li>對應 <a href="/blog/backend/03-message-queue/broker-basics/#%e8%aa%9e%e6%84%8f%e4%bf%9d%e8%ad%89%e7%9a%84%e4%b8%8d%e5%90%8c%e5%af%a6%e4%bd%9c%e6%a9%9f%e5%88%b6" data-link-title="3.1 broker 基礎與投遞模型" data-link-desc="先理解 broker、queue、consumer 與 delivery semantics">3.1 broker basics 的 QoS / ACK 機制橋接</a></li>
</ul>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<h3 id="queue-堆積messages-增加unacked-不收斂">Queue 堆積（messages 增加、unacked 不收斂）</h3>
<p>操作原則：先看 consumer 是否存在、再看 ack 速率 vs publish 速率、最後看 prefetch / poison message。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">rabbitmqctl list_queues name messages messages_unacknowledged consumers</span></span></code></pre></div><p>判讀路徑：無 consumer（client crash）→ consumer 慢（下游卡）→ poison message 卡住（看單一 message redelivery 次數）。</p>
<h3 id="connection--channel-limit">Connection / Channel limit</h3>
<p>操作原則：client 設計不當會用滿 connection / channel，看每個 connection 的 channel 數。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">rabbitmqctl list_connections
</span></span><span class="line"><span class="ln">2</span><span class="cl">rabbitmqctl list_channels</span></span></code></pre></div><h3 id="disk-alarm-觸發">Disk alarm 觸發</h3>
<p>操作原則：disk 低於 <code>disk_free_limit</code>、broker 暫停 publisher。判讀：保留期太長 / 訊息大小 / 未消費 queue 過大。</p>
<h3 id="memory-alarm-觸發">Memory alarm 觸發</h3>
<p>操作原則：記憶體超過 watermark、broker 觸發 <a href="/blog/backend/knowledge-cards/buffer/" data-link-title="Buffer" data-link-desc="說明系統如何用暫存空間吸收短暫速度差與尖峰流量">paging</a>、publisher 變慢。判讀路徑：訊息累積、consumer 失聯、queue 設定錯誤。</p>
<h3 id="network-partition腦裂">Network partition（腦裂）</h3>
<p>操作原則：cluster 節點互相不可達、看 <code>cluster_partition_handling</code> 與 partition log。對應 <a href="/blog/backend/03-message-queue/cases/failure-queue-semantics-mismatch-cutover/" data-link-title="3.C9 反例：Queue 語義切換誤配" data-link-desc="at-least-once / exactly-once 語義誤配導致資料重複與遺漏。">3.C9 語義誤配</a> 思路。</p>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>高吞吐事件流、長期 replay</td>
          <td><a href="/blog/backend/03-message-queue/vendors/kafka/" data-link-title="Apache Kafka" data-link-desc="Distributed event streaming platform、log-based 模型">Kafka</a></td>
      </tr>
      <tr>
          <td>Managed queue（AWS 生態）</td>
          <td><a href="/blog/backend/03-message-queue/vendors/aws-sqs/" data-link-title="AWS SQS" data-link-desc="AWS managed queue、簡單可靠、無 ordering（standard）">AWS SQS</a></td>
      </tr>
      <tr>
          <td>Managed pub/sub（GCP 生態）</td>
          <td><a href="/blog/backend/03-message-queue/vendors/google-pubsub/" data-link-title="Google Cloud Pub/Sub" data-link-desc="GCP managed pub/sub、global routing、push/pull">Google Pub/Sub</a></td>
      </tr>
      <tr>
          <td>輕量 messaging + 微服務</td>
          <td><a href="/blog/backend/03-message-queue/vendors/nats/" data-link-title="NATS" data-link-desc="Lightweight messaging、JetStream 加持久化與 streams">NATS</a></td>
      </tr>
      <tr>
          <td>Redis 生態 stream</td>
          <td><a href="/blog/backend/03-message-queue/vendors/redis-streams/" data-link-title="Redis Streams" data-link-desc="Redis 生態內的 streams、append-only log &#43; consumer group">Redis Streams</a></td>
      </tr>
      <tr>
          <td>IoT device 接入</td>
          <td>EMQX / HiveMQ / Mosquitto（MQTT broker、或用 RabbitMQ MQTT plugin）</td>
      </tr>
      <tr>
          <td>Workflow + durable execution</td>
          <td>Temporal（T4 候選）</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>各語言 AMQP client 完整 API（依官方文件）</li>
<li>所有 plugin 細節（只列主流 plugin）</li>
<li>RabbitMQ Streams 跟 Kafka 的詳細對照（見 <a href="/blog/backend/03-message-queue/vendors/kafka/" data-link-title="Apache Kafka" data-link-desc="Distributed event streaming platform、log-based 模型">Kafka vendor 頁</a>）</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<h3 id="rabbitmq-專屬案例c23-c33">RabbitMQ 專屬案例（C23-C33）</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>主討論議題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/rabbitmq-bloomberg-multi-tenant-vhost/" data-link-title="3.C23 Bloomberg：多租戶 vhost &#43; 自助平台化" data-link-desc="Bloomberg 從幾個團隊推到上百個團隊、靠自助 vhost 註冊跟專用叢集分離應用與 broker。">3.C23 Bloomberg vhost 多租戶</a></td>
          <td>多 vhost + 自助平台化</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/rabbitmq-soundcloud-fanout-audio/" data-link-title="3.C24 SoundCloud：AMQP fan-out 音訊處理 pipeline" data-link-desc="SoundCloud 每秒 20-30K persistent message、不同處理類型分開隊列、各自獨立 scale。">3.C24 SoundCloud fan-out</a></td>
          <td>音訊處理 pipeline 分隊列</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/rabbitmq-indeed-delay-dlq-escalation/" data-link-title="3.C25 Indeed：Delay queue &#43; DLQ 三層 escalation" data-link-desc="Indeed 每天 35M&#43; 職缺、設計 Requeue → Delay queue → DLQ 三層 escalation 避開 head-of-line blocking。">3.C25 Indeed Delay + DLQ</a></td>
          <td>三層 retry escalation</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/rabbitmq-gocardless-hutch-service-mesh/" data-link-title="3.C26 GoCardless：Hutch &#43; 單一 topic exchange service mesh" data-link-desc="GoCardless 單一 RabbitMQ cluster 作所有 service 通訊中樞、routing key 用 service.subject.action 格式、JSON 多語言可讀。">3.C26 GoCardless Hutch</a></td>
          <td>單一 topic exchange 服務 mesh</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/rabbitmq-zalando-aws-master-selection/" data-link-title="3.C27 Zalando：RabbitMQ on AWS 自動化 master selection" data-link-desc="Zalando 用 sidekick 服務查 AWS API 動態識別 cluster、指定最老 instance 當 master、跨版本升級用 federation 過渡。">3.C27 Zalando AWS</a></td>
          <td>雲端自動 master selection / federation 升級</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/rabbitmq-wework-consistent-hash-ordering/" data-link-title="3.C28 WeWork：Consistent hash exchange 保證帳戶順序" data-link-desc="WeWork 固定數量 queue &#43; account ID hash 路由、每 queue 一個 worker &#43; exclusive consumer 保 partition-level ordering。">3.C28 WeWork hash ordering</a></td>
          <td>Consistent hash exchange / per-key ordering</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/rabbitmq-wework-bunny-channel-pool/" data-link-title="3.C29 WeWork：Bunny &#43; Puma 多執行緒 channel pool" data-link-desc="WeWork 從 Unicorn 切到 Puma 後遇 ConnectionClosedError、根因是 AMQP channel 跨執行緒共用、改用 connection_pool 管理。">3.C29 WeWork Bunny channel pool</a></td>
          <td>AMQP channel 不可跨執行緒</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/rabbitmq-runtastic-mirrored-queue-bottleneck/" data-link-title="3.C30 Runtastic：Mirrored queue 網路負載瓶頸" data-link-desc="Runtastic 2020 lockdown 流量暴增、performance test 揭露 mirroring 邏輯把網路元件壓垮、調整 mirroring 配置消除瓶頸。">3.C30 Runtastic mirrored bottleneck</a></td>
          <td>Mirrored queue 網路成本</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/rabbitmq-mozilla-pulse-naming-isolation/" data-link-title="3.C31 Mozilla Pulse：命名前綴 &#43; ACL 取代 vhost 多租戶" data-link-desc="Mozilla Pulse 不用 vhost、改用權限 &#43; 命名前綴 (exchange/{user}/*) 做隔離、CloudAMQP 託管、PulseGuardian 管使用者。">3.C31 Mozilla Pulse</a></td>
          <td>ACL + naming 取代 vhost（反向）</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/rabbitmq-loyaltylion-monitoring-thousands/" data-link-title="3.C32 LoyaltyLion：監控數千 RabbitMQ queue" data-link-desc="LoyaltyLion 跑數千 queue、用 rabbitmqctl &#43; statsd 推 Datadog、揭露大規模 queue 拓樸下原生 plugin API 不夠用。">3.C32 LoyaltyLion monitoring</a></td>
          <td>大規模 queue topology 監控</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/rabbitmq-wargaming-game-portal-decoupling/" data-link-title="3.C33 Wargaming：World of Tanks 戰後 dossier 解耦" data-link-desc="Wargaming WoT server 全 Linux、戰後 dossier 寫 RabbitMQ、portal 顯示統計而不增 game server load。">3.C33 Wargaming game portal</a></td>
          <td>異步解耦 game server / portal</td>
      </tr>
  </tbody>
</table>
<h3 id="跨-vendor-對照">跨 vendor 對照</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>對 RabbitMQ 的對應</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/failure-queue-semantics-mismatch-cutover/" data-link-title="3.C9 反例：Queue 語義切換誤配" data-link-desc="at-least-once / exactly-once 語義誤配導致資料重複與遺漏。">3.C9 反例：語義誤配</a></td>
          <td>manual ack + DLX + idempotency 三層責任邊界</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/contrast-queue-model-by-scale/" data-link-title="3.C10 對照：規模差異下的佇列模型" data-link-desc="同一 queue 模型在不同規模下的治理與失敗邊界差異。">3.C10 規模對照</a></td>
          <td>小型直接用 / 中型補 idempotency / 大型分 vhost</td>
      </tr>
  </tbody>
</table>
<p><strong>MQTT plugin + Cluster Operator 缺直接 customer case</strong>：可補 RabbitMQ 官方 native MQTT blog 跟 K8s Operator docs、後續若有 customer 案例可加。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游概念：<a href="/blog/backend/00-service-selection/async-delivery-selection/" data-link-title="0.3 非同步與事件傳遞選型" data-link-desc="區分背景工作、durable queue、stream、pub/sub 與 outbox 的選型邊界">0.3 非同步選型</a>、<a href="/blog/backend/03-message-queue/broker-basics/" data-link-title="3.1 broker 基礎與投遞模型" data-link-desc="先理解 broker、queue、consumer 與 delivery semantics">3.1 broker basics</a></li>
<li>平行 vendor：<a href="/blog/backend/03-message-queue/vendors/kafka/" data-link-title="Apache Kafka" data-link-desc="Distributed event streaming platform、log-based 模型">Kafka</a>、<a href="/blog/backend/03-message-queue/vendors/nats/" data-link-title="NATS" data-link-desc="Lightweight messaging、JetStream 加持久化與 streams">NATS</a></li>
<li>下游能力：<a href="/blog/backend/03-message-queue/durable-queue/" data-link-title="3.2 durable queue 與重試策略" data-link-desc="整理持久化佇列、DLQ 與重試流程">3.2 durable queue</a>、<a href="/blog/backend/03-message-queue/consumer-design/" data-link-title="3.4 consumer 設計與去重" data-link-desc="整理 consumer、checkpoint 與 replay safety">3.4 consumer 設計</a></li>
</ul>
]]></content:encoded></item><item><title>Redis</title><link>https://tarrragon.github.io/blog/backend/02-cache-redis/vendors/redis/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/02-cache-redis/vendors/redis/</guid><description>&lt;p>Redis 是 in-memory data structure store、承擔三個責任：cache serving layer（with eviction）、data structure operation（string / hash / list / sorted set / stream / hyperloglog / geo）、輕量持久化（AOF / RDB）。設計取捨偏向「記憶體優先 + data type rich + 可選持久化」、cache 是主用場、但 data type 讓它跨入 session store / counter / leaderboard / lock 等場景。2024 起授權變動為 RSALv2 / SSPL（OSI 不認）、引發 Valkey fork。&lt;/p>
&lt;p>對「通用快取、session store、rate limit counter、leaderboard、distributed lock」這條路徑、Redis 是事實標準。本頁先給最短路徑、再展開日常 CLI / API 與 key 設計、最後進階治理（cluster / persistence / modules）跟排錯。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>用 docker 跑起 Redis、用 redis-cli 驗證&lt;/li>
&lt;li>用 SET / GET / EXPIRE / DEL / KEYS 操作、區分 6 大 data types 適用場景&lt;/li>
&lt;li>設計 key naming + TTL + eviction policy 對齊 cache miss 行為&lt;/li>
&lt;li>看懂 hit rate / memory pressure / eviction / replication lag 訊號&lt;/li>
&lt;li>評估 Cluster vs Sentinel、AOF/RDB、modules、授權變動下的選擇&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑5-分鐘把-redis-跑起來">最短路徑：5 分鐘把 Redis 跑起來&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 1. 啟動 Redis&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: docker run -d --name redis -p 6379:6379 redis:7&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="c1"># 2. 連線&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: docker exec -it redis redis-cli&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">&lt;span class="c1"># 3. 驗證 SET / GET / EXPIRE&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: SET foo bar / GET foo / EXPIRE foo 60 / TTL foo&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>最短路徑驗證「Redis 起來、能讀寫 + TTL」。實際應用見&lt;a href="#%e6%97%a5%e5%b8%b8%e6%93%8d%e4%bd%9c%e8%88%87%e6%b1%ba%e7%ad%96%e5%bd%a2%e7%8b%80">日常操作&lt;/a>。&lt;/p>
&lt;h2 id="日常操作與決策形狀">日常操作與決策形狀&lt;/h2>
&lt;h3 id="cli-與-client-api">CLI 與 client API&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>redis-cli 指令對照表（SET / GET / DEL / EXPIRE / TTL / KEYS / SCAN / MGET / MSET）&lt;/li>
&lt;li>Client library 配置：connection pool / timeout / pipeline / cluster mode&lt;/li>
&lt;li>Pub/Sub vs Streams 的選用判讀&lt;/li>
&lt;li>對應指令範例：&lt;code>INFO replication&lt;/code>、&lt;code>CLIENT LIST&lt;/code>、&lt;code>SLOWLOG GET&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="key-design-與-data-types">Key design 與 data types&lt;/h3>
&lt;p>不同 data type 對應不同&lt;a href="https://tarrragon.github.io/blog/backend/02-cache-redis/cache-data-shape-access-pattern/" data-link-title="2.8 Cache Data Shape 與 Access Pattern" data-link-desc="說明 cache value、key space、資料結構與存取型態如何反映服務語意。">資料形狀&lt;/a>。子議題：&lt;/p></description><content:encoded><![CDATA[<p>Redis 是 in-memory data structure store、承擔三個責任：cache serving layer（with eviction）、data structure operation（string / hash / list / sorted set / stream / hyperloglog / geo）、輕量持久化（AOF / RDB）。設計取捨偏向「記憶體優先 + data type rich + 可選持久化」、cache 是主用場、但 data type 讓它跨入 session store / counter / leaderboard / lock 等場景。2024 起授權變動為 RSALv2 / SSPL（OSI 不認）、引發 Valkey fork。</p>
<p>對「通用快取、session store、rate limit counter、leaderboard、distributed lock」這條路徑、Redis 是事實標準。本頁先給最短路徑、再展開日常 CLI / API 與 key 設計、最後進階治理（cluster / persistence / modules）跟排錯。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>用 docker 跑起 Redis、用 redis-cli 驗證</li>
<li>用 SET / GET / EXPIRE / DEL / KEYS 操作、區分 6 大 data types 適用場景</li>
<li>設計 key naming + TTL + eviction policy 對齊 cache miss 行為</li>
<li>看懂 hit rate / memory pressure / eviction / replication lag 訊號</li>
<li>評估 Cluster vs Sentinel、AOF/RDB、modules、授權變動下的選擇</li>
</ol>
<h2 id="最短路徑5-分鐘把-redis-跑起來">最短路徑：5 分鐘把 Redis 跑起來</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 1. 啟動 Redis</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># TODO: docker run -d --name redis -p 6379:6379 redis:7</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 2. 連線</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="c1"># TODO: docker exec -it redis redis-cli</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="c1"># 3. 驗證 SET / GET / EXPIRE</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="c1"># TODO: SET foo bar / GET foo / EXPIRE foo 60 / TTL foo</span></span></span></code></pre></div><p>最短路徑驗證「Redis 起來、能讀寫 + TTL」。實際應用見<a href="#%e6%97%a5%e5%b8%b8%e6%93%8d%e4%bd%9c%e8%88%87%e6%b1%ba%e7%ad%96%e5%bd%a2%e7%8b%80">日常操作</a>。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="cli-與-client-api">CLI 與 client API</h3>
<p>子議題：</p>
<ul>
<li>redis-cli 指令對照表（SET / GET / DEL / EXPIRE / TTL / KEYS / SCAN / MGET / MSET）</li>
<li>Client library 配置：connection pool / timeout / pipeline / cluster mode</li>
<li>Pub/Sub vs Streams 的選用判讀</li>
<li>對應指令範例：<code>INFO replication</code>、<code>CLIENT LIST</code>、<code>SLOWLOG GET</code></li>
</ul>
<h3 id="key-design-與-data-types">Key design 與 data types</h3>
<p>不同 data type 對應不同<a href="/blog/backend/02-cache-redis/cache-data-shape-access-pattern/" data-link-title="2.8 Cache Data Shape 與 Access Pattern" data-link-desc="說明 cache value、key space、資料結構與存取型態如何反映服務語意。">資料形狀</a>。子議題：</p>
<ul>
<li>String：cache / counter / config flag</li>
<li>Hash：object cache（避免反覆 serialize）</li>
<li>List：queue / activity feed（小規模）</li>
<li>Set：membership / tag</li>
<li>Sorted set：leaderboard / time-series sliding window</li>
<li>Stream：log-style queue / event stream</li>
<li>HyperLogLog / Geo：approximate count / 地理座標</li>
</ul>
<p>Key naming 規範：<code>&lt;service&gt;:&lt;entity&gt;:&lt;id&gt;:&lt;field&gt;</code>、用 <code>:</code> 分層、避免大 key（單 key &gt; 10KB / list 長度 &gt; 10K）。</p>
<h3 id="ttl-與-eviction-策略">TTL 與 eviction 策略</h3>
<p><a href="/blog/backend/02-cache-redis/ttl-eviction/" data-link-title="2.3 TTL 與 eviction" data-link-desc="整理過期策略、容量控制與熱點資料">TTL 跟 eviction</a> 是 cache 行為的核心旋鈕。子議題：</p>
<ul>
<li>顯式 EXPIRE vs SET EX 設 TTL</li>
<li>maxmemory + maxmemory-policy（allkeys-lru / allkeys-lfu / volatile-lru / volatile-ttl / noeviction）</li>
<li>TTL 設計：固定 TTL vs 動態 TTL vs 不設 TTL</li>
<li>對應指令：<code>CONFIG SET maxmemory 2gb</code>、<code>CONFIG SET maxmemory-policy allkeys-lfu</code></li>
</ul>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<h3 id="cluster-vs-sentinel">Cluster vs Sentinel</h3>
<p>子議題：</p>
<ul>
<li>Sentinel：HA 模式、無 sharding、適合單 master 容量足夠</li>
<li>Cluster：sharding 模式、16384 hash slot、橫向擴展容量</li>
<li>Hash tag <code>{...}</code> 強制 multi-key 同 shard</li>
<li>Cluster failover 對 PEL（Streams）跟 distributed lock 的影響</li>
</ul>
<h3 id="aof--rdb-持久化策略">AOF / RDB 持久化策略</h3>
<p>子議題：</p>
<ul>
<li>AOF（append-only file）：fsync 策略（always / everysec / no）、rewrite</li>
<li>RDB（snapshot）：save 策略、backup 還原</li>
<li>混合模式：AOF + RDB</li>
<li>持久化在 cache 場景的取捨（持久化是回填還是 source-of-truth）</li>
</ul>
<h3 id="eviction-policy-詳細">Eviction policy 詳細</h3>
<p>子議題：</p>
<ul>
<li>LRU vs LFU：access pattern 對選擇的影響</li>
<li>volatile-* vs allkeys-*：只淘汰有 TTL 的 vs 全 key</li>
<li>approximate LRU 的 sampling 影響</li>
<li>對應 <a href="/blog/backend/02-cache-redis/ttl-eviction/" data-link-title="2.3 TTL 與 eviction" data-link-desc="整理過期策略、容量控制與熱點資料">2.3 TTL eviction</a></li>
</ul>
<h3 id="distributed-lock">Distributed lock</h3>
<p>子議題：</p>
<ul>
<li>SETNX + EXPIRE 模式</li>
<li>Redlock 算法（多 master quorum）+ 取捨爭議</li>
<li>Redlock 何時不夠：fence token / lease renewal</li>
<li>對應 <a href="/blog/backend/02-cache-redis/distributed-lock/" data-link-title="2.4 distributed lock 與租約" data-link-desc="整理鎖語意、租約風險與適用場景">2.5 distributed lock</a></li>
</ul>
<h3 id="pubsub-vs-streams">Pub/Sub vs Streams</h3>
<p>子議題：</p>
<ul>
<li>Pub/Sub：fire-and-forget、訂閱者離線會錯過</li>
<li>Streams：append-only log、consumer group + PEL</li>
<li>何時用 Streams 取代 Pub/Sub</li>
<li>Redis Streams 細節見 <a href="/blog/backend/03-message-queue/vendors/redis-streams/" data-link-title="Redis Streams" data-link-desc="Redis 生態內的 streams、append-only log &#43; consumer group">03 messaging 模組 Redis Streams vendor</a></li>
</ul>
<h3 id="redis-modules">Redis Modules</h3>
<p>子議題：</p>
<ul>
<li>RedisJSON / RedisSearch / RedisTimeSeries / RedisBloom / RedisGraph</li>
<li>Module 隨授權變動受影響、Valkey 部分 fork</li>
<li>Module 在 ElastiCache 的支援限制</li>
</ul>
<h3 id="授權變動與選型影響">授權變動與選型影響</h3>
<p>子議題：</p>
<ul>
<li>2024 RSALv2 / SSPL 變動的影響範圍</li>
<li>對 managed service（ElastiCache 改 default 為 Valkey）的衝擊</li>
<li>從 Redis 遷 Valkey 的相容性路徑</li>
<li>商業 vs OSS 邊界</li>
</ul>
<h3 id="hot-key-處理">Hot key 處理</h3>
<p>子議題：</p>
<ul>
<li>Hot key 偵測（redis-cli &ndash;hotkeys、<code>MONITOR</code> 慎用）</li>
<li>Hot key 解法：local cache + Redis 兩層、key 拆分（讀多寫少場景）</li>
<li>對應 <a href="/blog/backend/02-cache-redis/high-concurrency-access/" data-link-title="2.1 高併發下的 Redis 讀寫邊界" data-link-desc="說明高併發服務如何共用 Redis client、控制 pipeline 與避免 cache stampede">2.6 high concurrency</a></li>
</ul>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<h3 id="hit-rate-下降">Hit rate 下降</h3>
<p>操作原則：先看 cache pattern 是否變（新功能 / TTL 變短）、再看 origin 壓力是否擴大。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># TODO: INFO stats（看 keyspace_hits / keyspace_misses 比例）</span></span></span></code></pre></div><p>判讀路徑：TTL 太短 → eviction 太積極 → key 命名變動造成 cache miss → origin 失敗 retry storm。</p>
<h3 id="memory-pressure--eviction-異常">Memory pressure / eviction 異常</h3>
<p>操作原則：先看 maxmemory + maxmemory-policy 設定、再看 key size 分布。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># TODO: INFO memory / MEMORY USAGE &lt;key&gt; / --bigkeys</span></span></span></code></pre></div><h3 id="hot-key">Hot key</h3>
<p>對應案例 <a href="/blog/backend/02-cache-redis/cases/shopify-write-through-cache-at-scale/" data-link-title="2.C5 Shopify：Write-through Cache 在高讀流量的實作" data-link-desc="read-heavy 服務如何轉向 write-through 快取模型。">2.C5 Shopify Write-Through</a>。判讀路徑：某 key 的 QPS 遠高於其他、單 shard CPU 接近 100%、其他 shard 閒置。</p>
<h3 id="replication-lag">Replication lag</h3>
<p>操作原則：replica 跟 master 差距、看 <code>INFO replication</code> 的 master_repl_offset vs slave_repl_offset。對 <a href="/blog/backend/02-cache-redis/cases/meta-cache-consistency-upgrade/" data-link-title="2.C1 Meta：Cache Consistency 升級" data-link-desc="快取 invalidation 一致性如何從常見錯誤演進到高可信治理。">2.C1 Meta Cache Consistency</a> 的對照。</p>
<h3 id="cache-stampede雷霆崩潰">Cache stampede（雷霆崩潰）</h3>
<p>對應反例 <a href="/blog/backend/02-cache-redis/cases/failure-cache-stampede-rollout-regression/" data-link-title="2.C9 反例：快取切換引發 Stampede 回歸" data-link-desc="快取策略切換若缺乏保護，會導致回源壓力與錯誤率連鎖上升。">2.C9 Cache Stampede Rollout</a>。判讀路徑：TTL 同時過期 → 大量 cache miss → origin 被打爆 → 連鎖失敗。修法：jitter TTL、early refresh、singleflight 模式。</p>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>需要 OSI 認可開源授權</td>
          <td><a href="/blog/backend/02-cache-redis/vendors/valkey/" data-link-title="Valkey" data-link-desc="Redis fork、Linux Foundation 託管、BSD 授權">Valkey</a></td>
      </tr>
      <tr>
          <td>純 cache、不需 data types</td>
          <td><a href="/blog/backend/02-cache-redis/vendors/memcached/" data-link-title="Memcached" data-link-desc="純記憶體 key-value cache、無持久化">Memcached</a></td>
      </tr>
      <tr>
          <td>極高 throughput / 多核</td>
          <td><a href="/blog/backend/02-cache-redis/vendors/dragonflydb/" data-link-title="DragonflyDB" data-link-desc="高效能 Redis / Memcached 相容替代、多核架構">DragonflyDB</a></td>
      </tr>
      <tr>
          <td>AWS 生態 managed</td>
          <td><a href="/blog/backend/02-cache-redis/vendors/aws-elasticache/" data-link-title="AWS ElastiCache" data-link-desc="AWS managed Redis / Valkey / Memcached">AWS ElastiCache</a></td>
      </tr>
      <tr>
          <td>Durable Redis-compatible</td>
          <td>AWS MemoryDB（介於 cache 與 DB）</td>
      </tr>
      <tr>
          <td>大規模 event stream</td>
          <td><a href="/blog/backend/03-message-queue/vendors/kafka/" data-link-title="Apache Kafka" data-link-desc="Distributed event streaming platform、log-based 模型">Kafka</a> / <a href="/blog/backend/03-message-queue/vendors/redis-streams/" data-link-title="Redis Streams" data-link-desc="Redis 生態內的 streams、append-only log &#43; consumer group">Redis Streams</a></td>
      </tr>
      <tr>
          <td>Process-local cache</td>
          <td><a href="/blog/backend/02-cache-redis/vendors/caffeine/" data-link-title="Caffeine" data-link-desc="JVM process-local cache、Window TinyLFU、Guava Cache 後繼">Caffeine</a> / Guava Cache（JVM 內、無網路）</td>
      </tr>
      <tr>
          <td>Search / full-text</td>
          <td>Elasticsearch / OpenSearch（不在本模組）</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>各語言 Redis client 完整 API</li>
<li>Redis command 百科（詳查 redis.io/commands）</li>
<li>Redis Stack 商業 modules 細節</li>
<li>AOF / RDB 內部 binary format</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<h3 id="直接相關案例">直接相關案例</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>對 Redis 的對應</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/shopify-cache-serialization-migration/" data-link-title="2.C3 Shopify：快取序列化格式遷移" data-link-desc="快取 payload 從 Marshal 轉 MessagePack 的遷移策略。">2.C3 Shopify serialization</a></td>
          <td>Shopify Redis 上做 Marshal → MessagePack 雙軌遷移、payload 編碼演進</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/shopify-write-through-cache-at-scale/" data-link-title="2.C5 Shopify：Write-through Cache 在高讀流量的實作" data-link-desc="read-heavy 服務如何轉向 write-through 快取模型。">2.C5 Shopify write-through</a></td>
          <td>Shopify 在 read-heavy 路徑用 Redis 做 write-through、對應 hot key / 命中率治理</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/meta-cache-consistency-upgrade/" data-link-title="2.C1 Meta：Cache Consistency 升級" data-link-desc="快取 invalidation 一致性如何從常見錯誤演進到高可信治理。">2.C1 Meta cache consistency</a></td>
          <td>invalidation / shard move 一致性議題、Redis Cluster 與 replica 場景共用判讀框架</td>
      </tr>
  </tbody>
</table>
<h3 id="跨-vendor-對照">跨 vendor 對照</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>對 Redis 的對應</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/failure-cache-stampede-rollout-regression/" data-link-title="2.C9 反例：快取切換引發 Stampede 回歸" data-link-desc="快取策略切換若缺乏保護，會導致回源壓力與錯誤率連鎖上升。">2.C9 Cache Stampede</a></td>
          <td>Redis TTL 切換 / key rename 都會觸發 stampede、需 jitter / singleflight / early refresh</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/contrast-cache-strategy-by-scale/" data-link-title="2.C10 對照：規模差異下的快取策略" data-link-desc="同一快取策略在小中大型服務下會產生不同風險。">2.C10 規模對照</a></td>
          <td>小型 single instance + AOF / 中型 Sentinel + replica / 大型 Cluster + hash tag</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/meta-mcrouter-global-cache-routing/" data-link-title="2.C2 Meta：mcrouter 與跨區快取路由" data-link-desc="快取從單點最佳化演進到分散式路由層的案例。">2.C2 Meta mcrouter</a></td>
          <td>Memcached 路由層案例、Redis 對應為 Cluster + proxy（Envoy / Twemproxy）或 client-side routing</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/meta-cachelib-kangaroo-tiered-cache/" data-link-title="2.C4 Meta：CacheLib / Kangaroo 分層快取" data-link-desc="快取從 DRAM-only 轉向分層快取架構的實務案例。">2.C4 Meta CacheLib + Kangaroo</a></td>
          <td>分層 cache（DRAM + flash）對照、Redis on flash（RoF / Speedb）的成本決策參考</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/netflix-evcache-global-cache-layer/" data-link-title="2.C6 Netflix：EVCache 全域快取層" data-link-desc="快取從本地層演進為跨區分散式能力的案例。">2.C6 Netflix EVCache</a></td>
          <td>EVCache 基於 Memcached + 跨 AZ replication、Redis 對應為 active-active CRDB / Global Datastore</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/meta-tao-social-graph-cache-evolution/" data-link-title="2.C8 Meta：TAO 社交圖快取演進" data-link-desc="社交圖查詢在規模化下如何把快取做成資料層能力。">2.C8 Meta TAO</a></td>
          <td>Graph cache 演進案例、Redis 對應為 RedisGraph（已 deprecated）或自建 graph 索引</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/cloudflare-cache-reserve-tiered-storage/" data-link-title="2.C7 Cloudflare：Cache Reserve 分層儲存快取" data-link-desc="邊緣快取延伸到持久層以降低回源壓力的案例。">2.C7 Cloudflare Cache Reserve</a></td>
          <td>Edge tiered（HTTP cache）對照、Redis 對應為 hot tier + S3 cold tier 自建分層</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游概念：<a href="/blog/backend/02-cache-redis/cache-aside/" data-link-title="2.2 cache aside 與失效策略" data-link-desc="整理 read-through 思路、cache miss 與 invalidation">2.2 Cache Aside</a>、<a href="/blog/backend/02-cache-redis/ttl-eviction/" data-link-title="2.3 TTL 與 eviction" data-link-desc="整理過期策略、容量控制與熱點資料">2.3 TTL eviction</a></li>
<li>平行 vendor：<a href="/blog/backend/02-cache-redis/vendors/valkey/" data-link-title="Valkey" data-link-desc="Redis fork、Linux Foundation 託管、BSD 授權">Valkey</a>、<a href="/blog/backend/02-cache-redis/vendors/memcached/" data-link-title="Memcached" data-link-desc="純記憶體 key-value cache、無持久化">Memcached</a></li>
<li>下游能力：<a href="/blog/backend/02-cache-redis/distributed-lock/" data-link-title="2.4 distributed lock 與租約" data-link-desc="整理鎖語意、租約風險與適用場景">2.5 distributed lock</a>、<a href="/blog/backend/02-cache-redis/high-concurrency-access/" data-link-title="2.1 高併發下的 Redis 讀寫邊界" data-link-desc="說明高併發服務如何共用 Redis client、控制 pipeline 與避免 cache stampede">2.6 high concurrency</a></li>
</ul>
]]></content:encoded></item><item><title>GitHub Actions：Environment Protection 與 OIDC Cloud Auth</title><link>https://tarrragon.github.io/blog/backend/06-reliability/vendors/github-actions/environment-protection-and-oidc-cloud-auth/</link><pubDate>Tue, 23 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/06-reliability/vendors/github-actions/environment-protection-and-oidc-cloud-auth/</guid><description>&lt;h2 id="問題情境">問題情境&lt;/h2>
&lt;p>CI pipeline 的可靠性驗證在測試階段結束後，還需要兩道控制面才算完整。第一道是 deploy approval gate — 決定誰可以核准 production deploy、在什麼條件下放行。第二道是 credential 安全 — deploy 需要 cloud credential，但 long-lived secret 存在 CI 環境中會擴大洩漏面。&lt;/p>
&lt;p>GitHub Actions 用 environment protection rules 處理第一道，用 OIDC federation 處理第二道。兩者搭配讓 deploy 流程同時滿足 &lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/release-gate/" data-link-title="6.8 Release Gate 與變更節奏" data-link-desc="把驗證、migration、相容性納入放行判準">6.8 release gate&lt;/a> 的放行控制與 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/" data-link-title="模組七：資安與資料保護" data-link-desc="以問題驅動方式擴充資安知識網：先定義服務環節問題，再以案例作為觸發式參考">07 資安&lt;/a> 的 credential 最小暴露原則。&lt;/p>
&lt;h2 id="environment-protection-rules">Environment Protection Rules&lt;/h2>
&lt;p>Environment 是 GitHub Actions 的 deploy 分層單位。每個 environment（staging / canary / production）可以獨立設定 protection rules，讓不同風險等級的 deploy 走不同的放行流程。&lt;/p>
&lt;h3 id="protection-rule-類型">Protection rule 類型&lt;/h3>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>規則&lt;/th>
 &lt;th>責任&lt;/th>
 &lt;th>典型設定&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Required reviewers&lt;/td>
 &lt;td>指定人員核准後才能 deploy&lt;/td>
 &lt;td>production 需 2 人核准&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Wait timer&lt;/td>
 &lt;td>deploy 前強制等待，讓最後一刻能攔住&lt;/td>
 &lt;td>production 等 15 分鐘&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Deployment branch policy&lt;/td>
 &lt;td>只允許特定 branch deploy 到該 environment&lt;/td>
 &lt;td>production 只接受 main / release/*&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>Required reviewers 是 deploy 層的 release gate。當 workflow job 標記 &lt;code>environment: production&lt;/code>，GitHub 會暫停 job 直到指定 reviewer 核准。reviewer 的選擇應對齊服務 ownership — 由該服務的 on-call lead 或 tech lead 核准，避免核准權過於集中或分散。&lt;/p>
&lt;p>Wait timer 提供一個緩衝窗口。deploy 前等待 N 分鐘讓團隊有時間檢查 staging 結果、確認沒有進行中的事故、或在發現問題時取消 deploy。timer 長度跟服務風險等級對齊 — 低風險服務可以 0 分鐘，交易路徑可以 15-30 分鐘。&lt;/p>
&lt;p>Deployment branch policy 限制哪些 branch 可以觸發特定 environment 的 deploy。這防止 feature branch 意外 deploy 到 production。production 通常只接受 main 或 release branch。&lt;/p>
&lt;h3 id="分層建議">分層建議&lt;/h3>
&lt;p>staging 用自動 deploy — push 到 staging branch 直接觸發 workflow，無需 approval，回饋速度最大化。production 用 required reviewer + wait timer — 確保每次 production deploy 都經過人工確認與緩衝。canary 介於兩者之間 — 可以自動 deploy 但加 wait timer，讓觀測指標有時間反映。&lt;/p>
&lt;h2 id="oidc-cloud-auth">OIDC Cloud Auth&lt;/h2>
&lt;h3 id="long-lived-credential-的風險">Long-lived credential 的風險&lt;/h3>
&lt;p>CI deploy 需要 cloud credential（AWS access key / GCP service account key / Azure service principal）。傳統做法是把這些 credential 存在 GitHub repository secret 或 environment secret 中。long-lived credential 的風險在於：洩漏後攻擊者可以長期使用、rotation 需要手動更新 CI 設定、credential scope 常設得比實際需求更大。&lt;/p></description><content:encoded><![CDATA[<h2 id="問題情境">問題情境</h2>
<p>CI pipeline 的可靠性驗證在測試階段結束後，還需要兩道控制面才算完整。第一道是 deploy approval gate — 決定誰可以核准 production deploy、在什麼條件下放行。第二道是 credential 安全 — deploy 需要 cloud credential，但 long-lived secret 存在 CI 環境中會擴大洩漏面。</p>
<p>GitHub Actions 用 environment protection rules 處理第一道，用 OIDC federation 處理第二道。兩者搭配讓 deploy 流程同時滿足 <a href="/blog/backend/06-reliability/release-gate/" data-link-title="6.8 Release Gate 與變更節奏" data-link-desc="把驗證、migration、相容性納入放行判準">6.8 release gate</a> 的放行控制與 <a href="/blog/backend/07-security-data-protection/" data-link-title="模組七：資安與資料保護" data-link-desc="以問題驅動方式擴充資安知識網：先定義服務環節問題，再以案例作為觸發式參考">07 資安</a> 的 credential 最小暴露原則。</p>
<h2 id="environment-protection-rules">Environment Protection Rules</h2>
<p>Environment 是 GitHub Actions 的 deploy 分層單位。每個 environment（staging / canary / production）可以獨立設定 protection rules，讓不同風險等級的 deploy 走不同的放行流程。</p>
<h3 id="protection-rule-類型">Protection rule 類型</h3>
<table>
  <thead>
      <tr>
          <th>規則</th>
          <th>責任</th>
          <th>典型設定</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Required reviewers</td>
          <td>指定人員核准後才能 deploy</td>
          <td>production 需 2 人核准</td>
      </tr>
      <tr>
          <td>Wait timer</td>
          <td>deploy 前強制等待，讓最後一刻能攔住</td>
          <td>production 等 15 分鐘</td>
      </tr>
      <tr>
          <td>Deployment branch policy</td>
          <td>只允許特定 branch deploy 到該 environment</td>
          <td>production 只接受 main / release/*</td>
      </tr>
  </tbody>
</table>
<p>Required reviewers 是 deploy 層的 release gate。當 workflow job 標記 <code>environment: production</code>，GitHub 會暫停 job 直到指定 reviewer 核准。reviewer 的選擇應對齊服務 ownership — 由該服務的 on-call lead 或 tech lead 核准，避免核准權過於集中或分散。</p>
<p>Wait timer 提供一個緩衝窗口。deploy 前等待 N 分鐘讓團隊有時間檢查 staging 結果、確認沒有進行中的事故、或在發現問題時取消 deploy。timer 長度跟服務風險等級對齊 — 低風險服務可以 0 分鐘，交易路徑可以 15-30 分鐘。</p>
<p>Deployment branch policy 限制哪些 branch 可以觸發特定 environment 的 deploy。這防止 feature branch 意外 deploy 到 production。production 通常只接受 main 或 release branch。</p>
<h3 id="分層建議">分層建議</h3>
<p>staging 用自動 deploy — push 到 staging branch 直接觸發 workflow，無需 approval，回饋速度最大化。production 用 required reviewer + wait timer — 確保每次 production deploy 都經過人工確認與緩衝。canary 介於兩者之間 — 可以自動 deploy 但加 wait timer，讓觀測指標有時間反映。</p>
<h2 id="oidc-cloud-auth">OIDC Cloud Auth</h2>
<h3 id="long-lived-credential-的風險">Long-lived credential 的風險</h3>
<p>CI deploy 需要 cloud credential（AWS access key / GCP service account key / Azure service principal）。傳統做法是把這些 credential 存在 GitHub repository secret 或 environment secret 中。long-lived credential 的風險在於：洩漏後攻擊者可以長期使用、rotation 需要手動更新 CI 設定、credential scope 常設得比實際需求更大。</p>
<h3 id="oidc-federation-的運作方式">OIDC federation 的運作方式</h3>
<p>GitHub Actions 支援作為 OIDC identity provider。workflow 在執行時可以向 GitHub 請求一個 short-lived OIDC token，cloud provider 信任這個 token 後發出 short-lived cloud credential。整個流程不需要在 CI 環境中存放任何 long-lived secret。</p>
<p>流程：workflow 啟動 → 向 GitHub OIDC provider 請求 token → token 帶有 repo / branch / environment 等 claim → cloud provider 的 trust policy 驗證 claim → 發出 short-lived credential（通常 1 小時有效期）。</p>
<h3 id="cloud-provider-配置">Cloud provider 配置</h3>
<p><strong>AWS</strong>：在 IAM 設定 OIDC identity provider（issuer: <code>token.actions.githubusercontent.com</code>）、建立 IAM role 並設定 trust policy 限制 repo + branch + environment。workflow 中用 <code>aws-actions/configure-aws-credentials</code> action 取得 session credential。</p>
<p><strong>GCP</strong>：設定 Workload Identity Federation pool + provider、建立 service account 並綁定 pool。workflow 中用 <code>google-github-actions/auth</code> action 取得 short-lived token。</p>
<p><strong>Azure</strong>：在 Azure AD 設定 federated credential 給 app registration、限制 repo + branch + environment。workflow 中用 <code>azure/login</code> action。</p>
<h3 id="trust-policy-的安全邊界">Trust policy 的安全邊界</h3>
<p>OIDC trust policy 必須限制到特定 repo、branch 與 environment。trust policy 寫成 wildcard（信任整個 GitHub org 的所有 repo）等於讓 org 內任何 repo 的 workflow 都能取得 cloud credential。最小權限原則：production environment 的 trust policy 只信任 <code>repo:org/service:environment:production</code>，不信任其他 environment 或 branch。</p>
<h2 id="實作範例">實作範例</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c"># .github/workflows/deploy.yml</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="w"></span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Deploy</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="w"></span><span class="nt">on</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="w">  </span><span class="nt">push</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="w">    </span><span class="nt">branches</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="l">main]</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="w"></span><span class="nt">permissions</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="w">  </span><span class="nt">id-token</span><span class="p">:</span><span class="w"> </span><span class="l">write</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="w">  </span><span class="nt">contents</span><span class="p">:</span><span class="w"> </span><span class="l">read</span><span class="w">
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="w"></span><span class="nt">jobs</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="w">  </span><span class="nt">deploy-staging</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="w">    </span><span class="nt">runs-on</span><span class="p">:</span><span class="w"> </span><span class="l">ubuntu-latest</span><span class="w">
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="w">    </span><span class="nt">environment</span><span class="p">:</span><span class="w"> </span><span class="l">staging</span><span class="w">
</span></span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="w">    </span><span class="nt">steps</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="w">      </span>- <span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">actions/checkout@v4</span><span class="w">
</span></span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="w">      </span>- <span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">aws-actions/configure-aws-credentials@v4</span><span class="w">
</span></span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="w">        </span><span class="nt">with</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="w">          </span><span class="nt">role-to-assume</span><span class="p">:</span><span class="w"> </span><span class="l">arn:aws:iam::123456789012:role/staging-deploy</span><span class="w">
</span></span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="w">          </span><span class="nt">aws-region</span><span class="p">:</span><span class="w"> </span><span class="l">ap-northeast-1</span><span class="w">
</span></span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="w">      </span>- <span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="l">./scripts/deploy.sh staging</span><span class="w">
</span></span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln">23</span><span class="cl"><span class="w">  </span><span class="nt">deploy-production</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">24</span><span class="cl"><span class="w">    </span><span class="nt">needs</span><span class="p">:</span><span class="w"> </span><span class="l">deploy-staging</span><span class="w">
</span></span></span><span class="line"><span class="ln">25</span><span class="cl"><span class="w">    </span><span class="nt">runs-on</span><span class="p">:</span><span class="w"> </span><span class="l">ubuntu-latest</span><span class="w">
</span></span></span><span class="line"><span class="ln">26</span><span class="cl"><span class="w">    </span><span class="nt">environment</span><span class="p">:</span><span class="w"> </span><span class="l">production</span><span class="w">
</span></span></span><span class="line"><span class="ln">27</span><span class="cl"><span class="w">    </span><span class="nt">steps</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">28</span><span class="cl"><span class="w">      </span>- <span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">actions/checkout@v4</span><span class="w">
</span></span></span><span class="line"><span class="ln">29</span><span class="cl"><span class="w">      </span>- <span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">aws-actions/configure-aws-credentials@v4</span><span class="w">
</span></span></span><span class="line"><span class="ln">30</span><span class="cl"><span class="w">        </span><span class="nt">with</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">31</span><span class="cl"><span class="w">          </span><span class="nt">role-to-assume</span><span class="p">:</span><span class="w"> </span><span class="l">arn:aws:iam::123456789012:role/production-deploy</span><span class="w">
</span></span></span><span class="line"><span class="ln">32</span><span class="cl"><span class="w">          </span><span class="nt">aws-region</span><span class="p">:</span><span class="w"> </span><span class="l">ap-northeast-1</span><span class="w">
</span></span></span><span class="line"><span class="ln">33</span><span class="cl"><span class="w">      </span>- <span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="l">./scripts/deploy.sh production</span></span></span></code></pre></div><p>staging job 自動觸發。production job 等 staging 完成後暫停，等待 environment protection rules 中設定的 reviewer 核准。兩個 job 各自用不同的 IAM role，scope 分離。</p>
<p>Environment secret 與 repository secret 的差異：environment secret 只在該 environment 的 job 中可用。把 production-only 的設定（如 database connection string）存在 production environment secret 而非 repository secret，避免 staging workflow 意外存取 production 資源。</p>
<h2 id="邊界與陷阱">邊界與陷阱</h2>
<p>Environment protection rules 在 private repo 上需要 GitHub Team 或 Enterprise 方案。Free 方案的 private repo 無法使用 required reviewers 與 wait timer，只有 public repo 或付費方案可用。</p>
<p>OIDC trust policy 的常見錯誤是 subject claim 設定太寬。<code>sub</code> claim 的格式是 <code>repo:{owner}/{repo}:environment:{name}</code>（使用 environment 時）或 <code>repo:{owner}/{repo}:ref:refs/heads/{branch}</code>（不使用 environment 時）。用 wildcard match 或省略 environment 限制會讓非預期的 workflow 取得 credential。</p>
<p>Wait timer 設定要跟服務風險等級對齊。所有服務統一用 30 分鐘 wait timer 會拖慢低風險服務的 deploy velocity。對齊方式：低風險服務 0 分鐘、中風險 5-10 分鐘、高風險（交易路徑）15-30 分鐘。</p>
<p>Required reviewer 數量跟團隊大小對齊。只有 1 個 reviewer 等於沒有四眼原則；需要 5 個 reviewer 會造成 approval 排隊。2-3 個 reviewer 是多數團隊的平衡點。</p>
<h2 id="整合路由">整合路由</h2>
<ul>
<li>上游：<a href="/blog/backend/06-reliability/ci-pipeline/" data-link-title="6.1 CI pipeline" data-link-desc="CI pipeline 的分層策略、artifact 管理、flaky 治理與 release gate 輸入">6.1 CI pipeline</a>（CI gate 通過後才進入 deploy 階段）</li>
<li>下游：<a href="/blog/backend/06-reliability/release-gate/" data-link-title="6.8 Release Gate 與變更節奏" data-link-desc="把驗證、migration、相容性納入放行判準">6.8 release gate</a>（environment protection 是 deploy 層的 release gate）</li>
<li>下游：<a href="/blog/backend/06-reliability/verification-evidence-handoff/" data-link-title="6.23 Verification Evidence Handoff" data-link-desc="把 SLO、load、chaos、DR 與 readiness 結果包成 release / incident 可用證據">6.23 verification evidence handoff</a>（deploy 結果作為 release evidence）</li>
<li>平行：<a href="/blog/backend/06-reliability/vendors/circleci/" data-link-title="CircleCI" data-link-desc="CI/CD 平台、強 cache 與 parallelism">CircleCI</a> contexts + approval jobs（同類功能的不同實作）</li>
<li>案例回寫：<a href="/blog/backend/06-reliability/cases/microsoft/change-management-and-reliability-governance/" data-link-title="Microsoft：變更治理與可靠性門檻" data-link-desc="透過分層變更管理與發布閘門，降低大型 SaaS 平台的系統性回歸風險。">Microsoft 變更分層</a>（變更風險分層對應 environment 分層）、<a href="/blog/backend/06-reliability/cases/google/error-budget-policy-and-release-gating/" data-link-title="Google：Error Budget 政策如何決定發布節奏" data-link-desc="把 SLO 消耗量轉成 release gate，讓可靠性與交付速度共用同一套決策語言。">Google Error Budget</a>（error budget 消耗時提高 gate 門檻 → 可動態調整 required reviewer 數量）</li>
</ul>
]]></content:encoded></item><item><title>Auth0</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/auth0/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/auth0/</guid><description>&lt;p>Auth0 是 Customer Identity Cloud 的代表選項。它承擔三段責任：B2C / B2B app 的&lt;em>使用者登入流程&lt;/em>託管、社交與企業 connection 的 token broker、user profile 與 metadata 的 store。當產品把登入交給 Auth0、信任邊界從「我的 app 自管密碼表」變成「tenant 配置 + Action hook 程式碼 + signing key 託管」三件事是否健康。認證在 &lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/capability-buy-vs-build/" data-link-title="0.22 能力級買 vs 建：feature-as-a-service 與 BaaS bundle 選型" data-link-desc="在交付形態決定整個系統要不要自建之後、逐能力判斷該外包還是自建：辨識 managed 基礎設施、feature SaaS 與 BaaS bundle 三種外包深度、no-code 到 dev-tool 的服務光譜、買 vs 建判準與權重浮動、整合接縫與遷出代價">0.22 能力級買 vs 建&lt;/a> 裡是 commodity 買的典型、Auth0 正是它的 feature SaaS（dev-tool 端）例子；要不要買、外包到多深、見 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/capability-outsourcing-depth/" data-link-title="Capability Outsourcing Depth（外包深度）" data-link-desc="說明外包一塊後端能力有三種深度（managed 基礎設施、feature SaaS、BaaS bundle）、深度決定保留多少控制權與遷出代價">外包深度&lt;/a> 卡。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Auth0 是 &lt;em>customer identity 的控制面&lt;/em>、不是員工 SSO（員工走 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta Workforce&lt;/a> 或 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-iam-identity-center/" data-link-title="AWS IAM Identity Center" data-link-desc="AWS 原生 workforce SSO、前 AWS SSO、Permission Set 跨帳號 access、可串外部 IdP federation">AWS IAM Identity Center&lt;/a>）。雖然 Auth0 於 2021 被 Okta 收購、目前屬「Customer Identity Cloud」產品線、跟 Workforce Okta 是 &lt;em>同公司不同 control plane&lt;/em>：tenant 叢集、事件分布、signing key 託管路徑都分開、Okta Workforce 的事故（2022 Sitel、2023 support system HAR）並未直接打到 Auth0 customer。&lt;/p>
&lt;p>跟自管 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/keycloak/" data-link-title="Keycloak" data-link-desc="Open source self-hosted Identity Provider、Red Hat 主導、Realm-based multi-tenancy、適合資料主權與自訂 flow 需求">Keycloak&lt;/a> 比、Auth0 把 Universal Login UI、social connection 預建、Rules / Action runtime、attack protection 都託管出去 — 代價是 &lt;em>SaaS 計費、token issuance / login attempt 都計量&lt;/em>、流量大的 B2C 場景遇到 credential stuffing 不擋會吃成本。跟 &lt;a href="https://docs.aws.amazon.com/cognito/">AWS Cognito&lt;/a> / &lt;a href="https://firebase.google.com/docs/auth">Firebase Auth&lt;/a> 比、Auth0 的核心優勢是 &lt;em>developer-first tenant 體驗 + 預建 social connection（Google / Facebook / Apple / Microsoft 等數十種）+ Action hook 寫 JS 客製&lt;/em>。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本頁、讀者能判斷：&lt;/p>
&lt;ol>
&lt;li>Auth0 該承擔哪一段 customer identity 控制（login flow / token broker / profile store / B2B Organizations）、哪一段該回到自己的 app&lt;/li>
&lt;li>Auth0 tenant 的信任邊界與最低稽核需求（admin role、management API token、Action 程式碼、connection 設定）&lt;/li>
&lt;li>Auth0 流量出事或母公司事件時的降級路徑（fallback connection、token rotation、anomaly throttle）&lt;/li>
&lt;li>何時用 Auth0、何時走 Cognito / Firebase Auth / Keycloak 的取捨&lt;/li>
&lt;/ol>
&lt;h2 id="最短判讀路徑">最短判讀路徑&lt;/h2>
&lt;p>判斷 Auth0 tenant 是否健康、最少看四件事：&lt;/p></description><content:encoded><![CDATA[<p>Auth0 是 Customer Identity Cloud 的代表選項。它承擔三段責任：B2C / B2B app 的<em>使用者登入流程</em>託管、社交與企業 connection 的 token broker、user profile 與 metadata 的 store。當產品把登入交給 Auth0、信任邊界從「我的 app 自管密碼表」變成「tenant 配置 + Action hook 程式碼 + signing key 託管」三件事是否健康。認證在 <a href="/blog/backend/00-service-selection/capability-buy-vs-build/" data-link-title="0.22 能力級買 vs 建：feature-as-a-service 與 BaaS bundle 選型" data-link-desc="在交付形態決定整個系統要不要自建之後、逐能力判斷該外包還是自建：辨識 managed 基礎設施、feature SaaS 與 BaaS bundle 三種外包深度、no-code 到 dev-tool 的服務光譜、買 vs 建判準與權重浮動、整合接縫與遷出代價">0.22 能力級買 vs 建</a> 裡是 commodity 買的典型、Auth0 正是它的 feature SaaS（dev-tool 端）例子；要不要買、外包到多深、見 <a href="/blog/backend/knowledge-cards/capability-outsourcing-depth/" data-link-title="Capability Outsourcing Depth（外包深度）" data-link-desc="說明外包一塊後端能力有三種深度（managed 基礎設施、feature SaaS、BaaS bundle）、深度決定保留多少控制權與遷出代價">外包深度</a> 卡。</p>
<h2 id="服務定位">服務定位</h2>
<p>Auth0 是 <em>customer identity 的控制面</em>、不是員工 SSO（員工走 <a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta Workforce</a> 或 <a href="/blog/backend/07-security-data-protection/vendors/aws-iam-identity-center/" data-link-title="AWS IAM Identity Center" data-link-desc="AWS 原生 workforce SSO、前 AWS SSO、Permission Set 跨帳號 access、可串外部 IdP federation">AWS IAM Identity Center</a>）。雖然 Auth0 於 2021 被 Okta 收購、目前屬「Customer Identity Cloud」產品線、跟 Workforce Okta 是 <em>同公司不同 control plane</em>：tenant 叢集、事件分布、signing key 託管路徑都分開、Okta Workforce 的事故（2022 Sitel、2023 support system HAR）並未直接打到 Auth0 customer。</p>
<p>跟自管 <a href="/blog/backend/07-security-data-protection/vendors/keycloak/" data-link-title="Keycloak" data-link-desc="Open source self-hosted Identity Provider、Red Hat 主導、Realm-based multi-tenancy、適合資料主權與自訂 flow 需求">Keycloak</a> 比、Auth0 把 Universal Login UI、social connection 預建、Rules / Action runtime、attack protection 都託管出去 — 代價是 <em>SaaS 計費、token issuance / login attempt 都計量</em>、流量大的 B2C 場景遇到 credential stuffing 不擋會吃成本。跟 <a href="https://docs.aws.amazon.com/cognito/">AWS Cognito</a> / <a href="https://firebase.google.com/docs/auth">Firebase Auth</a> 比、Auth0 的核心優勢是 <em>developer-first tenant 體驗 + 預建 social connection（Google / Facebook / Apple / Microsoft 等數十種）+ Action hook 寫 JS 客製</em>。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>Auth0 該承擔哪一段 customer identity 控制（login flow / token broker / profile store / B2B Organizations）、哪一段該回到自己的 app</li>
<li>Auth0 tenant 的信任邊界與最低稽核需求（admin role、management API token、Action 程式碼、connection 設定）</li>
<li>Auth0 流量出事或母公司事件時的降級路徑（fallback connection、token rotation、anomaly throttle）</li>
<li>何時用 Auth0、何時走 Cognito / Firebase Auth / Keycloak 的取捨</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Auth0 tenant 是否健康、最少看四件事：</p>
<ul>
<li><strong>誰能做什麼</strong>：Dashboard admin、Management API token 的 owner 與 scope、Action 是否走 code review、tenant 之間（dev / staging / prod）是否分離且授權獨立</li>
<li><strong>憑證在哪裡</strong>：Management API token / M2M client 的 scope 與 TTL、社交 connection 的 client secret 存放位置、signing key（per-tenant）的 rotation 節奏、是否啟用 Custom Domain（避免 token issuer 暴露 <code>*.auth0.com</code> 域名）</li>
<li><strong>入口如何暴露</strong>：登入走 Universal Login（託管 UI）還是 Embedded Login（嵌自家 app）、Cross-Origin Authentication 是否打開、Attack Protection（bot detection / brute-force / breached password / suspicious IP throttling）配置強度</li>
<li><strong>證據是否可回查</strong>：Tenant Log 是否同步到 SIEM（Log Stream 推 HTTP / Datadog / Splunk）、登入失敗 / Action 例外 / Management API 變更是否 alert、保留期是否符合合規要求</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">Audit Log</a> 與 <a href="/blog/backend/knowledge-cards/authentication/" data-link-title="Authentication" data-link-desc="說明系統如何確認呼叫者身份">Authentication</a> 邊界的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>Tenant 與環境分離</strong>：Auth0 的 tenant 是邏輯隔離的多租戶 SaaS、不是物理叢集。每個環境（dev / staging / prod）開獨立 tenant、避免 dev 的 Action bug 打到 prod 流量、避免共用 client secret 跨環境洩漏。tenant 間用 <code>auth0-deploy-cli</code> 同步配置、Action 程式碼進版控。</p>
<p><strong>Connection 設計</strong>：Database Connection（Auth0 託管帳密 store）跟 Social / Enterprise Connection（OIDC / SAML federation 到 Google / Microsoft / Okta）是兩種來源。決策點是 <em>user 是否要進 Auth0 profile store</em> — 純 federation 不存密碼、純 Database Connection 是 Auth0 替 app 管帳密表。混用要清楚 <em>primary identity</em> 與 <em>linked account</em> 的合併規則。</p>
<p><strong>Action / Rule hook 的風險</strong>：Action（新框架）跟 Rule（舊框架）讓 tenant admin 在 login pipeline 注入 JS 程式碼（pre / post login、M2M、send email 等）。這是 Auth0 強大但也是 <em>最大的供應鏈攻擊面</em> — Action 可以 <code>require()</code> npm package、惡意 dependency 會在每個 login flow 執行。應該 pin dependency 版本、code review、用最小權限的 Management API scope、定期掃 dependency CVE（思維對齊 <a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/" data-link-title="7.R7.2 Supply Chain 類案例" data-link-desc="整理第三方整合、CI/CD、更新鏈、開源與 MSP 供應鏈事故案例">紅隊 supply chain 案例</a>）。</p>
<p><strong>Universal Login vs Embedded Login</strong>：Universal Login 把登入 UI 託管在 Auth0 domain（或 Custom Domain）、user 跳轉到該頁完成登入後 redirect 回 app — 防 phishing / CSRF 的成本由 Auth0 吃。Embedded Login 把登入表單嵌進自己 app 並用 <code>/co/authenticate</code> 端點 — 看似 UX 順、但要自己防 XSS、CSRF、CORS、credential leak、且要打開 Cross-Origin Authentication（暴露額外攻擊面）。預設選 Universal Login、Embedded 只在 UX 強需求且能承擔安全成本時開。</p>
<p><strong>Management API token / M2M client</strong>：Management API 控制整個 tenant（建 user、改 client secret、改 Action 程式碼）。token 不該長期存在程式碼或 CI；改用 M2M Application（client credentials grant）拿短期 token、scope 收到最小（<code>read:users</code> ≠ <code>update:users</code> ≠ <code>update:actions</code>）、走 <a href="/blog/backend/knowledge-cards/secret-management/" data-link-title="Secret Management" data-link-desc="說明 token、key、password 與憑證如何保存、輪替與撤銷">Secret Management</a> 取用。</p>
<p><strong>Attack Protection 配置</strong>：B2C 流量大、登入嘗試本身計費也是攻擊面。Brute-force Protection（單 IP 多失敗鎖 user）、Suspicious IP Throttling（單 IP 多失敗鎖 IP）、Breached Password Detection（已洩漏密碼禁用）、Bot Detection（CAPTCHA / risk score）四個機制都該打開、否則 credential stuffing 既吃成本也提高帳號被接管的機率。</p>
<p><strong>Break-glass 與 fallback</strong>：B2C 場景沒有「員工備用 admin」概念、break-glass 是 <em>確保使用者在 Auth0 暫不可用時仍能登入</em>。常見作法：app 端容忍 Auth0 暫時失敗、提供 magic link / email OTP 的替代登入路徑（透過獨立 ESP）、或預先發放長 TTL 的 refresh token 撐過短時故障。tenant 管理面則維持至少 2 個獨立 admin、credential 離線存。</p>
<p><strong>Audit / handoff</strong>：Tenant Log 透過 Log Stream 推 SIEM、alert 三類事件 — Management API 對 Action / Connection / Client 的變更（供應鏈）、登入異常突增（credential stuffing）、support impersonation / Auth0 員工 access tenant 的紀錄（control plane）。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Auth0</th>
          <th>AWS Cognito</th>
          <th>Firebase Auth</th>
          <th>自管 Keycloak</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>控制面責任</td>
          <td>Auth0 託管 issuer / signing / Action runtime</td>
          <td>AWS 託管、限 AWS 帳號信任邊界</td>
          <td>Google 託管、綁 Firebase / GCP</td>
          <td>自己跑 issuer、key、HA、support</td>
      </tr>
      <tr>
          <td>Social connection</td>
          <td>預建數十種、UI / token broker 完整</td>
          <td>主要 OIDC / SAML、social 要自己接</td>
          <td>Google / Apple / Facebook 預建、其他要自接</td>
          <td>OIDC / SAML 通用、specific provider 要自配</td>
      </tr>
      <tr>
          <td>客製化能力</td>
          <td>Action JS hook 強、Universal Login 高度客製</td>
          <td>Lambda Trigger、UI 客製有限</td>
          <td>Cloud Function Trigger、UI 客製中等</td>
          <td>任何 — 自己掌握程式碼</td>
      </tr>
      <tr>
          <td>計費模型</td>
          <td>月活躍 user（MAU）+ B2B Organizations + 進階功能加價</td>
          <td>MAU 階梯、AWS 內部其他資源費用</td>
          <td>MAU + 簡訊 / phone auth 另計</td>
          <td>自管基礎設施成本</td>
      </tr>
      <tr>
          <td>成本陡升點</td>
          <td>大量 MAU、credential stuffing、Adaptive MFA 加價</td>
          <td>Cognito Identity Pool federation 複雜場景</td>
          <td>通常便宜、但 phone auth 成本明顯</td>
          <td>規模化後運維成本（HA、DR、cert、upgrade）</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>B2C / B2B SaaS、要 social login、developer-first</td>
          <td>AWS-heavy 後端、不要求 social 廣度</td>
          <td>mobile-first、Firebase 生態內</td>
          <td>主權 / 自管要求、不接受 SaaS IdP</td>
      </tr>
      <tr>
          <td>退場成本</td>
          <td>中高 — user / password hash 可匯出、Action 要重寫</td>
          <td>中 — Cognito user pool 可匯出、policy 重寫</td>
          <td>中 — Firebase user 可匯出</td>
          <td>低 — 自己掌握</td>
      </tr>
  </tbody>
</table>
<p>選 Auth0 的核心訴求：<em>customer identity + 大量 social / enterprise connection + 要 developer 客製 login flow</em>、且接受 SaaS 計費與第三方控制面風險、能投入 SIEM / Action 程式碼治理 / attack protection 配置。</p>
<p>Microsoft 生態（Entra External ID / 前 Azure AD B2C）是另一個 B2C / B2B 選項、本表沒列入主要競品 — 它在 M365 / Azure 重度組織內是合理選擇、但 social connection 預建廣度跟 developer-centric tenant 體驗仍不及 Auth0。M365 重度 + B2C 需求的組織可同時評估 <a href="/blog/backend/07-security-data-protection/vendors/azure-rbac/" data-link-title="Azure RBAC &#43; Entra ID" data-link-desc="Azure 雙層身份/權限體系、Entra ID（IdP）&#43; Azure RBAC（resource permission）、Conditional Access、PIM、Managed Identity">Entra ID</a> 的 External ID 產品線。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Action / Rule 的供應鏈治理</strong>：Action 程式碼進版控、走 PR review、<code>auth0-deploy-cli</code> 部署。Action 引用的 npm dependency pin 版本、避免 <code>^</code> / <code>~</code>、CI 跑 SCA 掃 CVE。新增 Action 時 default scope 給 read-only、需要寫操作另外升級。Action secret（OAuth credential、API key）走 Action Secret 管理、不寫死在程式碼。</p>
<p><strong>B2B Organizations</strong>：Auth0 Organizations 把同 tenant 內的多客戶（B2B 場景）邏輯隔離 — 每個 organization 有自己的 connection、branding、member。設計點是 <em>user 是 organization member 還是 tenant-wide user</em>、跨 organization 操作的 admin 是否有 organization scope。Organization 之間的隔離是 tenant 內邏輯層、共享底層 control plane、不能等同實體 tenant 隔離。</p>
<p><strong>Adaptive MFA / Step-up Authentication</strong>：Auth0 Adaptive MFA 用 device / location / behavioral signal 動態升級 MFA 要求（impossible travel、新裝置、低信任 IP）。屬付費 add-on、本質是把 risk-based 認證內建。對 B2C 場景比強制全 user MFA 友善、但要把 <em>risk threshold</em> 跟 <em>false positive 容忍度</em> 設清楚、避免合法 user 被連續挑戰流失。</p>
<p><strong>Custom Domain</strong>：預設登入網域是 <code>&lt;tenant&gt;.auth0.com</code>、揭露使用 Auth0 與 tenant 名稱、且 issuer 是 Auth0 子網域。Custom Domain 把 issuer 改成自己網域（如 <code>login.example.com</code>）、user 看到的 URL 一致、降低 phishing 對照成本。屬付費功能、production app 預設應該開。</p>
<p><strong>Cross-Origin Authentication 的攻擊面</strong>：Embedded Login 必須開 Cross-Origin Authentication、讓 app 域名直接呼叫 Auth0 的 <code>/co/authenticate</code>。風險是 XSS 拿到 token、CSRF 偽造登入、third-party cookie 政策變動讓 silent auth 壞掉。Universal Login 不需要這個、所以同樣風險不存在 — 這是 Universal Login 推薦的核心理由。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Management API token 散落 / 過權</strong>：CI / 後端服務各自存 token、scope 都給 <code>update:users</code> / <code>update:actions</code> — 改 M2M Application + 最小 scope、定期 rotate、用 <a href="/blog/backend/knowledge-cards/secret-management/" data-link-title="Secret Management" data-link-desc="說明 token、key、password 與憑證如何保存、輪替與撤銷">Secret Management</a> 集中取用</li>
<li><strong>Action 直接 <code>require</code> 未 pin 的 npm package</strong>：login flow 每次都拉最新版、惡意 dependency 直接執行 — pin 版本、code review、定期掃 CVE</li>
<li><strong>登入嘗試暴增 / 計費突增</strong>：Attack Protection 沒開或門檻太鬆、credential stuffing 吃額度 — 打開 Bot Detection、Brute-force、Suspicious IP Throttling、配合 <a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">Anomaly Detection</a></li>
<li><strong>使用 Embedded Login 又沒控 XSS</strong>：自家 app 一旦 XSS、token 直接被偷 — 改 Universal Login、或補上嚴格 CSP / DOM 防護、定期 pen test</li>
<li><strong>Tenant Log 沒進 SIEM</strong>：事件只在 Dashboard、無法跨系統 correlation — 配 Log Stream 打到 <a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">SIEM</a>、特定事件接 <a href="/blog/backend/knowledge-cards/alert-runbook/" data-link-title="Alert Runbook" data-link-desc="說明告警如何連到可執行的排障與恢復流程">alert runbook</a></li>
<li><strong>沒 Custom Domain</strong>：phishing 對照成本低、issuer 暴露 vendor — 配 Custom Domain、TLS cert 自管或走 Auth0 託管</li>
<li><strong>B2B Organizations 缺 scope 限制</strong>：admin 工具沒按 organization scope、單一 admin compromise 跨 organization 擴散 — 思維對齊 <a href="/blog/backend/07-security-data-protection/cases/okta-cross-tenant-impersonation-2023/" data-link-title="7.C6 Okta：Cross-tenant Impersonation 防禦回寫" data-link-desc="跨租戶 impersonation 風險如何轉成身份治理與偵測策略。">Okta Cross-Tenant 2023</a> 的 lesson</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>員工 SSO / Workforce identity</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta vendor</a> / <a href="/blog/backend/07-security-data-protection/vendors/aws-iam-identity-center/" data-link-title="AWS IAM Identity Center" data-link-desc="AWS 原生 workforce SSO、前 AWS SSO、Permission Set 跨帳號 access、可串外部 IdP federation">AWS IAM Identity Center</a></td>
      </tr>
      <tr>
          <td>自管 / 不接受 SaaS IdP</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/keycloak/" data-link-title="Keycloak" data-link-desc="Open source self-hosted Identity Provider、Red Hat 主導、Realm-based multi-tenancy、適合資料主權與自訂 flow 需求">Keycloak vendor</a></td>
      </tr>
      <tr>
          <td>AWS-only 應用</td>
          <td><a href="https://docs.aws.amazon.com/cognito/">AWS Cognito</a></td>
      </tr>
      <tr>
          <td>Firebase / mobile-first 生態</td>
          <td><a href="https://firebase.google.com/docs/auth">Firebase Authentication</a></td>
      </tr>
      <tr>
          <td>Cloud resource 權限（非人類身份）</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google IAM</a> / <a href="/blog/backend/07-security-data-protection/vendors/azure-rbac/" data-link-title="Azure RBAC &#43; Entra ID" data-link-desc="Azure 雙層身份/權限體系、Entra ID（IdP）&#43; Azure RBAC（resource permission）、Conditional Access、PIM、Managed Identity">Azure RBAC</a></td>
      </tr>
      <tr>
          <td>事件偵測（跨系統）</td>
          <td><a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">7.13 偵測覆蓋率與訊號治理</a></td>
      </tr>
      <tr>
          <td>Secret / API key 治理</td>
          <td><a href="/blog/backend/07-security-data-protection/secrets-and-machine-credential-governance/" data-link-title="7.6 秘密管理與機器憑證治理" data-link-desc="以問題驅動方式整理 secret、token、key 與機器身份治理">7.6 秘密管理與機器憑證治理</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Auth0 完整 OIDC / OAuth2 規格細節</li>
<li>Action / Rule 完整 API 與 trigger 清單</li>
<li>B2B Organizations 完整 schema 與 SDK 整合教學</li>
<li>Auth0 定價層級的詳細功能對照</li>
<li>各 social connection provider 的 OAuth app 註冊步驟</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>Auth0 在 07 沒有直接案例（母公司 Okta 的事件並未直接打到 Auth0 customer），以下案例採對照引用、抽取對 Auth0 customer 的 lesson。要注意的是 <em>缺直接案例不等於 vendor 沒有風險</em> — Auth0 自 2021 被 Okta 收購以來未公開重大 vendor 級事件、但同類 SaaS IdP 的歷史事件（Okta 集團、signing key 託管、credential stuffing）都是 Auth0 customer 的可預期風險面、不該等到第一次出事才補控制：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 Auth0 的關係（對照）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/cases/okta-support-system-incident-2023/" data-link-title="7.C5 Okta：2023 Support System 事件" data-link-desc="支援系統憑證風險如何擴散到客戶租戶的案例。">Okta Support System Incident 2023</a></td>
          <td>母公司 Workforce 事件、Auth0 customer 未直接受害；lesson：signing key 受託管時 break-glass 與替代登入路徑必要</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/cases/failure-credential-rotation-without-scope/" data-link-title="7.C9 反例：憑證輪替未分 Scope" data-link-desc="憑證輪替若未分域分批，容易造成跨系統連鎖中斷。">Failure: Credential Rotation Without Scope</a></td>
          <td>Management API token / connection client secret 的 rotation 要分域 — 多 tenant / 多 connection 不能用同一把</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/cloudflare-2023-okta-token-follow-through/" data-link-title="7.R7.1.6 Cloudflare 2023：供應商事件後的身分收斂" data-link-desc="同一條供應商事件鏈，如何在客戶端變成 session 與 token 的收斂壓力">Cloudflare 2023 Okta Token Follow-Through</a></td>
          <td>上游 IdP 事件後客戶側的 token rotation 節奏；Auth0 customer 應主動 rotate Management API token、不等供應商公告</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/uber-2022-mfa-fatigue/" data-link-title="7.R7.1.1 Uber 2022：MFA 疲勞與內部工具擴散" data-link-desc="從社交工程到內部工具存取，拆解身分流程與權限邊界的失效點">Uber 2022 MFA Fatigue</a></td>
          <td>Auth0 Adaptive MFA / step-up 的設計目標 — 高風險動作要求 phishing-resistant factor、避免單純 push fatigue</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/" data-link-title="7.R7.2 Supply Chain 類案例" data-link-desc="整理第三方整合、CI/CD、更新鏈、開源與 MSP 供應鏈事故案例">紅隊 supply chain 案例</a></td>
          <td>Action / Rule 引用 npm dependency 的供應鏈攻擊面、思維同 build pipeline 但發生在 login flow</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/identity-access-boundary/" data-link-title="7.2 身分與授權邊界" data-link-desc="以問題驅動方式整理身分、授權、會話與供應商身分鏈">7.2 身分與授權邊界</a>、<a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">7.13 偵測覆蓋率與訊號治理</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta vendor</a>、<a href="/blog/backend/07-security-data-protection/vendors/keycloak/" data-link-title="Keycloak" data-link-desc="Open source self-hosted Identity Provider、Red Hat 主導、Realm-based multi-tenancy、適合資料主權與自訂 flow 需求">Keycloak vendor</a>、<a href="/blog/backend/07-security-data-protection/vendors/aws-iam-identity-center/" data-link-title="AWS IAM Identity Center" data-link-desc="AWS 原生 workforce SSO、前 AWS SSO、Permission Set 跨帳號 access、可串外部 IdP federation">AWS IAM Identity Center</a></li>
<li>下游：<a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google Cloud IAM</a>（Auth0 認證後的 cloud resource 權限層）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（Auth0 異常如何 routing 進 IR 流程）</li>
<li>官方：<a href="https://auth0.com/docs">Auth0 Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>AWS Secrets Manager</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-secrets-manager/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-secrets-manager/</guid><description>&lt;p>AWS Secrets Manager 是 AWS 原生的 &lt;em>static secret 集中保管 service&lt;/em>、核心能力是把 secret 用 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-kms/" data-link-title="AWS KMS" data-link-desc="AWS 原生 key management service、envelope encryption / digital signing / Multi-Region Key、Key Policy &amp;#43; Grant 雙軌授權">KMS&lt;/a> 加密儲存、加上 &lt;em>built-in rotation Lambda&lt;/em>（針對 RDS / Redshift / DocumentDB）跟 &lt;em>Resource Policy + IAM Policy 雙層 grant&lt;/em>、把 secret lifecycle 鎖在 AWS account / IAM 邊界內。設計取捨跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault&lt;/a> 不同 — Secrets Manager 不做 dynamic credential、不做 transit encryption、不做內部 PKI、只把 &lt;em>static secret + AWS native DB rotation&lt;/em> 這條路徑做到極致。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Secrets Manager 的定位是 &lt;em>AWS-only workload 的 static secret 控制面&lt;/em>、跟 &lt;a href="https://docs.aws.amazon.com/systems-manager/">SSM Parameter Store&lt;/a> SecureString 在 &lt;em>存 secret&lt;/em> 這層功能重疊、但設計目的不同。Parameter Store 是 &lt;em>parameter 管理&lt;/em>（free tier、advanced parameter 每 10000 個約 $0.05、KMS 加密但無 staging label 與 rotation Lambda）；Secrets Manager 是 &lt;em>secret 管理&lt;/em>（每個 secret per month $0.40 + API call、有 staging label / rotation Lambda / Resource Policy / Cross-Region Replica）。價差 8 倍以上、選擇基準在 &lt;em>是否需要 rotation 跟 cross-account sharing&lt;/em>。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault&lt;/a> 比、Secrets Manager 是 &lt;em>單一雲、簡單、低運維&lt;/em>、Vault 是 &lt;em>跨雲、dynamic credential、高表達力&lt;/em>。AWS-only 組織用 Vault 等於多扛一個 HA cluster 運維成本只為了拿 KV engine 跟 RDS rotation、ROI 不划算；反向跨雲組織用 Secrets Manager 等於每個雲都自己一套 secret store、治理鏈會斷。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/google-secret-manager/" data-link-title="Google Secret Manager" data-link-desc="GCP 原生 secret store、CMEK &amp;#43; Workload Identity Federation 整合、rotation 走自寫 Cloud Function 而非 built-in Lambda">Google Secret Manager&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/azure-key-vault/" data-link-title="Azure Key Vault" data-link-desc="Azure 三合一 service（Secret &amp;#43; Key &amp;#43; Certificate）、整合 Managed Identity &amp;#43; Entra ID RBAC、Premium tier 走 HSM">Azure Key Vault&lt;/a> 比、設計理念類似（雲廠 managed、KMS 加密、IAM 授權）但 rotation 機制各家不同 — Secrets Manager 用 built-in Lambda 四階段 flow、GSM 用 Pub/Sub event 觸發自寫 Cloud Function、Azure 用 Key Vault rotation policy + Event Grid。&lt;/p></description><content:encoded><![CDATA[<p>AWS Secrets Manager 是 AWS 原生的 <em>static secret 集中保管 service</em>、核心能力是把 secret 用 <a href="/blog/backend/07-security-data-protection/vendors/aws-kms/" data-link-title="AWS KMS" data-link-desc="AWS 原生 key management service、envelope encryption / digital signing / Multi-Region Key、Key Policy &#43; Grant 雙軌授權">KMS</a> 加密儲存、加上 <em>built-in rotation Lambda</em>（針對 RDS / Redshift / DocumentDB）跟 <em>Resource Policy + IAM Policy 雙層 grant</em>、把 secret lifecycle 鎖在 AWS account / IAM 邊界內。設計取捨跟 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a> 不同 — Secrets Manager 不做 dynamic credential、不做 transit encryption、不做內部 PKI、只把 <em>static secret + AWS native DB rotation</em> 這條路徑做到極致。</p>
<h2 id="服務定位">服務定位</h2>
<p>Secrets Manager 的定位是 <em>AWS-only workload 的 static secret 控制面</em>、跟 <a href="https://docs.aws.amazon.com/systems-manager/">SSM Parameter Store</a> SecureString 在 <em>存 secret</em> 這層功能重疊、但設計目的不同。Parameter Store 是 <em>parameter 管理</em>（free tier、advanced parameter 每 10000 個約 $0.05、KMS 加密但無 staging label 與 rotation Lambda）；Secrets Manager 是 <em>secret 管理</em>（每個 secret per month $0.40 + API call、有 staging label / rotation Lambda / Resource Policy / Cross-Region Replica）。價差 8 倍以上、選擇基準在 <em>是否需要 rotation 跟 cross-account sharing</em>。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a> 比、Secrets Manager 是 <em>單一雲、簡單、低運維</em>、Vault 是 <em>跨雲、dynamic credential、高表達力</em>。AWS-only 組織用 Vault 等於多扛一個 HA cluster 運維成本只為了拿 KV engine 跟 RDS rotation、ROI 不划算；反向跨雲組織用 Secrets Manager 等於每個雲都自己一套 secret store、治理鏈會斷。跟 <a href="/blog/backend/07-security-data-protection/vendors/google-secret-manager/" data-link-title="Google Secret Manager" data-link-desc="GCP 原生 secret store、CMEK &#43; Workload Identity Federation 整合、rotation 走自寫 Cloud Function 而非 built-in Lambda">Google Secret Manager</a> / <a href="/blog/backend/07-security-data-protection/vendors/azure-key-vault/" data-link-title="Azure Key Vault" data-link-desc="Azure 三合一 service（Secret &#43; Key &#43; Certificate）、整合 Managed Identity &#43; Entra ID RBAC、Premium tier 走 HSM">Azure Key Vault</a> 比、設計理念類似（雲廠 managed、KMS 加密、IAM 授權）但 rotation 機制各家不同 — Secrets Manager 用 built-in Lambda 四階段 flow、GSM 用 Pub/Sub event 觸發自寫 Cloud Function、Azure 用 Key Vault rotation policy + Event Grid。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>哪些 secret 用 Secrets Manager、哪些可以下放到 Parameter Store、哪些該走 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a> 的 dynamic credential</li>
<li>Secrets Manager 的 <em>雙層 grant 模型</em>（Resource Policy + IAM Policy）跟 KMS encryption key custody 怎麼配</li>
<li>Built-in rotation 跟 Custom Rotation Lambda 的設計邊界、staging label 在 zero-downtime rotation 內的角色</li>
<li>何時 Secrets Manager 已經不夠用、要往 Vault / 跨雲 broker 走</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷一個 Secrets Manager 部署是否健康、最少看四件事：</p>
<ul>
<li><strong>誰能 GetSecretValue</strong>：IAM Policy 那邊是不是用 <code>secretsmanager:GetSecretValue</code> 限定到 <em>特定 secret ARN</em>（不是 <code>*</code>）、Resource Policy 是不是只允許特定 principal（不是 <code>Principal: *</code>）、跨帳號 share 有沒有用 ABAC tag 限縮</li>
<li><strong>KMS key custody</strong>：secret 用 <em>AWS-managed key</em>（<code>aws/secretsmanager</code>）還是 <em>customer-managed key</em>（CMK）— production 應該全部 CMK、key policy 限定 only Secrets Manager service principal 可用、KMS key 持有者跟 secret 持有者要分離</li>
<li><strong>Rotation 設定</strong>：rotation 開了沒、rotation interval 多久、Lambda 過去執行 success rate、staging label 在 rotation 過程中是否依序 promote（AWSPENDING → AWSCURRENT → AWSPREVIOUS）</li>
<li><strong>CloudTrail data event</strong>：<code>GetSecretValue</code> 是 <em>Data event</em>、預設不記、要手動開 data event logging — 沒開等於事故時看不到 <em>誰拿了 secret</em>、只看得到 management API（CreateSecret / UpdateSecret）</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/knowledge-cards/secret-management/" data-link-title="Secret Management" data-link-desc="說明 token、key、password 與憑證如何保存、輪替與撤銷">Secret Management</a> 跟 <a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">Audit Log</a> 邊界的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>Resource Policy + IAM Policy 雙層 grant</strong>：Secrets Manager 跟 S3 bucket policy 同模型 — IAM Policy 控制 <em>principal 端能做什麼</em>、Resource Policy 控制 <em>secret 端允許誰來</em>、兩者要 <em>都同意</em> 才放行。常見錯配：Resource Policy 寫 <code>Principal: &quot;*&quot;</code> 加 <code>aws:SourceAccount</code> condition 想做跨帳號 share、但 condition 漏寫或寫錯就變成公開可讀。跨帳號 share 一定要明確列 <code>Principal: arn:aws:iam::123456789012:role/AppRole</code>、不要靠 wildcard + condition 拼隔離。</p>
<p><strong>IAM Policy 細粒度授權</strong>：<code>secretsmanager:GetSecretValue</code> 該限定到 <em>specific secret ARN</em>（不是 <code>*</code>）、配合 ABAC tag condition（<code>secretsmanager:ResourceTag/team = payments</code>）限縮 blast radius。對應 <a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/circleci-2023-secrets-rotation/" data-link-title="7.R7.2.3 CircleCI 2023：CI secrets 輪替壓力" data-link-desc="工程端點入侵後，CI 平台 secrets 如何成為高風險擴散點">CircleCI 2023 Secrets Rotation</a> — CI 出事時要能依 tag 快速列出 <em>CI runner 可拿的所有 secret</em>、沒這套 tag 就只能盲目 rotate 全部。</p>
<p><strong>KMS encryption key 選 CMK 不是 default</strong>：每個 secret 用一把 KMS key 加密、預設用 AWS-managed key <code>aws/secretsmanager</code>、production 應該換 customer-managed key（CMK）。差別在 <em>key policy 是不是自己控</em> — AWS-managed key 的 policy 同 account 任何 service 可呼叫、CMK 的 key policy 可以鎖到 only Secrets Manager service principal 加 only specific role 可 Decrypt。對應 <a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/microsoft-storm-0558-2023-signing-key-chain/" data-link-title="7.R7.1.5 Microsoft Storm-0558 2023：簽章金鑰鏈與郵件存取" data-link-desc="從簽章金鑰保護失效到雲端郵件存取，拆解身分信任鏈的關鍵控制點">Storm-0558</a> 的對照啟示：<em>key 的 blast radius 來自 key policy</em>、用 CMK 把 policy 寫窄是減 blast radius 的關鍵動作。</p>
<p><strong>Built-in Rotation Lambda 只限 AWS native DB</strong>：Secrets Manager 內建 rotation template 涵蓋 RDS（PostgreSQL / MySQL / MariaDB / Oracle / SQL Server）/ Aurora / Redshift / DocumentDB — 拿 AWS 提供的 Lambda template、設定 rotation interval（最短 1 天、最長 365 天）、Secrets Manager 自動排程觸發。其他 DB（self-hosted PostgreSQL、MongoDB Atlas、Snowflake）或 API key 要寫 <em>Custom Rotation Lambda</em>、走 4-step state machine：<code>createSecret</code>（產新 credential 存為 AWSPENDING）、<code>setSecret</code>（把新 credential 寫到 target system）、<code>testSecret</code>（用新 credential 驗證可連）、<code>finishSecret</code>（promote AWSPENDING → AWSCURRENT）。Lambda 任一步失敗 Secrets Manager 會 rollback、舊 credential 不受影響。</p>
<p><strong>Staging Label（AWSCURRENT / AWSPENDING / AWSPREVIOUS）</strong>：staging label 是 <em>指向 version 的 pointer</em>、app 一律用 <code>GetSecretValue</code> 不帶 VersionStage 拿 AWSCURRENT、rotation 過程中 Secrets Manager 先把新 credential 標 AWSPENDING、testSecret 過後 promote 到 AWSCURRENT、舊的降到 AWSPREVIOUS。設計初衷是 <em>zero-downtime rotation</em> — 但 <em>只有 app 端支援 AWSPREVIOUS fallback</em> 期間才有意義：rotation 完成瞬間有些 app instance 還拿著舊 credential，target system 應該同時接受 AWSCURRENT 跟 AWSPREVIOUS（DB rotation template 會在 setSecret 階段保留舊 user 一段時間）。對應 <a href="/blog/backend/07-security-data-protection/cases/failure-credential-rotation-without-scope/" data-link-title="7.C9 反例：憑證輪替未分 Scope" data-link-desc="憑證輪替若未分域分批，容易造成跨系統連鎖中斷。">Failure: Credential Rotation Without Scope</a>：scope map 沒做、AWSPREVIOUS 窗口期太短、長尾 batch job 拿到舊 credential 就掛。</p>
<p><strong>Cross-Region Replica</strong>：multi-region app 把 secret replicate 到其他 region、replica 在 replica region 有獨立 ARN、KMS key 跟 rotation 都要在 replica region 各自配（不能跨 region 共用 KMS key）。replica 是 <em>讀副本</em>、寫只能在 primary region、rotation 觸發後新 version 自動 sync 到 replica（有秒級延遲）。failover 時 app 直接讀 replica region ARN、不需要 cross-region call。</p>
<p><strong>Cross-Account Sharing</strong>：跨帳號 share secret 走 Resource Policy + 對方帳號 IAM Policy 雙向授權 — Resource Policy 列對方 account 的具體 role ARN、對方 role 的 IAM Policy 加 <code>GetSecretValue</code> 對應 ARN。KMS key 也要跨帳號授權（KMS key policy 加對方 role 的 Decrypt 權限）— 漏了 KMS 授權會出現 <em>GetSecretValue 成功但 Decrypt 失敗</em> 的詭異錯誤。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>AWS Secrets Manager</th>
          <th>SSM Parameter Store SecureString</th>
          <th><a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a></th>
          <th><a href="/blog/backend/07-security-data-protection/vendors/google-secret-manager/" data-link-title="Google Secret Manager" data-link-desc="GCP 原生 secret store、CMEK &#43; Workload Identity Federation 整合、rotation 走自寫 Cloud Function 而非 built-in Lambda">Google Secret Manager</a></th>
          <th><a href="/blog/backend/07-security-data-protection/vendors/azure-key-vault/" data-link-title="Azure Key Vault" data-link-desc="Azure 三合一 service（Secret &#43; Key &#43; Certificate）、整合 Managed Identity &#43; Entra ID RBAC、Premium tier 走 HSM">Azure Key Vault</a></th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>部署模型</td>
          <td>AWS managed</td>
          <td>AWS managed</td>
          <td>自管 cluster</td>
          <td>GCP managed</td>
          <td>Azure managed</td>
      </tr>
      <tr>
          <td>跨雲</td>
          <td>弱 — 綁 AWS</td>
          <td>弱 — 綁 AWS</td>
          <td>強</td>
          <td>弱 — 綁 GCP</td>
          <td>弱 — 綁 Azure</td>
      </tr>
      <tr>
          <td>每月每 secret 成本</td>
          <td>~$0.40 + API call</td>
          <td>free / advanced ~$0.05/10k</td>
          <td>self-hosted 成本</td>
          <td>~$0.06 + API call</td>
          <td>~$0.03 + operation</td>
      </tr>
      <tr>
          <td>Built-in rotation</td>
          <td>RDS / Redshift / DocumentDB 內建 Lambda</td>
          <td>無</td>
          <td>dynamic engine 自動發短期 credential</td>
          <td>無 built-in</td>
          <td>Key Vault rotation policy（key 為主）</td>
      </tr>
      <tr>
          <td>Staging label</td>
          <td>AWSCURRENT / AWSPENDING / AWSPREVIOUS</td>
          <td>無、用 version number</td>
          <td>KV v2 用 version</td>
          <td>version 機制</td>
          <td>version 機制</td>
      </tr>
      <tr>
          <td>Cross-account share</td>
          <td>Resource Policy + IAM</td>
          <td>不支援（同 account only）</td>
          <td>Vault namespace + policy</td>
          <td>IAM cross-project</td>
          <td>RBAC cross-tenant</td>
      </tr>
      <tr>
          <td>Dynamic credential</td>
          <td>無（rotation Lambda 是 static 換 static）</td>
          <td>無</td>
          <td>有（DB / cloud / SSH engine）</td>
          <td>弱（IAM impersonation）</td>
          <td>弱（Managed Identity）</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>AWS-only + static secret + RDS rotation 為主</td>
          <td>AWS-only + 大量低敏 config + 不需 rotation</td>
          <td>跨雲 + dynamic credential + 內部 PKI</td>
          <td>GCP-only + Workload Identity 已主導</td>
          <td>Azure-only + Managed Identity 已主導</td>
      </tr>
      <tr>
          <td>退場成本</td>
          <td>低</td>
          <td>低</td>
          <td>中</td>
          <td>低</td>
          <td>低</td>
      </tr>
  </tbody>
</table>
<p>選 Secrets Manager 的核心訴求：<em>AWS-only</em> + <em>大部分 secret 是 static 或 AWS native DB credential</em> + <em>需要 cross-account share 或 rotation Lambda</em> + <em>不想 / 沒量能自管 Vault</em>。如果只是要存 config（feature flag、non-sensitive endpoint）、Parameter Store 8 倍便宜；如果跨雲 + 需要 dynamic credential / transit / PKI、Vault 才能滿足。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Custom Rotation Lambda 設計</strong>：4-step state machine 是 <em>idempotent contract</em> — Lambda 必須能被 Secrets Manager 重試任意步驟而不破壞狀態。常見實作陷阱：createSecret 不檢查 AWSPENDING 是否已存在、重試時又產生一把新的、AWSPENDING 對不上 setSecret 寫進去的；setSecret 沒處理「target system 已經有同名 user」的情況、第二次跑會卡住。Template 提供的 PostgreSQL rotation Lambda 用 <em>cloning approach</em> — 在 DB 內 clone 一份 user、改密碼、保留舊 user 跨 rotation 一個週期、下次 rotation 才 drop。</p>
<p><strong>Resource Policy + ABAC tag 跨帳號</strong>：跨帳號 share 時用 ABAC tag 條件比硬列 role ARN 有彈性 — Resource Policy 寫 <code>Condition: aws:PrincipalTag/team = payments</code>、對方 account 任何帶該 tag 的 role 都可讀。代價是 <em>tag 治理</em> 變成 critical control：對方 account 內誰能 attach tag = 誰能拿 secret、IAM Policy 要鎖 <code>iam:TagRole</code> 跟 <code>iam:UntagRole</code> 權限。</p>
<p><strong>Rotation 失敗的監控訊號</strong>：Lambda 執行失敗會在 CloudWatch 留 invocation error、Secrets Manager 把 rotation 標記為 failed、但 <em>secret 仍可用</em>（AWSCURRENT 保留舊 version）— 容易出現 <em>半年沒 rotate 成功但 app 看起來正常</em> 的盲區。要監控 <code>SecretsManager.RotationFailed</code> event（EventBridge rule）+ <code>LastRotatedDate</code> metric 超過 rotation interval 1.5 倍就 alert。</p>
<p><strong>跟 <a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM</a> 整合</strong>：誰可以 <code>GetSecretValue</code> 完全由 IAM 控制、最佳實踐是 <em>workload role</em> 拿 secret（EC2 instance role / ECS task role / Lambda execution role / EKS IRSA）、不要硬把 AWS credential 塞進 secret 再給 application read。Secret 內容應該是 <em>DB password / API token / third-party credential</em>、不應該是 <em>AWS credential</em>（AWS credential 用 IAM role 短期 STS 拿就好）。</p>
<p><strong>CloudTrail data event 的成本權衡</strong>：開 <code>GetSecretValue</code> data event 等於每次 secret 取用都進 CloudTrail、高 QPS application 一天可能跑數百萬筆、CloudTrail 成本（每 100k events 約 $0.10）跟 S3 儲存成本會明顯上升。降本作法：在 EventBridge 用 <em>filtering</em>（只送特定 sensitive secret 的 data event 到 SIEM）、CloudWatch Logs 端設 retention 短一點（7-30 天熱資料、長尾走 S3 + Athena）。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>GetSecretValue AccessDenied 但 IAM Policy 看起來對</strong>：檢查 Resource Policy 是否限定 source account / VPC、檢查 KMS key policy 是否允許該 role Decrypt — 兩層 grant + KMS 三點任一缺都會 AccessDenied</li>
<li><strong>跨帳號 secret 拿不到</strong>：Resource Policy 沒列對方 role、或 KMS key policy 沒給對方 Decrypt 權限 — 跨帳號要同步配三處（Resource Policy + 對方 IAM + KMS key policy）</li>
<li><strong>Rotation 一直失敗但沒人發現</strong>：沒設 EventBridge alert on <code>RotationFailed</code>、AWSCURRENT 保持舊 version、app 正常但 secret 過期 — 必設 LastRotatedDate metric alert</li>
<li><strong>App 拿到 stale secret rotation 後爆掉</strong>：app 端用了 SDK cache（如 AWS SDK 的 Secrets Manager Cache）、rotation 完成後 cache 沒 invalidate — cache TTL 要短於 staging label 重疊窗口、或實作 retry-on-auth-fail 觸發 cache refresh</li>
<li><strong>CloudTrail 看不到誰拿 secret</strong>：沒開 data event logging — 在 CloudTrail trail 設定加上 <code>AWS::SecretsManager::Secret</code> 為 data resource</li>
<li><strong>跨 region replica rotation 失效</strong>：rotation Lambda 只在 primary region 配、replica region 沒對應 Lambda — 每個 region 各自配 Lambda、或乾脆只在 primary rotate 讓 replica 自動 sync</li>
<li><strong>AWSPREVIOUS fallback 沒生效 batch job 掛</strong>：rotation Lambda finishSecret 太快 drop 舊 user、batch job 拿到舊 credential 連 DB 失敗 — DB rotation template 預設保留舊 user 一個 rotation 週期、custom Lambda 要自己實作雙軌窗口</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>大量低敏 config / feature flag</td>
          <td><a href="https://docs.aws.amazon.com/systems-manager/">SSM Parameter Store</a>（free tier、無 rotation 需求）</td>
      </tr>
      <tr>
          <td>跨雲統一 secret 控制面</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a></td>
      </tr>
      <tr>
          <td>Dynamic DB credential（non-AWS DB）</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault database engine</a></td>
      </tr>
      <tr>
          <td>Workload 拿 AWS credential</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM</a> role（EC2 instance role / ECS task role / IRSA）— 不要把 AWS credential 塞 secret</td>
      </tr>
      <tr>
          <td>Encryption-as-a-service / envelope encryption</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/aws-kms/" data-link-title="AWS KMS" data-link-desc="AWS 原生 key management service、envelope encryption / digital signing / Multi-Region Key、Key Policy &#43; Grant 雙軌授權">AWS KMS</a> Encrypt / Decrypt API、或 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault transit engine</a></td>
      </tr>
      <tr>
          <td>內部 PKI / mTLS workload cert</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/cert-manager/" data-link-title="cert-manager" data-link-desc="K8s 原生 certificate lifecycle automation、支援 Let&#39;s Encrypt / Vault PKI / Venafi 等多 issuer、auto-renewal &#43; Challenge solver">cert-manager</a> + <a href="/blog/backend/07-security-data-protection/vendors/aws-acm/" data-link-title="AWS ACM" data-link-desc="AWS-managed certificate provisioning、DNS validation &#43; auto-renewal、整合 ELB / CloudFront / API Gateway、Private CA 後端">AWS Private CA</a></td>
      </tr>
      <tr>
          <td>Secret rotation 跨服務 scope 治理</td>
          <td><a href="/blog/backend/07-security-data-protection/credential-rotation-scoped-evidence/" data-link-title="7.27 Credential Rotation with Scoped Evidence 實作示範" data-link-desc="以 webhook/API credential 輪替示範 scope map、證據欄位與回退窗口如何一起設計。">7.5 Credential Rotation Scoped Evidence</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Secrets Manager 完整 API reference 跟 SDK 用法</li>
<li>每種 RDS engine 的 rotation Lambda template 內部 SQL 細節</li>
<li>AWS pricing 詳細計算（每 region 略有差異）</li>
<li>Terraform / CDK 跟 Secrets Manager 的 IaC 整合</li>
<li>AWS account organization / SCP 怎麼限制 secret 建立</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>Secrets Manager 在 07 案例庫沒有直接 vendor-level 事件、以下案例採對照引用：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 Secrets Manager 的關係（對照）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/cases/failure-credential-rotation-without-scope/" data-link-title="7.C9 反例：憑證輪替未分 Scope" data-link-desc="憑證輪替若未分域分批，容易造成跨系統連鎖中斷。">Failure: Credential Rotation Without Scope</a></td>
          <td>Secrets Manager rotation 必須有 scope map — 跨服務共用同一把 secret 時、AWSPREVIOUS 窗口期 + 雙軌驗證要對齊長尾 batch job、不能單靠 Lambda 自動 promote</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/circleci-2023-secrets-rotation/" data-link-title="7.R7.2.3 CircleCI 2023：CI secrets 輪替壓力" data-link-desc="工程端點入侵後，CI 平台 secrets 如何成為高風險擴散點">CircleCI 2023 Secrets Rotation (red-team)</a></td>
          <td>CI 出事時 Secrets Manager 內 <em>所有 CI runner role 可拿的 secret</em> 都要 rotate — 必須事先以 ABAC tag 標 blast radius、不然只能盲掃整個 account</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/microsoft-storm-0558-2023-signing-key-chain/" data-link-title="7.R7.1.5 Microsoft Storm-0558 2023：簽章金鑰鏈與郵件存取" data-link-desc="從簽章金鑰保護失效到雲端郵件存取，拆解身分信任鏈的關鍵控制點">Microsoft Storm-0558 Signing Key Chain (red-team)</a></td>
          <td>對照啟示 — Secrets Manager 的 KMS encryption key 必須走 CMK 而非 AWS-managed key、key policy 限定 only Secrets Manager service principal 且 only specific role 可 Decrypt、把 blast radius 鎖在 key policy 內</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/secrets-and-machine-credential-governance/" data-link-title="7.6 秘密管理與機器憑證治理" data-link-desc="以問題驅動方式整理 secret、token、key 與機器身份治理">7.6 秘密管理與機器憑證治理</a>、<a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">7.13 偵測覆蓋率與訊號治理</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a>、<a href="/blog/backend/07-security-data-protection/vendors/google-secret-manager/" data-link-title="Google Secret Manager" data-link-desc="GCP 原生 secret store、CMEK &#43; Workload Identity Federation 整合、rotation 走自寫 Cloud Function 而非 built-in Lambda">Google Secret Manager</a>、<a href="/blog/backend/07-security-data-protection/vendors/azure-key-vault/" data-link-title="Azure Key Vault" data-link-desc="Azure 三合一 service（Secret &#43; Key &#43; Certificate）、整合 Managed Identity &#43; Entra ID RBAC、Premium tier 走 HSM">Azure Key Vault</a></li>
<li>下游：<a href="/blog/backend/07-security-data-protection/vendors/aws-kms/" data-link-title="AWS KMS" data-link-desc="AWS 原生 key management service、envelope encryption / digital signing / Multi-Region Key、Key Policy &#43; Grant 雙軌授權">AWS KMS</a>（Secrets Manager 加密 key custodian、CMK 與 key policy 治理）</li>
<li>下游：<a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM</a>（誰可以 GetSecretValue、跨帳號 share 的 principal 來源）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（secret 外洩事件如何 routing 進 IR 流程）</li>
<li>官方：<a href="https://docs.aws.amazon.com/secretsmanager/">AWS Secrets Manager Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>AWS WAF</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-waf/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-waf/</guid><description>&lt;p>AWS WAF 是 &lt;em>AWS-internal&lt;/em> 的 Web Application Firewall、掛在 ALB、CloudFront、API Gateway、App Runner、AppSync 與 Cognito User Pool 的前面，攔截 HTTP/HTTPS 攻擊。它跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &amp;#43; DDoS &amp;#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/fastly-ngwaf/" data-link-title="Fastly Next-Gen WAF" data-link-desc="Behavioral / 語意分析 WAF（前 Signal Sciences）、低 false positive、Edge / Agent / Cloud 三種部署模型、API &amp;#43; ATO &amp;#43; Bot 一體">Fastly Next-Gen WAF&lt;/a> 的核心差異是 &lt;em>部署位置在 AWS 內部&lt;/em>：流量先經 AWS 邊界進來、再進 Web ACL 過濾、最後抵達 origin；不是在 Cloudflare anycast edge 提早攔。對 AWS-heavy 客戶、AWS WAF 的價值是 &lt;em>跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM&lt;/a> / VPC / &lt;a href="https://docs.aws.amazon.com/waf/latest/developerguide/shield-chapter.html">AWS Shield&lt;/a> 同一個控制面&lt;/em>；對 multi-cloud / on-prem origin、AWS WAF 觸不到、要回到 edge WAF。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>AWS WAF 的核心定位是 &lt;em>跟 AWS 服務深度耦合的 L7 防護層&lt;/em>。Web ACL 直接掛 AWS resource、規則用 IAM policy 管理、log 進 Kinesis Firehose / CloudWatch Logs / S3、跟 AWS Shield Standard（內含、L3/L4 DDoS）自動整合。這跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &amp;#43; DDoS &amp;#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF&lt;/a> 在 &lt;em>origin 之前的 edge&lt;/em> 攔截不同 — AWS WAF 流量 &lt;em>已經進到 AWS 邊界&lt;/em>、不是擋在外部。對 origin 跑在 ALB / CloudFront / API Gateway 後的客戶、AWS WAF 是天然選項；origin 在其他雲或地端、AWS WAF 觸不到。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/fastly-ngwaf/" data-link-title="Fastly Next-Gen WAF" data-link-desc="Behavioral / 語意分析 WAF（前 Signal Sciences）、低 false positive、Edge / Agent / Cloud 三種部署模型、API &amp;#43; ATO &amp;#43; Bot 一體">Fastly Next-Gen WAF&lt;/a> 相比、AWS WAF 走 &lt;em>signature + managed rule group&lt;/em> 偵測模型、不像 Fastly NG-WAF 走語意 / behavioral；AWS WAF 的 Managed Rule Group 來自 AWS Managed 與 AWS Marketplace 第三方（Fortinet、F5、Imperva 等）、客戶端 &lt;em>看不到 rule logic&lt;/em>、debug 時要靠 sampled request 反推。&lt;/p></description><content:encoded><![CDATA[<p>AWS WAF 是 <em>AWS-internal</em> 的 Web Application Firewall、掛在 ALB、CloudFront、API Gateway、App Runner、AppSync 與 Cognito User Pool 的前面，攔截 HTTP/HTTPS 攻擊。它跟 <a href="/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &#43; DDoS &#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF</a> / <a href="/blog/backend/07-security-data-protection/vendors/fastly-ngwaf/" data-link-title="Fastly Next-Gen WAF" data-link-desc="Behavioral / 語意分析 WAF（前 Signal Sciences）、低 false positive、Edge / Agent / Cloud 三種部署模型、API &#43; ATO &#43; Bot 一體">Fastly Next-Gen WAF</a> 的核心差異是 <em>部署位置在 AWS 內部</em>：流量先經 AWS 邊界進來、再進 Web ACL 過濾、最後抵達 origin；不是在 Cloudflare anycast edge 提早攔。對 AWS-heavy 客戶、AWS WAF 的價值是 <em>跟 <a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM</a> / VPC / <a href="https://docs.aws.amazon.com/waf/latest/developerguide/shield-chapter.html">AWS Shield</a> 同一個控制面</em>；對 multi-cloud / on-prem origin、AWS WAF 觸不到、要回到 edge WAF。</p>
<h2 id="服務定位">服務定位</h2>
<p>AWS WAF 的核心定位是 <em>跟 AWS 服務深度耦合的 L7 防護層</em>。Web ACL 直接掛 AWS resource、規則用 IAM policy 管理、log 進 Kinesis Firehose / CloudWatch Logs / S3、跟 AWS Shield Standard（內含、L3/L4 DDoS）自動整合。這跟 <a href="/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &#43; DDoS &#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF</a> 在 <em>origin 之前的 edge</em> 攔截不同 — AWS WAF 流量 <em>已經進到 AWS 邊界</em>、不是擋在外部。對 origin 跑在 ALB / CloudFront / API Gateway 後的客戶、AWS WAF 是天然選項；origin 在其他雲或地端、AWS WAF 觸不到。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/fastly-ngwaf/" data-link-title="Fastly Next-Gen WAF" data-link-desc="Behavioral / 語意分析 WAF（前 Signal Sciences）、低 false positive、Edge / Agent / Cloud 三種部署模型、API &#43; ATO &#43; Bot 一體">Fastly Next-Gen WAF</a> 相比、AWS WAF 走 <em>signature + managed rule group</em> 偵測模型、不像 Fastly NG-WAF 走語意 / behavioral；AWS WAF 的 Managed Rule Group 來自 AWS Managed 與 AWS Marketplace 第三方（Fortinet、F5、Imperva 等）、客戶端 <em>看不到 rule logic</em>、debug 時要靠 sampled request 反推。</p>
<p>計費模型也是關鍵差異：AWS WAF 按 <em>per-Web-ACL + per-rule + per-request</em> 計費（單 ACL $5/月、單 rule $1/月、$0.60 per 1M request），Managed Rule Group 算多 rule、開太多套 ruleset 與流量大時帳單會明顯漲。Cloudflare 是 plan-tier 計費（Pro / Business / Enterprise）、不會因為多開 rule 線性漲價。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>AWS WAF 在 AWS-internal 防護 stack 中承擔哪一段、哪些要靠 <a href="https://docs.aws.amazon.com/waf/latest/developerguide/shield-chapter.html">AWS Shield</a> / VPC / CloudFront 補位</li>
<li>Web ACL scope（Regional vs CloudFront）的選擇與跨 region 部署成本</li>
<li>Managed Rule Group / Custom Rule / Rate-based Rule 的取捨、Bot Control add-on 是否值得開</li>
<li>何時用 AWS WAF、何時走 <a href="/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &#43; DDoS &#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF</a> / <a href="/blog/backend/07-security-data-protection/vendors/fastly-ngwaf/" data-link-title="Fastly Next-Gen WAF" data-link-desc="Behavioral / 語意分析 WAF（前 Signal Sciences）、低 false positive、Edge / Agent / Cloud 三種部署模型、API &#43; ATO &#43; Bot 一體">Fastly NG-WAF</a> 的判準</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 AWS WAF 配置是否健康、最少看四件事：</p>
<ul>
<li><strong>Web ACL scope 對不對</strong>：CloudFront distribution 必須掛 <em>CloudFront scope</em>（強制在 us-east-1 建立 ACL）、ALB / API Gateway 必須掛 <em>Regional scope</em>（每個 region 各一份）；scope 配錯掛不上去、跨 region 部署是否用 IaC（Terraform / CloudFormation）同步複製 ACL</li>
<li><strong>Managed Rule Group 與 sensitivity</strong>：是否啟用 <em>AWSManagedRulesCommonRuleSet</em>（CRS）、<em>AmazonIpReputationList</em>（已知惡意 IP）、<em>AnonymousIpList</em>（VPN / proxy / Tor）、<em>KnownBadInputsRuleSet</em>（已知 exploit pattern）、Marketplace rule 是否在 Count mode 觀察 1-2 週 FP 再切 Block</li>
<li><strong>Logging 有沒有開</strong>：Web ACL log 預設關閉、必須手動配 Kinesis Firehose / CloudWatch Logs / S3 destination；event 是否進 SIEM（見 <a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">7.13 偵測覆蓋率與訊號治理</a>）、是否能對 sampled request 反推 rule 行為</li>
<li><strong>IAM 邊界</strong>：誰能 update Web ACL（<code>wafv2:UpdateWebACL</code>、<code>wafv2:UpdateRuleGroup</code>）、是否限定 admin role 才能改、CI 是否只有 <code>wafv2:Get*</code> / <code>List*</code> 用來 verify、敏感變更是否走 Change Management / <a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">Audit Log</a></li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/07-security-data-protection/entrypoint-and-server-protection/" data-link-title="7.3 入口治理與伺服器防護" data-link-desc="以問題驅動方式整理對外入口、管理平面與伺服器邊界">Entry Point Protection</a> 邊界的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>Web ACL 與 scope</strong>：Web ACL 是 AWS WAF 的 <em>規則容器</em>、必須 attach 到 AWS resource。Scope 兩種：<em>Regional</em>（給 ALB / API Gateway / App Runner / AppSync / Cognito User Pool、每 region 獨立）與 <em>CloudFront</em>（給 CloudFront distribution、必須在 us-east-1 建立、全球生效）。同一個 ACL 不能跨 scope 共用；跨 region 部署同一套規則必須複製 ACL、用 Terraform / CloudFormation 管理避免 drift。</p>
<p><strong>Rule action 五種</strong>：每個 rule 觸發時可以做 <em>Block</em>（直接 403）、<em>Allow</em>（跳過後續 rule、放行）、<em>Count</em>（不擋、只記錄、用於 dry-run 觀察 FP）、<em>CAPTCHA</em>（出題給人類解、bot 過不去）、<em>Challenge</em>（silent JS challenge、無感驗證）。新 rule 上線標準動作是先 <em>Count</em> 1-2 週看 sample、確認 FP 在容忍範圍才切 <em>Block</em>。CAPTCHA / Challenge 是 <a href="https://docs.aws.amazon.com/waf/latest/developerguide/waf-bot-control.html">Bot Control add-on</a> 配套、要額外計費。</p>
<p><strong>Managed Rule Group（managed by AWS / Marketplace）</strong>：AWS Managed（免費含在 WAF）涵蓋 <em>Common Rule Set</em>（OWASP top10 對應）、<em>Known Bad Inputs</em>、<em>SQL Database</em>、<em>Linux</em>、<em>Unix</em>、<em>Windows</em>、<em>Anonymous IP List</em>、<em>Amazon IP Reputation List</em>、<em>Account Takeover Prevention (ATP)</em>、<em>Account Creation Fraud Prevention (ACFP)</em>。AWS Marketplace（付費）來自 Fortinet / F5 / Imperva / Cyber Security Cloud 等。Marketplace 規則 <em>不公開 rule logic</em>、攔錯時只能用 sampled request 反推、debug 比 AWS Managed 困難。</p>
<p><strong>Custom Rule（statement + 條件）</strong>：Custom Rule 用 <em>statement</em>（match condition + transformation）組合：IP Set match、Geo match、Regex Pattern Set、Size constraint、SQL injection match、XSS match、String match（含 header / body / URI / query 各部位）。複雜條件用 AND / OR / NOT 組合、上限是每 Web ACL 5,000 Web ACL Capacity Units（WCU）— 規則越複雜 WCU 越高、Marketplace 大型 rule group 可能直接吃掉一半 budget。</p>
<p><strong>IP Set / Regex Pattern Set</strong>：IP Set 存 IPv4 / IPv6 CIDR 清單、Regex Pattern Set 存正則表達式集合。兩者都是 <em>獨立資源</em>、可在多個 Web ACL 引用、單獨更新（不必動 Web ACL 結構）。實務上 threat intel feed 應該 push 到 IP Set、用 Lambda 自動 sync、不用手動加。</p>
<p><strong>Rate-based Rule</strong>：限制 <em>單一 aggregate key</em> 在滾動 5 分鐘窗口內的請求數、超過 threshold 觸發 action。aggregate key 可選 <em>IP</em>、<em>Forwarded-IP</em>（看 X-Forwarded-For）、<em>HTTP method</em>、<em>URI path</em>、<em>Header</em>、<em>Cookie</em> 或組合。關鍵陷阱：<strong>CloudFront 後 origin ALB 必須用 Forwarded-IP</strong>、否則 Rate-based Rule 看到的全是 CloudFront 邊緣節點 IP、所有真實使用者被合併計算、要嘛全擋要嘛全放。</p>
<p><strong>Logging 必須手動開</strong>：Web ACL log 預設關閉、destination 三選一：<em>Kinesis Data Firehose</em>（推到 S3 / Splunk / Datadog）、<em>CloudWatch Logs</em>（簡單但貴）、<em>S3</em>（直寫、需自己處理 partition）。production 通常走 Kinesis Firehose → S3 + Athena query、配合 SIEM 拉 alert。沒開 log 等於 <em>攻擊發生時沒證據</em>、事後無法回查。</p>
<p><strong>跟 AWS Shield 整合</strong>：所有 AWS WAF 客戶自動含 <em>Shield Standard</em>（L3/L4 DDoS、免費、SYN flood / UDP reflection 等基礎防護）。<em>Shield Advanced</em> 是付費 add-on（$3,000/month per organization + per-resource fee + data transfer out fee）、提供 <em>24/7 DRT（DDoS Response Team）</em>、cost protection（DDoS 期間 AWS service scaling fee 補貼）、進階分析。一般客戶 Shield Standard 已足夠；金融 / 政府 / 高知名度品牌需要 Shield Advanced 的 DRT 與 cost protection。</p>
<p><strong>Lambda@Edge / CloudFront Functions 補位</strong>：當 WAF rule statement 表達不出複雜業務邏輯（geofencing + business hour + user tier 組合、JWT claim 解析後判斷 routing）、用 <em>Lambda@Edge</em>（Node.js / Python、跑在 CloudFront 邊緣節點、4 個 phase：viewer-request / origin-request / origin-response / viewer-response）或 <em>CloudFront Functions</em>（純 JS、輕量、低延遲、只在 viewer-request / viewer-response）補位。Lambda@Edge 適合複雜邏輯、CloudFront Functions 適合 header rewrite / 簡單 routing；兩者都不能取代 WAF managed rule、但補位 WAF 表達力上限。</p>
<p><strong>跟 <a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM</a> 整合</strong>：誰能改 Web ACL 是 <em>IAM policy</em> 決定（<code>wafv2:CreateWebACL</code>、<code>wafv2:UpdateWebACL</code>、<code>wafv2:AssociateWebACL</code>、<code>wafv2:UpdateRuleGroup</code> 等 action）。production 標準配置：admin role 才能 update、CI / 開發者只有 <code>wafv2:Get*</code> / <code>List*</code> 用來 verify、敏感變更走 Change Management + CloudTrail <a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">audit log</a>。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>AWS WAF</th>
          <th>Cloudflare WAF</th>
          <th>Fastly Next-Gen WAF</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>部署位置</td>
          <td>AWS 內部（ALB / CloudFront / API Gateway 前）</td>
          <td>Cloudflare global edge（300+ POP）</td>
          <td>Fastly global edge / 各 origin agent</td>
      </tr>
      <tr>
          <td>Origin 適配</td>
          <td>強耦合 — origin 必須在 AWS</td>
          <td>強中立 — 任意雲 / on-prem</td>
          <td>強中立 — Fastly CDN / 任何 origin</td>
      </tr>
      <tr>
          <td>計費模型</td>
          <td>per-ACL + per-rule + per-request</td>
          <td>plan tier（Free / Pro / Business / Enterprise）</td>
          <td>request-based + plan</td>
      </tr>
      <tr>
          <td>Managed Rule</td>
          <td>AWS Managed（免費）+ Marketplace（付費、logic 不透明）</td>
          <td>Cloudflare Managed + OWASP CRS + Exposed Credentials</td>
          <td>Signal-based（語意、低 FP、不靠 regex signature）</td>
      </tr>
      <tr>
          <td>Rate Limiting</td>
          <td>Rate-based Rule（含在 WAF、5 分鐘 window）</td>
          <td>Rate Limiting 獨立 product</td>
          <td>inline rate limit + Signal</td>
      </tr>
      <tr>
          <td>Bot 對應</td>
          <td>AWS WAF Bot Control（add-on、付費）</td>
          <td>Bot Management（Pro+ add-on）</td>
          <td>NG-WAF behavioral bot detection</td>
      </tr>
      <tr>
          <td>DDoS 內建</td>
          <td>Shield Standard 自動含（L3/L4）、Advanced 加價</td>
          <td>同套餐內建</td>
          <td>內建 + Fastly DDoS</td>
      </tr>
      <tr>
          <td>控制面整合</td>
          <td>跟 IAM / CloudTrail / Shield / VPC 同 plane</td>
          <td>Cloudflare 控制面、跟其他 Cloudflare 產品同套</td>
          <td>Fastly 控制面、agent 跑在 origin</td>
      </tr>
      <tr>
          <td>學習曲線</td>
          <td>中陡 — Web ACL + WCU + scope + IAM policy 多軌</td>
          <td>中 — UI / Rules language / Terraform 完整</td>
          <td>中 — agent 安裝 + Signal 語意設定</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>AWS-heavy、ALB / CloudFront 是主要入口</td>
          <td>Multi-cloud / on-prem origin、要整套 edge security</td>
          <td>高 FP 容忍度低、業務有 schema、想避 regex signature</td>
      </tr>
  </tbody>
</table>
<p>選 AWS WAF 的核心訴求：<em>AWS-internal app</em> + origin 跑在 ALB / CloudFront / API Gateway / App Runner 後 + 想跟 IAM / CloudTrail / Shield 同套 control plane 治理。Origin 不在 AWS、或要 <em>把攻擊擋在抵達雲之前</em>、應該走 <a href="/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &#43; DDoS &#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF</a> 或 <a href="/blog/backend/07-security-data-protection/vendors/fastly-ngwaf/" data-link-title="Fastly Next-Gen WAF" data-link-desc="Behavioral / 語意分析 WAF（前 Signal Sciences）、低 false positive、Edge / Agent / Cloud 三種部署模型、API &#43; ATO &#43; Bot 一體">Fastly NG-WAF</a>。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>AWS WAF Bot Control（add-on）</strong>：付費 add-on、用 AWS 自家 bot fingerprinting 區分 <em>verified bot</em>（搜尋引擎）/ <em>signal: automated browser</em>（headless Chrome 等）/ <em>signal: known bot</em>（已標記 IoT / scraper），給每個請求 <em>bot category label</em>。Custom Rule 在 label 上做條件、決定 Block / Challenge / CAPTCHA。比 user-agent 過濾準很多、但要額外計費（per-request）。Bot Control 有兩個 inspection level：<em>common</em>（便宜、基礎指紋）與 <em>targeted</em>（貴、含 JavaScript challenge、CAPTCHA、token-based）。</p>
<p><strong>Fraud Control（ATP / ACFP）</strong>：<em>Account Takeover Prevention</em>（ATP）跟 <em>Account Creation Fraud Prevention</em>（ACFP）是 Managed Rule Group 的特殊類別、需付費啟用。ATP 看登入端點的 credential stuffing、ACFP 看註冊端點的 bot signup。兩者都用 AWS 自家 threat intel（被竊憑證 list、行為模型）打 label、客戶側用 Custom Rule 處理。對有 login / signup 端點的 SaaS / 電商有價值、純內部後台不必開。</p>
<p><strong>CAPTCHA / Challenge</strong>：AWS WAF 內建 CAPTCHA puzzle 與 silent JS Challenge、可在 rule action 直接呼叫。Challenge 在客戶端執行 proof-of-work、合法瀏覽器無感、headless 工具卡住；CAPTCHA 是視覺題、人類解、bot 不會。Production 標準做法：Bot Control 給 label → Custom Rule 看 label → likely bot 走 Challenge、known bad 走 Block、人類流量直接 Allow。</p>
<p><strong>ACM Private CA + WAF 對 mTLS</strong>：AWS WAF 本身不做 mTLS 驗證、mTLS 是 ALB / API Gateway / CloudFront 自己的功能（搭配 <a href="/blog/backend/07-security-data-protection/vendors/aws-acm/" data-link-title="AWS ACM" data-link-desc="AWS-managed certificate provisioning、DNS validation &#43; auto-renewal、整合 ELB / CloudFront / API Gateway、Private CA 後端">AWS ACM</a> Private CA 簽發 client cert）。WAF 在 mTLS 完成後才看 L7 流量、可以用 <em>HTTP header match</em>（mTLS 後 ALB 注入 client cert 資訊到 header）做進一步 rule。Internal API 用 mTLS + WAF 是常見組合。</p>
<p><strong>Lambda@Edge 補 inline business logic</strong>：複雜判斷（user tier × geo × business hour × A/B test）WAF rule statement 表達不出來、用 Lambda@Edge 在 <em>viewer-request</em> phase 解析 JWT、查 internal risk API、回 response header 給 WAF 後續判斷。代價：Lambda@Edge 部署只能在 us-east-1、code 更新傳播到全球 edge 要幾分鐘、debug 是分散式 CloudWatch Logs。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Web ACL 掛不上 CloudFront</strong>：scope 配成 Regional、CloudFront 拒絕 attach — Web ACL 必須在 us-east-1 + CloudFront scope 才能掛 CloudFront；ALB / API Gateway 反過來只能掛 Regional scope</li>
<li><strong>Rate-based Rule 全擋 / 全放</strong>：CloudFront 後 origin 看到全部都是 CloudFront IP、aggregate key 沒換 Forwarded-IP — 改用 <em>Forwarded-IP</em>（X-Forwarded-For）作 aggregate key，並設 Fallback behavior</li>
<li><strong>Managed Rule Group 誤殺合法請求</strong>：CRS High sensitivity 開後 file upload / rich text editor 端點被 Block — 找 sampled request 看 rule_id、用 <em>Scope-down statement</em> 限定該 rule 在某 path 不執行、或開該 rule 為 Count、不要關整個 group</li>
<li><strong>Marketplace Rule 攔不明流量</strong>：Marketplace rule logic 不公開、sampled request 看到 rule label 但不知為何 — 切該 rule 到 Count mode 觀察、若無 attack 跡象換 AWS Managed 同類 rule</li>
<li><strong>WCU 超限</strong>：Web ACL 上限 5,000 WCU、加 Marketplace + 多個 AWS Managed 就會爆 — 看 <em>Capacity Used</em>、移除重疊 rule、把 Custom Rule 表達式簡化（少用 <em>transformation chain</em>）</li>
<li><strong>Logging 沒設 / 設錯</strong>：事件發生後沒有完整 log 可查、只有 sampled request（保留 3 小時、機率抽樣） — 必開 <em>Logging configuration</em> 到 Kinesis Firehose / S3 / CloudWatch Logs、確認 IAM role 有 firehose:PutRecord 權限</li>
<li><strong>IAM 權限過寬</strong>：CI account 拿到 <code>wafv2:*</code> 整 zone 都能改 — 收斂到 <code>wafv2:Get*</code> / <code>List*</code> 唯讀、敏感寫入限 admin role + MFA + Change Management</li>
<li><strong>跨 region 部署 drift</strong>：手動在 console 改 us-east-1 ACL、其他 region 沒同步 — 用 Terraform / CloudFormation IaC 管理、PR review、CI plan 檢查 drift</li>
<li><strong>Shield Standard 不夠擋大型 L7 DDoS</strong>：Standard 只防 L3/L4、L7 attack 靠 WAF Rate-based Rule + Bot Control — 若反覆遭遇大型 L7 DDoS、評估 Shield Advanced 的 DRT + cost protection 是否值得</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Multi-cloud / on-prem origin</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &#43; DDoS &#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF</a></td>
      </tr>
      <tr>
          <td>低 FP 容忍 / 業務有 schema</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/fastly-ngwaf/" data-link-title="Fastly Next-Gen WAF" data-link-desc="Behavioral / 語意分析 WAF（前 Signal Sciences）、低 false positive、Edge / Agent / Cloud 三種部署模型、API &#43; ATO &#43; Bot 一體">Fastly Next-Gen WAF</a></td>
      </tr>
      <tr>
          <td>L3/L4 DDoS 進階防護</td>
          <td>AWS Shield Advanced / Cloudflare Magic Transit</td>
      </tr>
      <tr>
          <td>純內部 mTLS / east-west</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/spire/" data-link-title="SPIRE" data-link-desc="SPIFFE Runtime Environment、attested workload identity、short-lived SVID &#43; Trust Bundle、跨組織 federation">SPIRE</a> + service mesh</td>
      </tr>
      <tr>
          <td>Cert lifecycle</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/aws-acm/" data-link-title="AWS ACM" data-link-desc="AWS-managed certificate provisioning、DNS validation &#43; auto-renewal、整合 ELB / CloudFront / API Gateway、Private CA 後端">AWS ACM</a> / <a href="/blog/backend/07-security-data-protection/vendors/cert-manager/" data-link-title="cert-manager" data-link-desc="K8s 原生 certificate lifecycle automation、支援 Let&#39;s Encrypt / Vault PKI / Venafi 等多 issuer、auto-renewal &#43; Challenge solver">cert-manager</a></td>
      </tr>
      <tr>
          <td>Secrets / API key</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/aws-secrets-manager/" data-link-title="AWS Secrets Manager" data-link-desc="AWS 原生 secret store &#43; 內建 RDS / Redshift rotation Lambda、Resource Policy 跨帳號共享、KMS 加密">AWS Secrets Manager</a> / <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a></td>
      </tr>
      <tr>
          <td>複雜業務邏輯 inline 處理</td>
          <td>Lambda@Edge / CloudFront Functions</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>AWS WAF Classic（v1）的遷移細節 — 本頁全以 WAFv2 為準</li>
<li>完整 WCU 計算規則與每個 statement 的 WCU cost reference</li>
<li>Marketplace 第三方 rule group 各家功能矩陣</li>
<li>AWS WAF 在 GovCloud / China region 的差異</li>
<li>Bot Control / ATP / ACFP 完整 label schema reference</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>AWS WAF 在 07 案例庫無直接 vendor-level case、但多個 case 對應 WAF 作為 <em>修補窗口期臨時控制</em> 與 <em>entry point 治理</em> 的角色：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 AWS WAF 的關係</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/log4shell-cve-2021-44228-component-chain/" data-link-title="7.R7.2.7 Log4Shell 2021：共用元件風險與修補鏈" data-link-desc="共用元件漏洞如何同步影響多服務，並迫使團隊建立依賴治理 workflow">Log4Shell CVE-2021-44228</a></td>
          <td>對照啟示 — AWS Managed Rule Group 當時推出 Log4Shell 規則作為 emergency mitigation；但 exploitation 通過 WAF 後在後端執行，不能單靠 WAF 防 supply chain</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/edge-exposure/citrix-bleed-2023-session-hijack/" data-link-title="7.R7.3.3 Citrix Bleed 2023：會話被劫持與重放風險" data-link-desc="邊界設備會話資料外洩後，如何演變成帳號與服務風險">Citrix Bleed 2023 Session Hijack</a></td>
          <td>對照啟示 — WAF 攔不住 edge appliance zero-day、需要「修補 + session 失效 + 異常清查」三同步</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/edge-exposure/fortinet-cve-2023-27997-sslvpn-overflow/" data-link-title="7.R7.3.21 Fortinet 2023：CVE-2023-27997 SSL-VPN 溢位" data-link-desc="SSL-VPN 漏洞在邊界設備上會放大大規模掃描與利用速度">Fortinet SSL-VPN CVE 2023-27997</a></td>
          <td>對照啟示 — vendor patch 前的臨時 AWS WAF Custom Rule + Shield Advanced + Origin lockdown 是修補窗口期動作</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/entrypoint-and-server-protection/" data-link-title="7.3 入口治理與伺服器防護" data-link-desc="以問題驅動方式整理對外入口、管理平面與伺服器邊界">7.3 入口治理與伺服器防護</a></td>
          <td>AWS WAF 是 entry point protection 的工具、章節原則對應 WAF rule lifecycle 治理（Count → Block、IaC、IAM 收斂）</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/entrypoint-and-server-protection/" data-link-title="7.3 入口治理與伺服器防護" data-link-desc="以問題驅動方式整理對外入口、管理平面與伺服器邊界">7.3 入口治理與伺服器防護</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &#43; DDoS &#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF</a>、<a href="/blog/backend/07-security-data-protection/vendors/fastly-ngwaf/" data-link-title="Fastly Next-Gen WAF" data-link-desc="Behavioral / 語意分析 WAF（前 Signal Sciences）、低 false positive、Edge / Agent / Cloud 三種部署模型、API &#43; ATO &#43; Bot 一體">Fastly Next-Gen WAF</a></li>
<li>下游：<a href="/blog/backend/07-security-data-protection/data-protection-and-masking-governance/" data-link-title="7.4 資料保護與遮罩治理" data-link-desc="以問題驅動方式整理資料分級、遮罩、匯出與備份治理">7.4 資料保護與遮罩治理</a>（WAF block 不夠時、資料層也要遮罩）</li>
<li>跨類：<a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM</a>（誰能改 Web ACL）、<a href="/blog/backend/07-security-data-protection/vendors/aws-acm/" data-link-title="AWS ACM" data-link-desc="AWS-managed certificate provisioning、DNS validation &#43; auto-renewal、整合 ELB / CloudFront / API Gateway、Private CA 後端">AWS ACM</a>（mTLS client cert）、<a href="/blog/backend/07-security-data-protection/vendors/aws-secrets-manager/" data-link-title="AWS Secrets Manager" data-link-desc="AWS 原生 secret store &#43; 內建 RDS / Redshift rotation Lambda、Resource Policy 跨帳號共享、KMS 加密">AWS Secrets Manager</a>（rule update 用的 API key）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（WAF block 事件如何 routing 進 IR）</li>
<li>官方：<a href="https://docs.aws.amazon.com/waf/latest/developerguide/">AWS WAF Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>Elastic Security</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/elastic-security/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/elastic-security/</guid><description>&lt;p>Elastic Security 是 Elastic Stack（Elasticsearch + Kibana + Beats / Agent）上的 SIEM + EDR + Cloud Security 套件、OSS 起源、現屬 Elastic 商業版的 Solution。它跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &amp;#43; indexer &amp;#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &amp;#43; CSPM &amp;#43; CWS &amp;#43; AAP &amp;#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Security&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/google-security-operations/" data-link-title="Google Security Operations" data-link-desc="Google 雲原生 SIEM &amp;#43; SOAR &amp;#43; Mandiant threat intel 三合一（前 Chronicle）、UDM &amp;#43; YARA-L、fixed-price by data tier、PB-scale 友善">Google Security Operations&lt;/a> 的差異在 &lt;em>計費模型 + 查詢語言模型 + ecosystem 開放度&lt;/em>、偵測能力本身相近 — Elastic 走 &lt;em>resource-based pricing&lt;/em>（按 cluster size 而非 ingestion volume）、且提供 KQL / EQL / Lucene / ES|QL 四種互補的查詢語言。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Elastic Security 的核心定位是 &lt;em>Elastic Stack 上的 security solution&lt;/em>、底層是 &lt;em>Elasticsearch&lt;/em>（資料層）+ &lt;em>Kibana&lt;/em>（查詢與 UI 層）+ &lt;em>Fleet / Elastic Agent&lt;/em>（採集層）、頂層產品分三條：&lt;em>Elastic SIEM&lt;/em>（log aggregation + detection rule + Case + Timeline）、&lt;em>Elastic Defend&lt;/em>（前 Endgame 收購而來、EDR + endpoint protection、跟 CrowdStrike / SentinelOne 同層）、&lt;em>Elastic Cloud Security&lt;/em>（CSPM + CWP、雲端資源 misconfig 與 workload 防護）。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &amp;#43; indexer &amp;#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk&lt;/a> 比、Elastic 走 &lt;em>OSS-friendly + resource-based pricing&lt;/em> — TB-scale ingestion 不直接漲費用（要 scale node 但邊際成本遠低於 Splunk per-GB 累進）、Sigma rule 社群可直接 import 5000+ 規則；但 Splunk Security Content 跟 SOAR / RBA 等 detection content + SOC tooling 成熟度仍高一個量級。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &amp;#43; CSPM &amp;#43; CWS &amp;#43; AAP &amp;#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Security&lt;/a> 比、Elastic 跨 on-prem + 多雲、可自管也可 Elastic Cloud SaaS；Datadog 是 SaaS-only、適合純 cloud-native。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/google-security-operations/" data-link-title="Google Security Operations" data-link-desc="Google 雲原生 SIEM &amp;#43; SOAR &amp;#43; Mandiant threat intel 三合一（前 Chronicle）、UDM &amp;#43; YARA-L、fixed-price by data tier、PB-scale 友善">Google Security Operations&lt;/a> 比、Elastic 多查詢語言（KQL / EQL / Lucene / ES|QL）、Google 走 YARA-L 單一統一語言、超大規模 ingestion Google 反而划算。&lt;/p></description><content:encoded><![CDATA[<p>Elastic Security 是 Elastic Stack（Elasticsearch + Kibana + Beats / Agent）上的 SIEM + EDR + Cloud Security 套件、OSS 起源、現屬 Elastic 商業版的 Solution。它跟 <a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / <a href="/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &#43; CSPM &#43; CWS &#43; AAP &#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Security</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-security-operations/" data-link-title="Google Security Operations" data-link-desc="Google 雲原生 SIEM &#43; SOAR &#43; Mandiant threat intel 三合一（前 Chronicle）、UDM &#43; YARA-L、fixed-price by data tier、PB-scale 友善">Google Security Operations</a> 的差異在 <em>計費模型 + 查詢語言模型 + ecosystem 開放度</em>、偵測能力本身相近 — Elastic 走 <em>resource-based pricing</em>（按 cluster size 而非 ingestion volume）、且提供 KQL / EQL / Lucene / ES|QL 四種互補的查詢語言。</p>
<h2 id="服務定位">服務定位</h2>
<p>Elastic Security 的核心定位是 <em>Elastic Stack 上的 security solution</em>、底層是 <em>Elasticsearch</em>（資料層）+ <em>Kibana</em>（查詢與 UI 層）+ <em>Fleet / Elastic Agent</em>（採集層）、頂層產品分三條：<em>Elastic SIEM</em>（log aggregation + detection rule + Case + Timeline）、<em>Elastic Defend</em>（前 Endgame 收購而來、EDR + endpoint protection、跟 CrowdStrike / SentinelOne 同層）、<em>Elastic Cloud Security</em>（CSPM + CWP、雲端資源 misconfig 與 workload 防護）。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> 比、Elastic 走 <em>OSS-friendly + resource-based pricing</em> — TB-scale ingestion 不直接漲費用（要 scale node 但邊際成本遠低於 Splunk per-GB 累進）、Sigma rule 社群可直接 import 5000+ 規則；但 Splunk Security Content 跟 SOAR / RBA 等 detection content + SOC tooling 成熟度仍高一個量級。跟 <a href="/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &#43; CSPM &#43; CWS &#43; AAP &#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Security</a> 比、Elastic 跨 on-prem + 多雲、可自管也可 Elastic Cloud SaaS；Datadog 是 SaaS-only、適合純 cloud-native。跟 <a href="/blog/backend/07-security-data-protection/vendors/google-security-operations/" data-link-title="Google Security Operations" data-link-desc="Google 雲原生 SIEM &#43; SOAR &#43; Mandiant threat intel 三合一（前 Chronicle）、UDM &#43; YARA-L、fixed-price by data tier、PB-scale 友善">Google Security Operations</a> 比、Elastic 多查詢語言（KQL / EQL / Lucene / ES|QL）、Google 走 YARA-L 單一統一語言、超大規模 ingestion Google 反而划算。</p>
<p>關鍵張力：<em>多查詢語言模型</em> 同時是 Elastic 的優勢跟負擔。EQL 寫 attack chain sequence 比 SPL correlation 更直接、KQL 過濾快、ES|QL 寫 aggregation 像 SQL 直覺、Lucene 處理 full-text；但 SOC team 要決定哪個 rule 用哪個語言、不能讓每個 analyst 各寫各的。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>Elastic Security 在 SOC stack 中承擔哪一段（log aggregation / SIEM / EDR / CSPM）、哪些要外接（<a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a> IdP log、<a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a> secret rotation）</li>
<li>KQL / EQL / Lucene / ES|QL 四種查詢語言的職責分工（誰用在哪種 rule、誰負責教育 SOC）</li>
<li>Resource-based pricing 的治理（cluster sizing、hot-warm-cold tier、Searchable Snapshots、Elastic Cloud Serverless）</li>
<li>何時用 Elastic、何時走 Splunk / Datadog / Google Security Ops 的取捨</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Elastic Security deployment 是否健康、最少看四件事：</p>
<ul>
<li><strong>誰能改 detection rule</strong>：Elastic Security app 的 rule editor 權限、<code>detection-rules</code> repo（Elastic 官方 OSS rule 庫）有沒有 fork 進組織版控、rule change 是否走 PR review + staging space 驗證</li>
<li><strong>採集治理</strong>：Fleet 統一管 Elastic Agent policy / 還是散落 Beats（filebeat / metricbeat / auditbeat / winlogbeat）各自設定、log source 是否分 hot / warm / cold tier、Searchable Snapshots 是否開</li>
<li><strong>Detection content coverage</strong>：Elastic Prebuilt rules + Sigma 社群規則 import 多少 enabled、是否跟 MITRE ATT&amp;CK 對照、EQL sequence 規則覆蓋多少 attack chain pattern</li>
<li><strong>Alert quality / SOC handoff</strong>：alert volume per day、Case 跟 Timeline 是否進入日常 SOC workflow、ML anomaly job 是否在線 + threshold 是否 tuned、跟 <a href="/blog/backend/08-incident-response/" data-link-title="模組八：事故處理與復盤" data-link-desc="用 IR 領域詞彙建問題節點、以服務級案例庫累積事故脈絡，先建概念與案例庫再進實作交接">8 incident response</a> 的 routing 是否定義</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">Detection Coverage and Signal Governance</a> 邊界的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>Ingestion architecture</strong>：log 進 Elastic 三種主路徑 — <em>Elastic Agent + Fleet</em>（現代部署的預設、單一 agent 收 system / endpoint / cloud / app log、中央 Fleet server 統一管 policy）、<em>Beats</em>（filebeat / metricbeat / auditbeat / winlogbeat 等專用 agent、Fleet 推出前的傳統做法、現在持續支援但建議遷移到 Elastic Agent）、<em>Logstash</em>（pipeline-style ETL、用在 enrich / filter / route 複雜場景）。production 通常 Elastic Agent + Fleet 為主、Logstash 補 ETL 缺口。</p>
<p><strong>KQL / EQL / Lucene / ES|QL 的職責分工</strong>：四種查詢語言各有 first-class 場景。<em>KQL</em>（Kibana Query Language）是 Kibana 預設過濾語法、<code>user.name : &quot;alice&quot; and event.action : &quot;logon-failed&quot;</code>、簡單直觀、適合 dashboard / Discover 過濾。<em>EQL</em>（Event Query Language）做 sequence pattern matching、<code>sequence by user.name [authentication where event.outcome==&quot;failure&quot;] [authentication where event.outcome==&quot;success&quot; and source.geo.country != &quot;TW&quot;]</code>、表達 attack chain 比 SPL correlation 更直接。<em>Lucene</em> 是底層 full-text query、特殊需要時直接寫。<em>ES|QL</em>（Elasticsearch Query Language、2024+）是新版 SQL-like、<code>FROM logs-* | WHERE event.category == &quot;authentication&quot; | STATS count = COUNT(*) BY user.name</code>、寫 aggregation 直覺；屬新語言、production 採用 cadence 還在跟進中。</p>
<p><strong>Detection rule 種類</strong>：Elastic Security 的 rule type 是六種 first-class 概念、不是只有「query rule」一種 — <em>Query rule</em>（KQL / Lucene 觸發）、<em>EQL rule</em>（sequence pattern）、<em>Threshold rule</em>（聚合超過閾值、例如同一 IP 5min 內 login fail &gt; 100）、<em>ML rule</em>（綁 Elastic ML anomaly job、anomaly score 超過閾值觸發）、<em>New term rule</em>（首次出現的 entity、例如某 user 第一次從某國登入）、<em>Indicator match rule</em>（事件 enrich 比對 threat intel feed、IoC hit 觸發）。production rule 經常組合多種 — query rule 做粗篩、EQL rule 抓 sequence、threshold + ML 補 baseline anomaly。</p>
<p><strong>Sigma rule import</strong>：Sigma 是 OSS 通用 detection rule 格式（YAML、跨 SIEM 可移植）、社群維護 5000+ 規則。Elastic 支援直接 import Sigma rule 轉成 Elastic detection rule、是 Elastic 拉開跟商業 SIEM 距離的 OSS 槓桿。實務做法：先 import Sigma baseline + 全部走 staging space 跑 false positive 觀察、再 enable 到 production；不要直接全 enable、Sigma rule 跨 SIEM 通用所以 environment-specific tuning 必須自己做。</p>
<p><strong>Case + Timeline</strong>：Case 是 incident 容器、聚合 alert + comment + assignment + status；Timeline 是 SOC analyst 的 investigation workspace、可以 pin event / annotate / link related alert、產出 investigation narrative。兩者組合是 Elastic 的 SOC workflow first-class、不是外掛 — 對應 Splunk ES 的 Notable Event + Incident Review、但 Elastic 走 OSS 化、Case 可 export markdown 進 ticketing。</p>
<p><strong>Elastic Defend（EDR）</strong>：前 Endgame 收購整合、提供 endpoint detection + prevention（malware block / ransomware protection / behavior detection）、跟 CrowdStrike Falcon / SentinelOne 同層。Elastic Defend 跑在 Elastic Agent 內、policy 從 Fleet 推。實務上多數 SIEM 客戶不會用內建 EDR、而是外接專業 EDR feed 進 Elastic SIEM；但 OSS-friendly + 預算敏感的中型客戶可以直接整合到一個 stack。</p>
<p><strong>Cross-cluster search</strong>：跨多個 Elastic cluster 統一查詢（<code>remote_cluster:index-name</code>）、適合 multi-region / multi-tenant SOC、不需要把所有 log 搬到單一 cluster。對應 Splunk Cloud federated search。實務場景：歐洲 GDPR 資料留在 EU cluster、美國 cluster query 過去做 incident investigation 而不複製資料。</p>
<p><strong>ML jobs（anomaly detection）</strong>：Elastic ML 內建 unsupervised anomaly detection、pre-built ML job library 覆蓋 SOC 常見場景（user behavior baseline、host login pattern、port scan detection、rare process）。ML rule 綁 ML job、anomaly score 超過閾值觸發 detection rule。對應 Splunk UBA、但 Elastic ML 是 stack 內建、不是 add-on app。</p>
<p><strong>Resource-based pricing 治理</strong>：Elastic Cloud 按 <em>cluster size</em>（node count × node size）計費、不按 ingestion volume — 意義是 ingest 多 log 不直接漲費用、但要 scale node 維持查詢效能。實務治理：<em>hot tier</em>（最近 7-30 天、SSD 高效能 node）、<em>warm tier</em>（30-90 天、低 IO node）、<em>cold tier</em> / <em>frozen tier</em>（90 天以上、Searchable Snapshots on S3 / GCS、查詢慢但成本極低）。對應 Splunk SmartStore、但 Elastic frozen tier 把 retention 從幾個月延長到幾年、cost 不線性漲。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Elastic Security</th>
          <th>Splunk</th>
          <th>Datadog Security</th>
          <th>Google Security Operations</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>計費模型</td>
          <td>Resource-based（node / cluster size）</td>
          <td>Ingestion-based（GB/day、累進）</td>
          <td>Per-host + per-event（events/month）</td>
          <td>Fixed price by data tier（PB-scale 划算）</td>
      </tr>
      <tr>
          <td>查詢語言</td>
          <td>KQL / EQL / Lucene / ES|QL 四種互補</td>
          <td>SPL（單一強表達力）</td>
          <td>Datadog Query（沿用 observability 語法）</td>
          <td>YARA-L（統一、結構清楚）</td>
      </tr>
      <tr>
          <td>Sequence 表達</td>
          <td>EQL <code>sequence by</code> 直接表達 attack chain</td>
          <td>SPL transaction / streamstats</td>
          <td>log + metrics + trace 同 plane</td>
          <td>UDM + YARA-L 多事件 rule</td>
      </tr>
      <tr>
          <td>部署模型</td>
          <td>Self-hosted / Elastic Cloud / Serverless</td>
          <td>Self-hosted (Enterprise) / SaaS (Cloud)</td>
          <td>SaaS only</td>
          <td>SaaS only（Google Cloud）</td>
      </tr>
      <tr>
          <td>Detection content</td>
          <td>Elastic Prebuilt rules + Sigma 社群 5000+</td>
          <td>Splunk Security Content（最豐富、社群活躍）</td>
          <td>Datadog Security Rules（中等）</td>
          <td>Google YARA-L + Google threat intel</td>
      </tr>
      <tr>
          <td>EDR 整合</td>
          <td>Elastic Defend 內建（前 Endgame）</td>
          <td>外接 CrowdStrike / Defender</td>
          <td>Workload Security（容器 focus）</td>
          <td>外接（透過 forwarder）</td>
      </tr>
      <tr>
          <td>SOAR / Response</td>
          <td>Cases + Endpoint response（Elastic Defend）</td>
          <td>Splunk SOAR（前 Phantom、業界先驅）</td>
          <td>Workflow Automation（基本）</td>
          <td>SOAR 內建（前 Siemplify）</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>OSS-friendly、中大型、Elastic stack 已用</td>
          <td>Enterprise + 跨 on-prem、預算允許</td>
          <td>Cloud-native + observability 已用 Datadog</td>
          <td>超大規模 ingestion、Google 雲 + 多雲 SOC</td>
      </tr>
      <tr>
          <td>退場成本</td>
          <td>中 — Sigma / Lucene / EQL 部分可移植</td>
          <td>高 — SPL / detection content / dashboard 量多</td>
          <td>中</td>
          <td>中</td>
      </tr>
  </tbody>
</table>
<p>選 Elastic 的核心訴求：<em>OSS-friendly 文化 + resource-based pricing 友善 + Elastic Stack 已作為 observability 在用</em>、團隊有能力跨四種查詢語言（或至少把 EQL 跟 KQL 雙語分工清楚）、能接受 detection content 跟 SOAR 成熟度 trade-off。TB-scale ingestion 時 Elastic 比 Splunk 省 60-80% license cost 是最大誘因、但要算進 cluster sizing 跟 SRE 維運的隱形成本。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>EQL sequence pattern（時序攻擊鏈）</strong>：EQL 的 <code>sequence by</code> 是 Elastic 表達 attack chain 的 first-class 武器、比 SPL correlation 直接。例如 MFA fatigue 寫成 <code>sequence by user.name with maxspan=5m [authentication where event.outcome==&quot;failure&quot;] [authentication where event.outcome==&quot;failure&quot;] [authentication where event.outcome==&quot;success&quot; and source.ip != known_ip]</code>、序列邏輯直接表達。配對 <a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/uber-2022-mfa-fatigue/" data-link-title="7.R7.1.1 Uber 2022：MFA 疲勞與內部工具擴散" data-link-desc="從社交工程到內部工具存取，拆解身分流程與權限邊界的失效點">Uber 2022 MFA Fatigue</a> lesson：MFA fail 序列 + 新裝置 success 直接觸發。</p>
<p><strong>Elastic Defend endpoint response</strong>：除偵測外、Defend 支援 host isolation（隔離受感染 endpoint 但保留 SOC 連線）、process kill、file quarantine 等 response action、直接從 Kibana Security app 觸發。對應 CrowdStrike Real Time Response。production 採用前要設 approval gate、避免 SOC analyst 誤觸動 production server。</p>
<p><strong>CSPM / CWP（Elastic Cloud Security）</strong>：CSPM（Cloud Security Posture Management）對 AWS / GCP / Azure 帳號做 misconfig 掃描（S3 bucket public、IAM over-permission、security group 0.0.0.0/0）、對照 CIS Benchmark；CWP（Cloud Workload Protection）對 Kubernetes workload 跑 runtime detection。屬較新的功能、跟 Wiz / Lacework 等專業 CNAPP 比覆蓋還在追趕。</p>
<p><strong>Cross-cluster search 跨環境 federated query</strong>：multi-region SOC 的 first-class 工具 — query 寫 <code>FROM logs-auth-*, eu-cluster:logs-auth-*</code>、Elastic 自動路由跨 cluster。實務注意：跨 cluster query 延遲較高、要設 timeout；資料合規（GDPR）必須留意 query 結果是否包含跨境資料、不是搬資料但 query 結果回傳算不算傳輸要法務確認。</p>
<p><strong>Sigma 規則社群</strong>：Sigma 是 OSS detection rule 通用格式、Elastic 是 Sigma 主力使用者（內建 importer + Elastic 工程師參與 Sigma upstream）。實務做法：fork SigmaHQ repo 進組織版控、CI pipeline 自動轉 Sigma → Elastic detection rule、staging space 跑 false positive curve、promote 到 production；不要每次 manually import。</p>
<p><strong>Elastic Cloud Serverless（2024+）</strong>：新模型、按 <em>workload type</em>（search / observability / security）計費、不再按 cluster size — 減少 sizing 決策、autoscaling 由 Elastic 託管。屬新模型、production 採用 cadence 還在跟進中、適合 greenfield 部署或 PoC、existing cluster 遷移 roadmap 還在演進。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Alert volume 爆炸 / SOC 看不完</strong>：Sigma rule 全 enable 沒 tune、或 threshold rule 閾值太低 — staging space 跑 1 週統計 FP、tune threshold、加 exception list 排除已知合法 source、ML rule 補 user-specific baseline</li>
<li><strong>EQL sequence rule 跑不動 / timeout</strong>：sequence span 太長（24h）或 by field cardinality 太高、查詢成本爆炸 — 縮短 maxspan、限定 index pattern、加 pre-filter 條件</li>
<li><strong>Cluster 查詢慢 / Kibana 卡</strong>：hot tier 塞太多舊資料、沒做 hot-warm-cold tier 分層 — 開 ILM（Index Lifecycle Management）policy 自動 rollover、warm tier 用便宜 node、cold / frozen 走 Searchable Snapshots</li>
<li><strong>Fleet agent enrollment 失敗</strong>：Fleet server 跟 Elasticsearch 之間網路 / 憑證 / token 問題 — 檢查 Fleet server health、確認 enrollment token 未過期、agent log 看 specific 錯誤</li>
<li><strong>Sigma rule import 後大量 FP</strong>：Sigma rule 是 cross-SIEM 通用、沒有 environment-specific exclusion — 不要全 enable、staging tune 後再 promote、加 exception list（known scanner IP / 內部測試帳號）</li>
<li><strong>Resource-based pricing 超預算</strong>：node 過度 scale 或 hot tier 留太多 — 開 hot-warm-cold ILM、把 retention 超過 30 天的 index 推到 frozen tier on S3、Searchable Snapshots 是預設應該開</li>
<li><strong>ML job anomaly score 不準</strong>：training data 包含已 compromise 期間、baseline 被汙染 — 確認 training window 在乾淨期、定期重訓、配 detection rule 用 anomaly_score &gt; 75 而非 &gt; 50</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Enterprise + detection content 最豐富</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a></td>
      </tr>
      <tr>
          <td>Cloud-native + observability 已用 Datadog</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &#43; CSPM &#43; CWS &#43; AAP &#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Security</a></td>
      </tr>
      <tr>
          <td>超大規模 ingestion + Google 雲</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/google-security-operations/" data-link-title="Google Security Operations" data-link-desc="Google 雲原生 SIEM &#43; SOAR &#43; Mandiant threat intel 三合一（前 Chronicle）、UDM &#43; YARA-L、fixed-price by data tier、PB-scale 友善">Google Security Operations</a></td>
      </tr>
      <tr>
          <td>DLP / sensitive data discovery</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/google-dlp/" data-link-title="Google DLP" data-link-desc="GCP 原生 Sensitive Data Protection：infoType discovery &#43; transformation (mask / FPE / tokenize / k-anonymity)、整合 BigQuery / GCS / Cloud SQL">Google DLP</a> / <a href="/blog/backend/07-security-data-protection/vendors/microsoft-purview/" data-link-title="Microsoft Purview" data-link-desc="Microsoft 跨 M365 / Azure / endpoint 的 data governance &#43; information protection &#43; DLP &#43; insider risk 統合平台、label-driven">Microsoft Purview</a></td>
      </tr>
      <tr>
          <td>Endpoint detection 為主、不要全 stack</td>
          <td>CrowdStrike Falcon / Microsoft Defender for Endpoint / SentinelOne</td>
      </tr>
      <tr>
          <td>CNAPP 為主（雲端 posture + workload）</td>
          <td>Wiz / Lacework / Prisma Cloud（Elastic Cloud Security 較新）</td>
      </tr>
      <tr>
          <td>Incident routing</td>
          <td><a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>KQL / EQL / ES|QL 完整語法 reference、Lucene query DSL 進階用法</li>
<li>Elasticsearch index sharding / replica / ILM tuning 細節（屬 observability / 資料工程範圍）</li>
<li>Elastic Observability（APM / logs / metrics）— 屬 observability 不屬 security</li>
<li>Elastic Cloud Serverless 詳細 sizing 與 pricing 模型（2024+ 新模型、變動中）</li>
<li>Elastic Stack 自管的維運（cluster upgrade、Kibana plugin 開發）</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>Elastic Security 在 07 案例庫沒有直接 vendor-level 事件、但所有 detection-related case 都是 SIEM 偵測覆蓋率的對照：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 Elastic Security 的關係（對照啟示）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/uber-2022-mfa-fatigue/" data-link-title="7.R7.1.1 Uber 2022：MFA 疲勞與內部工具擴散" data-link-desc="從社交工程到內部工具存取，拆解身分流程與權限邊界的失效點">Uber 2022 MFA Fatigue</a></td>
          <td>Elastic EQL <code>sequence by user.name [auth fail count &gt; 50 in 5min] [auth success from new device]</code> 直接表達 MFA fatigue pattern、Sigma 社群有現成規則可 import 起步</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/microsoft-storm-0558-2023-signing-key-chain/" data-link-title="7.R7.1.5 Microsoft Storm-0558 2023：簽章金鑰鏈與郵件存取" data-link-desc="從簽章金鑰保護失效到雲端郵件存取，拆解身分信任鏈的關鍵控制點">Microsoft Storm-0558 Signing Key Chain</a></td>
          <td>跨租戶 token 異常驗證需 Elastic Cross-cluster search 跨 Azure AD log + GCP audit log + 自家 app log 同時 query、不需先搬資料</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/3cx-2023-desktopapp-supply-chain/" data-link-title="7.R7.2.8 3CX 2023：桌面軟體更新鏈攻擊" data-link-desc="合法更新流程被植入後，桌面端供應鏈事件如何傳到企業端點">3CX 2023 Desktop App Supply Chain</a></td>
          <td>Elastic Defend 直接看到 desktop app process spawn + 異常網路 callback、不需外接 EDR feed；EQL <code>sequence</code> 抓 process → DNS → C2 行為鏈</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/blue-team/detection-engineering-lifecycle/" data-link-title="7.B5 Detection Engineering Lifecycle" data-link-desc="把偵測規則視為可維護資產，建立從來源、測試、調校到退場的完整生命週期">Detection Engineering Lifecycle (section)</a></td>
          <td>Elastic rule 走 <code>detection-rules</code> repo（OSS、Elastic 官方維護）+ Sigma fork + staging space + promote 工程化 lifecycle、不是 Kibana UI 直改</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/blue-team/alert-fatigue-and-signal-quality/" data-link-title="7.B10 Alert Fatigue and Signal Quality" data-link-desc="建立告警疲勞治理方法，讓訊號品質、分級一致性與處置效率同步提升">Alert Fatigue and Signal Quality (section)</a></td>
          <td>Elastic 沒有 Splunk RBA 對應、用 ML anomaly rule + threshold rule severity + Case grouping 三層降噪、要設 ML job 重訓 lifecycle</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">7.13 偵測覆蓋率與訊號治理</a>、<a href="/blog/backend/07-security-data-protection/blue-team/detection-engineering-lifecycle/" data-link-title="7.B5 Detection Engineering Lifecycle" data-link-desc="把偵測規則視為可維護資產，建立從來源、測試、調校到退場的完整生命週期">Detection Engineering Lifecycle</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a>、<a href="/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &#43; CSPM &#43; CWS &#43; AAP &#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Security</a>、<a href="/blog/backend/07-security-data-protection/vendors/google-security-operations/" data-link-title="Google Security Operations" data-link-desc="Google 雲原生 SIEM &#43; SOAR &#43; Mandiant threat intel 三合一（前 Chronicle）、UDM &#43; YARA-L、fixed-price by data tier、PB-scale 友善">Google Security Operations</a></li>
<li>下游：<a href="/blog/backend/07-security-data-protection/vendors/google-dlp/" data-link-title="Google DLP" data-link-desc="GCP 原生 Sensitive Data Protection：infoType discovery &#43; transformation (mask / FPE / tokenize / k-anonymity)、整合 BigQuery / GCS / Cloud SQL">Google DLP</a> / <a href="/blog/backend/07-security-data-protection/vendors/microsoft-purview/" data-link-title="Microsoft Purview" data-link-desc="Microsoft 跨 M365 / Azure / endpoint 的 data governance &#43; information protection &#43; DLP &#43; insider risk 統合平台、label-driven">Microsoft Purview</a>（DLP signal 進 Elastic SIEM）</li>
<li>跨類：<a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a>（IdP log source）、<a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a>（secret rotation API）、<a href="/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &#43; DDoS &#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF</a>（WAF log + Sigma rule 對接）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（Case → IR routing）、<a href="/blog/backend/04-observability/" data-link-title="模組四：可觀測性平台" data-link-desc="整理 log、metric、trace、dashboard 與 alert 的後端操作實務">4 observability</a>（Elastic Stack 共用 log pipeline）</li>
<li>官方：<a href="https://www.elastic.co/guide/en/security/current/index.html">Elastic Security Documentation</a>、<a href="https://github.com/elastic/detection-rules">detection-rules repo</a></li>
</ul>
]]></content:encoded></item><item><title>Apache JMeter</title><link>https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/jmeter/</link><pubDate>Fri, 15 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/jmeter/</guid><description>&lt;p>JMeter 的核心責任是把多 protocol 測試與既有企業測試資產轉成可重跑的負載驗證。它適合 GUI 驅動、plugin 生態成熟、HTTP 之外還需要 JDBC、JMS、FTP、mail 或 legacy protocol 的團隊，重點在把測試流程保留成可審查、可交接、可在 non-GUI mode 跑的 artifact。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>JMeter 是 Apache Software Foundation 的 OSS load testing tool、Java 寫、用 XML 描述 thread group / sampler / listener 組成的 test plan（&lt;code>.jmx&lt;/code> 檔）、支援 GUI 與 CLI（non-GUI / headless）雙模式。它是業界最老牌、protocol 覆蓋最廣的壓測工具 — sampler 直接覆蓋 HTTP、JDBC、JMS、SOAP、FTP、SMTP、IMAP、TCP、JUnit、OS process 等。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/k6/" data-link-title="k6" data-link-desc="用 scriptable scenario 建立 API、protocol 與 CI 友善壓測的效能工程工具">k6&lt;/a> 比、JMeter 走 &lt;em>GUI-driven + protocol 廣&lt;/em>、k6 走 &lt;em>code-first（JavaScript）+ HTTP 為主&lt;/em>；JMeter 適合 QA 團隊維護、k6 適合 dev / SRE 寫進 CI。跟 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/locust/" data-link-title="Locust" data-link-desc="用 Python user behavior 與 distributed worker 表達高自訂負載模型的效能工程工具">Locust&lt;/a> 比、JMeter 用 XML + plugin、Locust 用純 Python class、custom client 彈性 Locust 強但 protocol 內建支援 JMeter 廣。跟 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/gatling/" data-link-title="Gatling" data-link-desc="用 JVM DSL、simulation 與 injection profile 表達複雜 scenario 的效能工程工具">Gatling&lt;/a> 比、JMeter 偏 GUI / 多 protocol、Gatling 偏 JVM DSL（Scala / Java / Kotlin）+ async runtime、單機 throughput Gatling 較高但 protocol 廣度與既有資產承接 JMeter 勝。&lt;/p>
&lt;p>關鍵張力：&lt;em>GUI / protocol 廣度&lt;/em> ↔ &lt;em>單機 throughput / CI 友善度&lt;/em> 是選 JMeter 的根本取捨。GUI 適合 QA 團隊與跨角色協作、&lt;code>.jmx&lt;/code> 又有 plugin 生態與十多年累積；代價是 XML diff 難 review、GUI listener 吃記憶體、CI 整合相比 k6 / Gatling 多一層 packaging。&lt;/p>
&lt;p>JMeter 適合測試資產已經存在的組織。當團隊有大量 &lt;code>.jmx&lt;/code> 測試計畫、QA 團隊用 GUI 維護 scenario、或壓測需要跨 HTTP、JDBC、JMS 與其他 plugin protocol，JMeter 的價值在於承接組織流程，而不只是產生 HTTP 負載。這個定位讓 JMeter 接到 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/load-test-tooling/" data-link-title="9.3 壓測工具選型" data-link-desc="k6 / JMeter / Gatling / Locust / Vegeta / Production Replay 的工程選型">9.3 壓測工具選型&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/production-validation/" data-link-title="9.10 Production-Side 驗證" data-link-desc="shadow traffic、dark launch、canary、production-like load test">9.10 Production-Side 驗證&lt;/a>。它能支援 production-like test 的多系統 dependency，但 evidence package 要補上測試計畫版本、plugin 版本、runner 配置與結果保存方式。&lt;/p></description><content:encoded><![CDATA[<p>JMeter 的核心責任是把多 protocol 測試與既有企業測試資產轉成可重跑的負載驗證。它適合 GUI 驅動、plugin 生態成熟、HTTP 之外還需要 JDBC、JMS、FTP、mail 或 legacy protocol 的團隊，重點在把測試流程保留成可審查、可交接、可在 non-GUI mode 跑的 artifact。</p>
<h2 id="服務定位">服務定位</h2>
<p>JMeter 是 Apache Software Foundation 的 OSS load testing tool、Java 寫、用 XML 描述 thread group / sampler / listener 組成的 test plan（<code>.jmx</code> 檔）、支援 GUI 與 CLI（non-GUI / headless）雙模式。它是業界最老牌、protocol 覆蓋最廣的壓測工具 — sampler 直接覆蓋 HTTP、JDBC、JMS、SOAP、FTP、SMTP、IMAP、TCP、JUnit、OS process 等。</p>
<p>跟 <a href="/blog/backend/09-performance-capacity/vendors/k6/" data-link-title="k6" data-link-desc="用 scriptable scenario 建立 API、protocol 與 CI 友善壓測的效能工程工具">k6</a> 比、JMeter 走 <em>GUI-driven + protocol 廣</em>、k6 走 <em>code-first（JavaScript）+ HTTP 為主</em>；JMeter 適合 QA 團隊維護、k6 適合 dev / SRE 寫進 CI。跟 <a href="/blog/backend/09-performance-capacity/vendors/locust/" data-link-title="Locust" data-link-desc="用 Python user behavior 與 distributed worker 表達高自訂負載模型的效能工程工具">Locust</a> 比、JMeter 用 XML + plugin、Locust 用純 Python class、custom client 彈性 Locust 強但 protocol 內建支援 JMeter 廣。跟 <a href="/blog/backend/09-performance-capacity/vendors/gatling/" data-link-title="Gatling" data-link-desc="用 JVM DSL、simulation 與 injection profile 表達複雜 scenario 的效能工程工具">Gatling</a> 比、JMeter 偏 GUI / 多 protocol、Gatling 偏 JVM DSL（Scala / Java / Kotlin）+ async runtime、單機 throughput Gatling 較高但 protocol 廣度與既有資產承接 JMeter 勝。</p>
<p>關鍵張力：<em>GUI / protocol 廣度</em> ↔ <em>單機 throughput / CI 友善度</em> 是選 JMeter 的根本取捨。GUI 適合 QA 團隊與跨角色協作、<code>.jmx</code> 又有 plugin 生態與十多年累積；代價是 XML diff 難 review、GUI listener 吃記憶體、CI 整合相比 k6 / Gatling 多一層 packaging。</p>
<p>JMeter 適合測試資產已經存在的組織。當團隊有大量 <code>.jmx</code> 測試計畫、QA 團隊用 GUI 維護 scenario、或壓測需要跨 HTTP、JDBC、JMS 與其他 plugin protocol，JMeter 的價值在於承接組織流程，而不只是產生 HTTP 負載。這個定位讓 JMeter 接到 <a href="/blog/backend/09-performance-capacity/load-test-tooling/" data-link-title="9.3 壓測工具選型" data-link-desc="k6 / JMeter / Gatling / Locust / Vegeta / Production Replay 的工程選型">9.3 壓測工具選型</a> 與 <a href="/blog/backend/09-performance-capacity/production-validation/" data-link-title="9.10 Production-Side 驗證" data-link-desc="shadow traffic、dark launch、canary、production-like load test">9.10 Production-Side 驗證</a>。它能支援 production-like test 的多系統 dependency，但 evidence package 要補上測試計畫版本、plugin 版本、runner 配置與結果保存方式。</p>
<h2 id="適用場景">適用場景</h2>
<p>多 protocol 壓測是 JMeter 的主要入口。企業服務常同時需要測 HTTP API、JDBC query、JMS queue、FTP 或 mail flow，JMeter 的 sampler 與 plugin 生態能讓同一份測試計畫覆蓋多種 dependency。</p>
<p>GUI 協作適合非純工程團隊。QA、測試中心或受監管環境常需要可視化測試設計、審核與交接，JMeter 的 GUI 能降低跨角色溝通成本。</p>
<p>Legacy 測試資產適合保留 JMeter。既有 <code>.jmx</code> 檔案、listener、plugin 與報表流程如果已經運作多年，重寫到 k6、Gatling 或 Locust 的機會成本要用維護收益抵銷。</p>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 JMeter deployment 是否健康、最少看四件事：</p>
<ul>
<li><strong>Thread group 設計</strong>：thread count / ramp-up / loop count / duration 是否反映真實流量模型、有沒有用 <em>Stepping Thread Group</em>（plugin）或 <em>Concurrency Thread Group</em> 控制 arrival rate、不是把 thread 當「user」直接綁</li>
<li><strong>Listener 配置</strong>：GUI listener（View Results Tree / Aggregate Report / Graph）只在 design / debug 階段開、正式跑必須改 <em>Simple Data Writer</em> 輸出 JTL、結果分析交給離線 HTML report 或外部 Grafana</li>
<li><strong>Distributed mode 設定</strong>：單機 thread 上限約 3000-5000（受 JVM heap 與 thread context switch 限制）、超過要走 <em>master + slave</em>（remote engine）；slave 機器 plugin / JMeter version / JVM 參數要跟 master 一致、否則結果不可信</li>
<li><strong>GUI vs CLI 模式區分</strong>：GUI 是 design / debug only、production load 一律走 <code>jmeter -n -t plan.jmx -l result.jtl</code>；GUI 跑大規模測試會把 listener 拉爆記憶體、結果反而失真</li>
</ul>
<p>四件事任一缺、就是 <a href="/blog/backend/09-performance-capacity/load-test-tooling/" data-link-title="9.3 壓測工具選型" data-link-desc="k6 / JMeter / Gatling / Locust / Vegeta / Production Replay 的工程選型">9.3 壓測工具選型</a> 邊界的待補項目。</p>
<h2 id="選型判準">選型判準</h2>
<table>
  <thead>
      <tr>
          <th>判準</th>
          <th>JMeter 的價值</th>
          <th>需要補的能力</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>多 protocol</td>
          <td>sampler 與 plugin 覆蓋廣</td>
          <td>plugin 版本治理與測試環境一致性</td>
      </tr>
      <tr>
          <td>GUI 協作</td>
          <td>非工程角色可讀可改</td>
          <td>code review、diff 與版本控制紀律</td>
      </tr>
      <tr>
          <td>既有資產</td>
          <td><code>.jmx</code>、listener、報表可延續</td>
          <td>scenario cleanup 與 artifact 標準化</td>
      </tr>
      <tr>
          <td>分散式執行</td>
          <td>remote engine 可擴負載</td>
          <td>runner sizing、網路瓶頸與結果合併</td>
      </tr>
  </tbody>
</table>
<p>多 protocol 價值來自 dependency coverage。當 workload model 包含 database、queue、file transfer 或 legacy endpoint，JMeter 可以把不同 dependency 的壓力放在同一個測試計畫中觀察。</p>
<p>GUI 協作價值來自跨角色可見性。這個優點會帶來版本控制成本，因為 XML diff 不容易 review；團隊要補上 naming、folder structure、parameterization 與 review checklist。</p>
<h2 id="跟其他工具的取捨">跟其他工具的取捨</h2>
<p>JMeter 和 k6 的主要差異是 workflow。JMeter 偏 GUI、plugin 與既有企業流程；k6 偏 code-first、CLI、threshold 與 CI artifact。</p>
<p>JMeter 和 Gatling 的主要差異是 scenario 表達。JMeter 用 test plan、thread group、sampler 與 listener 組裝；Gatling 用 JVM DSL 描述 simulation，較適合工程團隊維護複雜 flow。</p>
<p>JMeter 和 Locust 的主要差異是自訂能力。JMeter 依賴 plugin 與 sampler，Locust 可以直接用 Python library 實作 custom client；如果 protocol 特別特殊，Python 團隊可能更適合 Locust。</p>
<p>JMeter 和 Vegeta 的主要差異是複雜度。Vegeta 適合快速 HTTP saturation probe；JMeter 適合多步驟、多 dependency 與可交接測試計畫。</p>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>JMeter</th>
          <th>k6</th>
          <th>Locust</th>
          <th>Gatling</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>描述語言</td>
          <td>XML（<code>.jmx</code>）+ GUI</td>
          <td>JavaScript</td>
          <td>Python（class-based）</td>
          <td>Scala / Java / Kotlin DSL</td>
      </tr>
      <tr>
          <td>Protocol 覆蓋</td>
          <td>HTTP/JDBC/JMS/SOAP/FTP/SMTP/TCP</td>
          <td>HTTP/WebSocket/gRPC</td>
          <td>HTTP + 任何 Python lib custom</td>
          <td>HTTP/JMS/MQTT</td>
      </tr>
      <tr>
          <td>單機 throughput</td>
          <td>中（thread-per-user）</td>
          <td>高（Go goroutine）</td>
          <td>中（gevent / async）</td>
          <td>高（Akka async）</td>
      </tr>
      <tr>
          <td>Runtime model</td>
          <td>JVM thread</td>
          <td>Go runtime</td>
          <td>Python gevent</td>
          <td>JVM async actor</td>
      </tr>
      <tr>
          <td>CI 友善度</td>
          <td>需 packaging <code>.jmx</code> + plugin</td>
          <td>強 — 單一 JS file + CLI</td>
          <td>強 — pip + Python file</td>
          <td>強 — sbt / Maven + Scala file</td>
      </tr>
      <tr>
          <td>GUI</td>
          <td>完整 GUI（design / debug）</td>
          <td>無（CLI only）</td>
          <td>Web UI（runtime monitoring）</td>
          <td>無（HTML report only）</td>
      </tr>
      <tr>
          <td>Distributed</td>
          <td>Master + Slave（remote engine）</td>
          <td>k6 Cloud / Operator</td>
          <td>Master + Worker</td>
          <td>Gatling Enterprise / FrontLine</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>Enterprise QA + 多 protocol</td>
          <td>Dev / SRE + HTTP-heavy + CI</td>
          <td>Python 團隊 + custom protocol</td>
          <td>JVM 團隊 + 複雜 scenario</td>
      </tr>
  </tbody>
</table>
<h2 id="操作成本">操作成本</h2>
<p>JMeter 的主要成本是測試計畫治理。<code>.jmx</code> 檔案可以累積大量 listener、debug sampler、hard-coded variable 與過期 assertion，長期不整理會讓壓測結果失去可追溯性。</p>
<p>Runner 成本來自 JVM 與 listener。GUI listener 適合開發階段觀察，不適合大規模壓測；正式測試要使用 non-GUI mode，把結果輸出成 JTL、HTML report 或外部 metrics。</p>
<p>Plugin 成本來自版本漂移。不同 runner、不同工程師機器或 CI image 的 plugin 版本如果不一致，同一份測試計畫可能產生不同結果，因此要把 plugin 清單、JMeter 版本與 container image 固定下來。</p>
<h2 id="evidence-package">Evidence Package</h2>
<p>JMeter 結果應回寫到 evidence package。最小欄位包括 test plan version、JMeter version、plugin list、runner topology、thread group 設定、ramp-up、duration、p95 / p99、error rate、throughput、target saturation metric 與 known gap。</p>
<table>
  <thead>
      <tr>
          <th>欄位</th>
          <th>JMeter 證據來源</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Source</td>
          <td><code>.jmx</code>、JTL、HTML report、dashboard link</td>
      </tr>
      <tr>
          <td>Time range</td>
          <td>test start / end</td>
      </tr>
      <tr>
          <td>Query link</td>
          <td>APM / Prometheus / DB / queue 查詢連結</td>
      </tr>
      <tr>
          <td>Data quality</td>
          <td>test plan version、plugin version</td>
      </tr>
      <tr>
          <td>Confidence</td>
          <td>runner topology、production similarity</td>
      </tr>
      <tr>
          <td>Known gap</td>
          <td>未覆蓋 protocol、資料偏差、listener overhead</td>
      </tr>
  </tbody>
</table>
<p>Evidence package 的核心用途是讓結果可審查。JMeter 測試計畫常由多人維護，gate decision 要能追到哪一版 <code>.jmx</code>、哪一組 runner、哪一批測試資料與哪一個目標環境。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>JMeter Plugins 生態</strong>：<a href="https://jmeter-plugins.org/">jmeter-plugins.org</a> 社群維護的 plugin 集合補齊原版 JMeter 的不足 — <em>Custom Thread Groups</em>（Stepping / Ultimate / Concurrency / Arrivals）讓 thread schedule 反映真實 arrival rate、<em>PerfMon</em> 抓 remote server CPU / memory、<em>Throughput Shaping Timer</em> 直接以 RPS 為目標而非 thread count、<em>Dummy Sampler</em> 拿來 mock dependency。Plugin Manager 統一安裝、CI image 要把 plugin 清單固定（<code>PluginsManagerCMD.sh install &lt;plugins&gt;</code>）避免漂移。</p>
<p><strong>BlazeMeter Cloud / Distributed execution</strong>：自建 distributed mode（master + slave 跨多 VM）成本高 — slave 機器要同 JMeter 版本、同 plugin、同 JVM 參數、RMI port 開通、結果回傳網路足夠。<a href="https://www.blazemeter.com/">BlazeMeter</a>（Perforce / 前 CA）是 JMeter SaaS、直接吃 <code>.jmx</code> 跑 cloud-scale 壓測、附 geo-distributed runner、適合短期 spike 測試不想自建 distributed cluster 的團隊。trade-off 是 vendor lock-in 跟 per-test 計費 — 長期高頻測試自建較划算。</p>
<p><strong>Distributed mode 細節</strong>：master 機器發 control plane（thread group 配置、test plan 分發）、slave 跑 thread 並回傳 sample 結果。瓶頸常出在 <em>master 收結果</em>（RMI / 自訂 protocol），不是 slave 跑不動 — 大規模測試應該關掉 GUI listener、用 <em>Backend Listener</em> 把 metric 即時推到外部時序資料庫、master 只收彙整指標而非每個 sample。同步要點：所有 slave 用同一份 <code>.jmx</code> 與 test data CSV，CSV 不能依賴 master local path。</p>
<p><strong>Backend Listener + Grafana 整合</strong>：JMeter 原生 <em>Backend Listener</em> 支援 InfluxDB / Graphite / Elasticsearch、把 active thread / response time / hit / error 即時推出去、Grafana 配 <a href="https://grafana.com/grafana/dashboards/5496-apache-jmeter-dashboard/">official JMeter dashboard</a> 即時看 throughput / latency curve。這個組合取代 GUI listener、是 distributed mode 的標準觀測方式 — listener overhead 從 master 移到外部時序系統、master 不再被 GUI 拉爆。配合 <a href="/blog/backend/04-observability/" data-link-title="模組四：可觀測性平台" data-link-desc="整理 log、metric、trace、dashboard 與 alert 的後端操作實務">4 observability</a> 的時序資料庫已有時、JMeter metric 進同一個 Grafana、跟 application 端的 latency / error 並列、加速 <a href="/blog/backend/06-reliability/performance-regression-gate/" data-link-title="6.13 Performance Regression Gate" data-link-desc="把效能 baseline 從一次性壓測變成持續對齊的 release gate，涵蓋 baseline 設定、判讀方法、variance 控制與退化定位">6.13 Performance Regression Gate</a> 的對照判讀。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>GUI 模式吃記憶體爆 / OOM</strong>：GUI listener（View Results Tree / Graph）會把所有 sample 留在 heap、跑大規模就 OutOfMemoryError — 設計階段才開 GUI、正式跑切 <code>jmeter -n</code> non-GUI、listener 用 Simple Data Writer 寫 JTL 而非 in-memory aggregate</li>
<li><strong>Listener 拖累 throughput / 結果失真</strong>：太多 listener 同時開、每個 sample 都被多個 listener 處理、JMeter 自身成為瓶頸 — 正式測試只留 Simple Data Writer + Backend Listener、結果分析離線跑 <code>jmeter -g result.jtl -o report/</code> 產 HTML</li>
<li><strong>Thread group 計算錯 / 真實流量對不上</strong>：把 thread 當「user」直接設、忽略 think time + ramp-up、結果壓出來的是 thread 全速跑而非業務流量 — 改用 Concurrency Thread Group 或 Throughput Shaping Timer 直接以 RPS 為目標、配 Constant Timer 模擬 think time</li>
<li><strong>Distributed mode 結果跟單機對不上</strong>：slave 機器 plugin / JMeter version / JVM heap 不一致、或 CSV 路徑只存在 master — 把 slave 環境 container 化（同 Docker image）、CSV 隨 <code>.jmx</code> 一起分發、<code>--remote-start</code> 統一啟動</li>
<li><strong><code>.jmx</code> XML diff 不可 review / merge conflict 多</strong>：多人同時改測試計畫、GUI 改完 XML 結構大變 — 拆 fragment（Test Fragment + Module Controller）、scenario 分檔、parameterization 走外部 CSV / properties、PR review 看截圖 + 跑結果而非 raw XML diff</li>
<li><strong>Plugin 版本漂移 / CI 結果不可重現</strong>：dev 機器 plugin 跟 CI image 不同版 — 固定 plugin manifest、CI image 用 <code>PluginsManagerCMD.sh install-for-jmx plan.jmx</code> 從 plan 自動安裝、版本鎖到 image tag</li>
<li><strong>HTTPS / TLS 連線數爆炸</strong>：JMeter 預設每 thread 一個 TLS handshake、large thread count 把 server TLS 拖垮、結果反而測到 TLS 不是 app — 開 <em>HTTP Cache Manager</em> 跟 <em>KeepAlive</em>、必要時調 <code>httpclient4.idletimeout</code></li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>JMeter 在 09 案例庫中適合作為 enterprise load test 承接點。它可回寫到 <a href="/blog/backend/09-performance-capacity/cases/tixcraft-ticketing-flash-sale-spike/" data-link-title="9.C15 拓元 Tixcraft：售票搶購的瞬間爆量架構" data-link-desc="拓元用 DynamoDB 當寫入緩衝 &#43; 傳統伺服器當慢速消費者、承受 100K&#43; 同時選位 &#43; 30 秒從 6 台擴到 800 台">9.C15 Tixcraft 售票壓測</a> 的 pre-event validation、<a href="/blog/backend/09-performance-capacity/cases/bookmyshow-indian-ticketing-platform/" data-link-title="9.C17 BookMyShow：印度年售 2 億張票的資料架構現代化" data-link-desc="BookMyShow 從 15 年自建 analytics 遷移到 AWS modern data architecture、4 個月完成、分析成本下降 80%">9.C17 BookMyShow ticketing</a> 的售票流量模型、<a href="/blog/backend/09-performance-capacity/cases/aws-prime-day-extreme-scale-2025/" data-link-title="9.C1 AWS Prime Day 2025：可預期極端峰值的 dogfood" data-link-desc="Amazon 自家服務在 Prime Day 2025 的峰值數字 — 一年一次可預期峰值的容量設計參考">9.C1 Prime Day readiness</a> 的 staged validation、<a href="/blog/backend/09-performance-capacity/cases/hotstar-ipl-eighteen-million-concurrent/" data-link-title="9.C13 Disney&#43; Hotstar：IPL 板球決賽 1860 萬人同時直播" data-link-desc="Hotstar 在 IPL 板球決賽創下 1860 萬同時觀看的全球直播紀錄、CDN 與全球邊緣容量極限">9.C13 Hotstar IPL 1860 萬同時觀看</a> 的全球直播 pre-event rehearsal、以及 <a href="/blog/backend/09-performance-capacity/cases/standard-chartered-aurora-banking/" data-link-title="9.C14 Standard Chartered：受監管銀行的 Aurora 4000 TPS 容量提升" data-link-desc="Standard Chartered 銀行遷移到 Aurora 後吞吐量提升 10 倍至 4000 TPS、跨 7 個受監管市場">9.C14 Standard Chartered</a> 跨 7 個受監管市場的 Aurora 4000 TPS 容量驗證。</p>
<p>這些案例提供的是複雜業務流程與活動前驗證節奏。JMeter 頁引用案例時，要把 case 轉成 thread group、ramp-up、data set、dependency sampler 與 result artifact，並讓負載數字回到業務流程判讀 — 例如 Hotstar 的「集中地理區 CDN 壓力」要在 JMeter 用 per-region thread group 模擬、不是把全球流量塞進單一 runner。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/09-performance-capacity/load-test-tooling/" data-link-title="9.3 壓測工具選型" data-link-desc="k6 / JMeter / Gatling / Locust / Vegeta / Production Replay 的工程選型">9.3 壓測工具選型</a></li>
<li>上游：<a href="/blog/backend/09-performance-capacity/production-validation/" data-link-title="9.10 Production-Side 驗證" data-link-desc="shadow traffic、dark launch、canary、production-like load test">9.10 Production-Side 驗證</a></li>
<li>平行：<a href="/blog/backend/09-performance-capacity/vendors/k6/" data-link-title="k6" data-link-desc="用 scriptable scenario 建立 API、protocol 與 CI 友善壓測的效能工程工具">k6</a>、<a href="/blog/backend/09-performance-capacity/vendors/gatling/" data-link-title="Gatling" data-link-desc="用 JVM DSL、simulation 與 injection profile 表達複雜 scenario 的效能工程工具">Gatling</a>、<a href="/blog/backend/09-performance-capacity/vendors/locust/" data-link-title="Locust" data-link-desc="用 Python user behavior 與 distributed worker 表達高自訂負載模型的效能工程工具">Locust</a></li>
<li>跨模組：<a href="/blog/backend/06-reliability/performance-regression-gate/" data-link-title="6.13 Performance Regression Gate" data-link-desc="把效能 baseline 從一次性壓測變成持續對齊的 release gate，涵蓋 baseline 設定、判讀方法、variance 控制與退化定位">6.13 Performance Regression Gate</a></li>
<li>官方：<a href="https://jmeter.apache.org/usermanual/index.html">Apache JMeter documentation</a></li>
</ul>
]]></content:encoded></item><item><title>MySQL</title><link>https://tarrragon.github.io/blog/backend/01-database/vendors/mysql/</link><pubDate>Wed, 13 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/01-database/vendors/mysql/</guid><description>&lt;p>MySQL 是大型網路服務的常見選擇、簡單 query 效能跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">database sharding&lt;/a> 生態（Vitess / PlanetScale）成熟。GitHub、Shopify、Slack、Facebook（YouTube 從 MySQL 起家）等大規模服務的核心 OLTP 多採 MySQL。InnoDB engine 的 row-level lock、clustered index、buffer pool tuning 都被深度驗證。&lt;/p>
&lt;h2 id="教學路線高併發-oltp-與分片生態">教學路線：高併發 OLTP 與分片生態&lt;/h2>
&lt;p>MySQL 服務頁的教學目標是把「簡單 SQL 查詢」推進到高併發 OLTP、replication、online schema change 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">sharding governance&lt;/a>。讀者讀完後要能判斷 MySQL 何時是成熟預設、何時已經進入 Vitess / PlanetScale 或 application sharding 的討論。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>學習段&lt;/th>
 &lt;th>核心問題&lt;/th>
 &lt;th>對應段落&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>OLTP 基線&lt;/td>
 &lt;td>MySQL 適合哪種大量簡單查詢與交易路徑&lt;/td>
 &lt;td>定位、適用場景&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Replication&lt;/td>
 &lt;td>replica、failover、lag 與 read scaling 如何影響服務&lt;/td>
 &lt;td>容量特性、容量規劃要點&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Schema change&lt;/td>
 &lt;td>online schema change 與 migration 如何保護高流量服務&lt;/td>
 &lt;td>容量規劃要點、預計實作話題&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Sharding&lt;/td>
 &lt;td>Vitess、PlanetScale 與 application sharding 何時變成主線&lt;/td>
 &lt;td>跟其他 vendor 的取捨&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>替代路由&lt;/td>
 &lt;td>何時轉 PostgreSQL、Aurora、DynamoDB 或 distributed SQL&lt;/td>
 &lt;td>不適用場景、下一步路由&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="定位高併發簡單-sql--強分片生態">定位：高併發簡單 SQL + 強分片生態&lt;/h2>
&lt;p>MySQL 跟 PostgreSQL 是 SQL OLTP 兩大主流、但設計取捨明顯不同：&lt;/p>
&lt;ul>
&lt;li>MySQL 偏 &lt;em>簡單 query 效能 + 分片生態&lt;/em> — InnoDB clustered index 對 primary key range query 特別快、Vitess 提供超大規模透明 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">database sharding&lt;/a>&lt;/li>
&lt;li>PostgreSQL 偏 &lt;em>特性深度&lt;/em> — 詳見 &lt;a href="https://tarrragon.github.io/blog/backend/01-database/vendors/postgresql/" data-link-title="PostgreSQL" data-link-desc="多用途 OLTP 主流關聯式資料庫、MVCC、豐富 SQL 特性、是 Aurora / Cosmos DB / Spanner / CockroachDB / Aurora DSQL 的相容目標">PostgreSQL vendor page&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>選 MySQL 的核心訴求：需要超大規模分片（&amp;gt; 100 TB、&amp;gt; 100K WPS）、簡單 query 為主、已用 MySQL 生態工具鏈（gh-ost、pt-online-schema-change）。&lt;/p>
&lt;h2 id="容量特性">容量特性&lt;/h2>
&lt;p>&lt;strong>單一 primary 寫吞吐&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>標準 InnoDB：10K-30K WPS（依 row size、commit sync、index 數量）&lt;/li>
&lt;li>高階 instance + 優化 schema：50K-100K WPS&lt;/li>
&lt;li>超過此級別 → &lt;a href="vitess-sharding/">Vitess sharding&lt;/a> 或 PlanetScale&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Connection 上限&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>預設 max_connections = 151、實務常設 1000-5000&lt;/li>
&lt;li>每個 connection thread stack ~3 MB + session buffer 累積、active 高峰時 ~8-10 MB（thread + sort/join buffer）&lt;/li>
&lt;li>仍建議 ProxySQL / connection pool 限制 backend connection 數&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Replication&lt;/strong>：&lt;/p></description><content:encoded><![CDATA[<p>MySQL 是大型網路服務的常見選擇、簡單 query 效能跟 <a href="/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">database sharding</a> 生態（Vitess / PlanetScale）成熟。GitHub、Shopify、Slack、Facebook（YouTube 從 MySQL 起家）等大規模服務的核心 OLTP 多採 MySQL。InnoDB engine 的 row-level lock、clustered index、buffer pool tuning 都被深度驗證。</p>
<h2 id="教學路線高併發-oltp-與分片生態">教學路線：高併發 OLTP 與分片生態</h2>
<p>MySQL 服務頁的教學目標是把「簡單 SQL 查詢」推進到高併發 OLTP、replication、online schema change 與 <a href="/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">sharding governance</a>。讀者讀完後要能判斷 MySQL 何時是成熟預設、何時已經進入 Vitess / PlanetScale 或 application sharding 的討論。</p>
<table>
  <thead>
      <tr>
          <th>學習段</th>
          <th>核心問題</th>
          <th>對應段落</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>OLTP 基線</td>
          <td>MySQL 適合哪種大量簡單查詢與交易路徑</td>
          <td>定位、適用場景</td>
      </tr>
      <tr>
          <td>Replication</td>
          <td>replica、failover、lag 與 read scaling 如何影響服務</td>
          <td>容量特性、容量規劃要點</td>
      </tr>
      <tr>
          <td>Schema change</td>
          <td>online schema change 與 migration 如何保護高流量服務</td>
          <td>容量規劃要點、預計實作話題</td>
      </tr>
      <tr>
          <td>Sharding</td>
          <td>Vitess、PlanetScale 與 application sharding 何時變成主線</td>
          <td>跟其他 vendor 的取捨</td>
      </tr>
      <tr>
          <td>替代路由</td>
          <td>何時轉 PostgreSQL、Aurora、DynamoDB 或 distributed SQL</td>
          <td>不適用場景、下一步路由</td>
      </tr>
  </tbody>
</table>
<h2 id="定位高併發簡單-sql--強分片生態">定位：高併發簡單 SQL + 強分片生態</h2>
<p>MySQL 跟 PostgreSQL 是 SQL OLTP 兩大主流、但設計取捨明顯不同：</p>
<ul>
<li>MySQL 偏 <em>簡單 query 效能 + 分片生態</em> — InnoDB clustered index 對 primary key range query 特別快、Vitess 提供超大規模透明 <a href="/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">database sharding</a></li>
<li>PostgreSQL 偏 <em>特性深度</em> — 詳見 <a href="/blog/backend/01-database/vendors/postgresql/" data-link-title="PostgreSQL" data-link-desc="多用途 OLTP 主流關聯式資料庫、MVCC、豐富 SQL 特性、是 Aurora / Cosmos DB / Spanner / CockroachDB / Aurora DSQL 的相容目標">PostgreSQL vendor page</a></li>
</ul>
<p>選 MySQL 的核心訴求：需要超大規模分片（&gt; 100 TB、&gt; 100K WPS）、簡單 query 為主、已用 MySQL 生態工具鏈（gh-ost、pt-online-schema-change）。</p>
<h2 id="容量特性">容量特性</h2>
<p><strong>單一 primary 寫吞吐</strong>：</p>
<ul>
<li>標準 InnoDB：10K-30K WPS（依 row size、commit sync、index 數量）</li>
<li>高階 instance + 優化 schema：50K-100K WPS</li>
<li>超過此級別 → <a href="vitess-sharding/">Vitess sharding</a> 或 PlanetScale</li>
</ul>
<p><strong>Connection 上限</strong>：</p>
<ul>
<li>預設 max_connections = 151、實務常設 1000-5000</li>
<li>每個 connection thread stack ~3 MB + session buffer 累積、active 高峰時 ~8-10 MB（thread + sort/join buffer）</li>
<li>仍建議 ProxySQL / connection pool 限制 backend connection 數</li>
</ul>
<p><strong>Replication</strong>：</p>
<ul>
<li>async / semi-sync / GTID-based</li>
<li>跨 AZ async lag 通常 &lt; 100ms</li>
<li>跨 region 通常用 chain replication 或 binlog 同步</li>
</ul>
<p><strong>Storage 上限</strong>：</p>
<ul>
<li>單一 table 64 TB（InnoDB 設計上限）</li>
<li>實務超過 1 TB 表建議分片</li>
</ul>
<h2 id="適用場景">適用場景</h2>
<p><strong>1. 大規模 OLTP + 分片需求</strong>：</p>
<ul>
<li>流量 &gt; 50K WPS、必須進入 <a href="/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">database sharding</a> 設計</li>
<li>用 Vitess / PlanetScale 透明 sharding、應用層幾乎不必改</li>
<li>對應產業：超大網路服務（GitHub、Shopify、Slack）</li>
</ul>
<p><strong>2. 簡單 query 為主</strong>：</p>
<ul>
<li>primary key lookup、簡單 range query</li>
<li>不太用 CTE、window function、複雜 JOIN</li>
<li>InnoDB clustered index 對這類 workload 特別快</li>
</ul>
<p><strong>3. 既有 MySQL 生態工具</strong>：</p>
<ul>
<li>gh-ost / pt-online-schema-change（online schema migration）</li>
<li>Orchestrator（HA topology 管理）</li>
<li>ProxySQL（query routing + connection pool）</li>
<li>Maxwell / Debezium MySQL（<a href="/blog/backend/knowledge-cards/change-data-capture/" data-link-title="Change Data Capture" data-link-desc="說明資料變更如何被捕捉並傳送到其他系統">CDC</a>）</li>
</ul>
<p><strong>4. 強一致 transaction 但容忍部分 SQL 功能缺失</strong>：</p>
<ul>
<li>不需 partial index、不需 JSONB indexing</li>
<li>不需 PostGIS、用 spatial extension 夠</li>
</ul>
<p><strong>5. Aurora MySQL（managed 路徑）</strong>：</p>
<ul>
<li>從自管 MySQL 上 AWS、保留 wire protocol</li>
<li>詳見 <a href="/blog/backend/01-database/vendors/aurora/" data-link-title="AWS Aurora" data-link-desc="AWS managed PostgreSQL / MySQL、storage / compute 分離、&#43;75% 效能改善的 production 證據">Aurora vendor page</a></li>
</ul>
<h2 id="不適用場景">不適用場景</h2>
<p><strong>1. 需要 PostgreSQL 等級的 SQL / JSON 特性</strong>：</p>
<ul>
<li>複雜 CTE、recursive query、window function</li>
<li>JSON Schema validation、JSONB GIN indexing</li>
<li>PostGIS 等深度 extension</li>
</ul>
<p><strong>2. 全球 multi-region active-active write</strong>：</p>
<ul>
<li>MySQL 設計是 single primary、跨 region 是 async</li>
<li>替代：Aurora DSQL、Spanner、Vitess multi-cluster</li>
</ul>
<p><strong>3. 大規模 OLAP</strong>：</p>
<ul>
<li>MySQL 定位在 OLTP，analytics workload 交給 OLAP 系統</li>
<li>替代：ClickHouse、BigQuery、Snowflake</li>
</ul>
<p><strong>4. KV 簡單查詢 + sub-10ms p99</strong>：</p>
<ul>
<li>跟 PostgreSQL 一樣有 parsing / planning 開銷</li>
<li>替代：DynamoDB、Redis</li>
</ul>
<h2 id="跟其他-vendor-的取捨">跟其他 vendor 的取捨</h2>
<p><strong>vs PostgreSQL</strong>：</p>
<ul>
<li>詳見 <a href="/blog/backend/01-database/vendors/postgresql/" data-link-title="PostgreSQL" data-link-desc="多用途 OLTP 主流關聯式資料庫、MVCC、豐富 SQL 特性、是 Aurora / Cosmos DB / Spanner / CockroachDB / Aurora DSQL 的相容目標">PostgreSQL vendor page</a> 對比段</li>
<li>摘要：MySQL 適合超大規模分片、PostgreSQL 適合進階 SQL 特性</li>
</ul>
<p><strong>vs Aurora MySQL（同 wire protocol）</strong>：</p>
<ul>
<li>MySQL（自管 / RDS）：可跨雲、彈性高</li>
<li>Aurora MySQL：AWS managed、storage / compute 分離、更多 read replica</li>
<li>選自管 MySQL：跨雲需求、預算敏感</li>
<li>選 Aurora MySQL：AWS 生態深、需要 storage scaling</li>
</ul>
<p><strong>vs PlanetScale（Vitess managed）</strong>：</p>
<ul>
<li>MySQL（自管 + Vitess）：完全控制、可自管分片</li>
<li>PlanetScale：managed Vitess、branch-based schema migration</li>
<li>選 MySQL + Vitess：team 有能力管 Vitess、預算敏感</li>
<li>選 PlanetScale：想 zero ops、branch-based workflow</li>
</ul>
<p><strong>vs TiDB</strong>：</p>
<ul>
<li>MySQL：single-primary、傳統分片靠 Vitess</li>
<li>TiDB：MySQL wire protocol 相容、HTAP（OLTP + OLAP 同庫）、跨 region 強一致</li>
<li>選 MySQL：已有 MySQL 投資、不想換引擎</li>
<li>選 TiDB：需要跨 region 強一致 + OLAP 同庫</li>
</ul>
<p><strong>vs Vitess（self-managed sharding layer）</strong>：</p>
<ul>
<li>Vitess 本質是 MySQL 上層的 sharding layer</li>
<li>由 YouTube 設計、捐贈 CNCF</li>
<li>適合超大規模 MySQL 集群、需要透明 sharding</li>
</ul>
<p><strong>vs DynamoDB（document/KV 替代）</strong>：</p>
<ul>
<li>MySQL：SQL、有 transaction、ad-hoc query、connection-based</li>
<li>DynamoDB：KV、partition 透明、無 connection 限制、5 個 9 SLA</li>
<li>選 MySQL：需要 ad-hoc query、複雜 JOIN、SQL transaction</li>
<li>選 DynamoDB：access pattern 固定、AWS-only、想避免 connection limit 問題</li>
<li>詳見 <a href="/blog/backend/01-database/kv-document-capacity-planning/" data-link-title="1.10 KV / Document DB 容量規劃" data-link-desc="DynamoDB / Cosmos DB / Bigtable / MongoDB 等 KV / Document DB 的容量設計、partition key 取捨、capacity mode 選擇">1.10 KV / Document DB 容量規劃</a> 的 connection model 對比</li>
</ul>
<p><strong>vs Spanner / CockroachDB / Aurora DSQL（distributed SQL）</strong>：</p>
<ul>
<li>MySQL + Vitess：自管 sharding、operational 重、跨雲可用</li>
<li>Spanner / CockroachDB / Aurora DSQL：分散式 SQL、跨 region 強一致、transparent sharding</li>
<li>選 MySQL + Vitess：已有 MySQL 投資、有能力管 Vitess、預算敏感</li>
<li>選 distributed SQL：需要 multi-region 強一致、不想自管 sharding</li>
<li>詳見 <a href="/blog/backend/01-database/global-distributed-oltp/" data-link-title="1.11 全球分散式 OLTP" data-link-desc="Spanner / Aurora DSQL / Cosmos DB multi-region write / CockroachDB / TiDB 的全球一致性取捨">1.11 全球分散式 OLTP</a></li>
</ul>
<p><strong>vs MongoDB（document 替代）</strong>：</p>
<ul>
<li>MySQL：SQL + JSON column 補充</li>
<li>MongoDB：document 為主、aggregation pipeline 強、schema-flexible</li>
<li>選 MySQL：主要結構化、少量半結構化</li>
<li>選 MongoDB：document 占主要 schema、aggregation 工作負載</li>
</ul>
<h2 id="容量規劃要點">容量規劃要點</h2>
<p><strong>1. Sharding 是 MySQL 大規模的核心</strong>：</p>
<ul>
<li>單一 MySQL primary 寫吞吐有上限</li>
<li>Vitess / PlanetScale 用 keyspace + shard 切分</li>
<li>shard key 設計類似 DynamoDB partition key — 必須均勻</li>
<li>大規模案例：Shopify（多 shard 分散）、Slack（per-team sharding）</li>
</ul>
<p><strong>2. Online schema change 是必備</strong>：</p>
<ul>
<li>ALTER TABLE 直接跑會 lock 整個 table</li>
<li>gh-ost（GitHub）/ pt-online-schema-change（Percona）/ Vitess online DDL 用 ghost table 漸進 migrate</li>
<li>大表 schema change 可能跑 hours / days、要排程</li>
</ul>
<p><strong>3. Replication 跟 GTID</strong>：</p>
<ul>
<li>GTID-based replication 比 binlog position 容易管 topology</li>
<li>semi-sync replication 保證至少一個 standby ack 才 commit</li>
<li>async replication 高吞吐但 lag 較大</li>
</ul>
<p><strong>4. Connection management</strong>：</p>
<ul>
<li>ProxySQL 是 MySQL 生態的 connection pool 標準</li>
<li>提供 query routing（讀 → replica、寫 → primary）</li>
<li>對應 <a href="/blog/backend/09-performance-capacity/cases/ntt-docomo-lemino-japanese-streaming/" data-link-title="9.C29 NTT DOCOMO Lemino：3 個月達 500 萬 MAU 的串流後端" data-link-desc="Lemino 用 DynamoDB &#43; AWS Media Services 撐 30 channels live &#43; 5M MAU、工程工時下降 90%">9.C29 Lemino case</a> — RDB connection limit 議題對 MySQL 同樣適用</li>
</ul>
<p><strong>5. InnoDB tuning</strong>：</p>
<ul>
<li>innodb_buffer_pool_size：dedicated server 70-75%、shared server 30-50%（詳見 <a href="innodb-tuning/">InnoDB Tuning</a>）</li>
<li>innodb_flush_log_at_trx_commit：1（durable）vs 2（faster）vs 0（fastest, 不安全）</li>
<li>innodb_io_capacity：依 storage 類型調整</li>
</ul>
<h2 id="anti-recommendation-與升級路由">Anti-recommendation 與升級路由</h2>
<p>MySQL 的成熟生態容易讓讀者過早引入重工具。這一段補上 deep article audit 提到的 anti-recommendation 缺口：先說何時維持簡單 MySQL 路徑，再說何時升級到 ProxySQL、Orchestrator、gh-ost、Vitess、PlanetScale 或 distributed SQL。</p>
<table>
  <thead>
      <tr>
          <th>機制</th>
          <th>維持簡單設計的條件</th>
          <th>升級訊號</th>
          <th>主要引用路徑</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Replication</td>
          <td>單 primary + 1-2 replica，lag 可被 read routing 容忍</td>
          <td>failover 反覆手動、GTID gap、semi-sync fallback</td>
          <td><a href="replication-topology/">Replication Topology</a>、<a href="orchestrator-failover/">Orchestrator Failover</a></td>
      </tr>
      <tr>
          <td>Online schema change</td>
          <td>小表、maintenance window 足夠、MySQL 8.0 instant DDL 可 cover</td>
          <td>大表 ALTER 需 hours、metadata lock 影響 production</td>
          <td><a href="online-schema-change-tools/">Online Schema Change Tools</a>、<a href="/blog/backend/06-reliability/migration-safety/" data-link-title="6.11 Migration Safety 與 DB Rollout" data-link-desc="把 schema migration 從一次性事件變成可逆、可漸進的 rollout 流程">6.11 Migration Safety</a></td>
      </tr>
      <tr>
          <td>ProxySQL</td>
          <td>application pool + primary endpoint 已能控制連線</td>
          <td>read/write routing、lag-aware routing、connection storm</td>
          <td><a href="proxysql-config/">ProxySQL Config</a>、<a href="/blog/backend/knowledge-cards/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">Connection Pool</a></td>
      </tr>
      <tr>
          <td>Vitess / sharding</td>
          <td>單 primary 寫入與資料量仍在可維護範圍</td>
          <td>&gt; 50K WPS、&gt; 100 TB、shard key 已明確、跨 shard query 可接受</td>
          <td><a href="vitess-sharding/">Vitess Sharding</a>、<a href="/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">Database Sharding</a></td>
      </tr>
      <tr>
          <td>PlanetScale</td>
          <td>團隊已有 DBA / SRE 能力管理 Vitess 或自管 MySQL</td>
          <td>想把 Vitess ops、schema branch workflow 與 failover 交給平台</td>
          <td><a href="migrate-to-planetscale/">→ PlanetScale</a>、<a href="migrate-vitess-to-planetscale/">Vitess → PlanetScale</a></td>
      </tr>
      <tr>
          <td>Distributed SQL</td>
          <td>workload 仍是 single-region OLTP 或 Vitess 可解</td>
          <td>multi-region 強一致、cross-shard transaction 是核心需求</td>
          <td><a href="/blog/backend/01-database/global-distributed-oltp/" data-link-title="1.11 全球分散式 OLTP" data-link-desc="Spanner / Aurora DSQL / Cosmos DB multi-region write / CockroachDB / TiDB 的全球一致性取捨">1.11 全球分散式 OLTP</a></td>
      </tr>
  </tbody>
</table>
<p>Replication 的簡單路徑是 GTID + async replica + 明確 read routing。當 failover 仍靠人工判斷、replica re-pointing 反覆出錯、或 semi-sync fallback 沒有被監控時，才需要把 Orchestrator、ProxySQL 與 incident runbook 放進同一條 HA 路徑。</p>
<p>Online schema change 的簡單路徑是先判斷 MySQL 8.0 instant / inplace DDL 能否 cover。只有大表 rewrite、長時間 metadata lock、FK / trigger 複雜互動或 maintenance window 不足時，才讓 gh-ost / pt-online-schema-change 成為主線工具。</p>
<p>Sharding 的簡單路徑是延後到資料形狀穩定後再做。Vitess 能把 MySQL 推到超大規模，但它也引入 VTGate、VTTablet、VReplication、VSchema、resharding workflow 與跨 shard transaction 邊界；<a href="/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">shard key</a> 還沒穩定時，應先用 schema、index、read replica、partition 與容量治理延長單 primary 壽命。</p>
<p>Managed sharding 的簡單路徑是先確認團隊想轉移哪一層責任。PlanetScale 解的是 Vitess operation、branch-based schema workflow 與 managed failover；FK、cross-shard query、connection pool 與 cost model 仍要在 migration playbook 中驗證。</p>
<h2 id="deep-article--migration-playbook已完成">Deep article + Migration playbook（已完成）</h2>
<table>
  <thead>
      <tr>
          <th>主題</th>
          <th>文章</th>
          <th>類型</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Replication topology（async / semi-sync / GTID）配置</td>
          <td><a href="replication-topology/">replication-topology</a></td>
          <td>Deep article</td>
      </tr>
      <tr>
          <td>gh-ost / pt-online-schema-change 對比</td>
          <td><a href="online-schema-change-tools/">online-schema-change-tools</a></td>
          <td>Deep article</td>
      </tr>
      <tr>
          <td>ProxySQL 配置跟 query routing</td>
          <td><a href="proxysql-config/">proxysql-config</a></td>
          <td>Deep article</td>
      </tr>
      <tr>
          <td>Orchestrator failover 設計</td>
          <td><a href="orchestrator-failover/">orchestrator-failover</a></td>
          <td>Deep article</td>
      </tr>
      <tr>
          <td>InnoDB tuning（buffer pool / log / IO）</td>
          <td><a href="innodb-tuning/">innodb-tuning</a></td>
          <td>Deep article</td>
      </tr>
      <tr>
          <td>Binary log + Maxwell / Debezium CDC</td>
          <td><a href="binlog-cdc/">binlog-cdc</a></td>
          <td>Deep article</td>
      </tr>
      <tr>
          <td>Vitess sharding 設計</td>
          <td><a href="vitess-sharding/">vitess-sharding</a></td>
          <td>Deep article</td>
      </tr>
      <tr>
          <td>8.0 modern SQL（CTE / window / JSON_TABLE）</td>
          <td><a href="modern-sql-features/">modern-sql-features</a></td>
          <td>Deep article</td>
      </tr>
      <tr>
          <td>Group Replication / InnoDB Cluster 部署</td>
          <td><a href="group-replication/">group-replication</a></td>
          <td>Deep article</td>
      </tr>
      <tr>
          <td>Query optimization deep dive</td>
          <td><a href="query-optimization/">query-optimization</a></td>
          <td>Deep article</td>
      </tr>
      <tr>
          <td>Partitioning（range / list / hash / sub-partition）</td>
          <td><a href="partitioning/">partitioning</a></td>
          <td>Deep article</td>
      </tr>
      <tr>
          <td>PITR + Backup strategy</td>
          <td><a href="pitr-backup/">pitr-backup</a></td>
          <td>Deep article</td>
      </tr>
      <tr>
          <td>Lock contention（gap / next-key / deadlock）</td>
          <td><a href="lock-contention/">lock-contention</a></td>
          <td>Deep article</td>
      </tr>
      <tr>
          <td>Hands-on 操作路線</td>
          <td><a href="hands-on/">hands-on</a></td>
          <td>操作型章節群</td>
      </tr>
      <tr>
          <td>5.7 → 8.0 major version upgrade</td>
          <td><a href="major-version-upgrade/">major-version-upgrade</a></td>
          <td>Migration playbook（Type E）</td>
      </tr>
      <tr>
          <td>從自管 MySQL 遷到 Aurora MySQL</td>
          <td><a href="migrate-to-aurora/">migrate-to-aurora</a></td>
          <td>Migration playbook（Type C）</td>
      </tr>
      <tr>
          <td>從自管 MySQL 遷到 PlanetScale</td>
          <td><a href="migrate-to-planetscale/">migrate-to-planetscale</a></td>
          <td>Migration playbook（Type E）</td>
      </tr>
      <tr>
          <td>自管 Vitess 遷到 PlanetScale</td>
          <td><a href="migrate-vitess-to-planetscale/">migrate-vitess-to-planetscale</a></td>
          <td>Migration playbook（Type C）</td>
      </tr>
      <tr>
          <td>從 MySQL 遷到 PostgreSQL</td>
          <td><a href="migrate-to-postgresql/">migrate-to-postgresql</a></td>
          <td>Migration playbook</td>
      </tr>
  </tbody>
</table>
<h2 id="補充正文路由">補充正文路由</h2>
<p>當前 deep article、migration playbook、補充正文與 hands-on 已 cover ops / schema / failover / tuning / SQL features / sharding / backup / migration / security / audit / document / OLAP / memory / metadata lock 等維度。下列補充正文用來承接 overview 中提到的延伸議題：</p>
<ul>
<li><strong><a href="encryption-tls-key-management/">Encryption at rest + TLS in transit + key management</a></strong>：對應 PG TLS-mTLS 議題</li>
<li><strong><a href="audit-log-siem/">Audit log + SIEM 整合</a></strong>：MySQL Enterprise Audit Plugin 跟 Splunk / Elastic Security 整合</li>
<li><strong><a href="document-store-x-protocol/">MySQL Document Store（X-Protocol）</a></strong>：少用但對特定 use case 有興趣</li>
<li><strong><a href="multi-source-replication/">Multi-source replication topology</a></strong>：1 個 replica 從 N 個 primary 拉、用於 sharded environment 整合</li>
<li><strong><a href="heatwave-olap-addon/">HeatWave（MySQL OLAP add-on）</a></strong>：Oracle 推的 HTAP solution、跟 ClickHouse / Snowflake 對比</li>
<li><strong><a href="cross-buffer-memory-contention/">Cross-buffer memory contention deep dive</a></strong>：buffer pool / connection thread / temp table / sort buffer 之間的 RAM 競爭、跟 OS swap 互動</li>
<li><strong><a href="metadata-lock-deep-dive/">Metadata lock deep dive</a></strong>：DDL / long-running SELECT / FK 互動造成的 stalls</li>
</ul>
<p>上述補充篇已完成正文，並保留既有路由。Encryption / TLS / key management 接 <a href="/blog/backend/knowledge-cards/tls-mtls/" data-link-title="TLS / mTLS" data-link-desc="說明傳輸加密與雙向憑證驗證如何保護跨邊界資料流">TLS / mTLS</a> 與 <a href="/blog/backend/knowledge-cards/secret-management/" data-link-title="Secret Management" data-link-desc="說明 token、key、password 與憑證如何保存、輪替與撤銷">Secret Management</a>；audit log 接 <a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">Audit Log</a> 與 07 資安資料保護；Document Store 接 <a href="/blog/backend/01-database/vendors/mongodb/" data-link-title="MongoDB" data-link-desc="Document database 代表、Atlas managed、跨雲可用、許多大規模平台從 MongoDB 起家">MongoDB vendor</a> 與 <a href="/blog/backend/01-database/kv-document-capacity-planning/" data-link-title="1.10 KV / Document DB 容量規劃" data-link-desc="DynamoDB / Cosmos DB / Bigtable / MongoDB 等 KV / Document DB 的容量設計、partition key 取捨、capacity mode 選擇">1.10 KV / Document DB 容量規劃</a>；multi-source replication 接 <a href="replication-topology/">Replication Topology</a>；HeatWave 接 OLAP 替代路由；memory contention 接 <a href="innodb-tuning/">InnoDB Tuning</a>；metadata lock 接 <a href="lock-contention/">Lock Contention</a> 與 <a href="online-schema-change-tools/">Online Schema Change Tools</a>。</p>
<h2 id="已知-limitation多輪-audit-結論">已知 limitation（多輪 audit 結論）</h2>
<p>17 篇 batch 跑過 4-reviewer audit（寫作規範 / 跨檔一致性 / 技術準確性 / 結構性質疑）後留下的 limitation：</p>
<ul>
<li><em>Framework bias</em>：5 篇 migration playbook 全落在 Type A / C / E、沒一篇 Type B / D / F。這反映 <em>MySQL 領域 migration 的本質</em>（多數情境是 schema 差 / operational 轉手 / paradigm shift）、也可能反映 <a href="/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">6 type framework</a> 的覆蓋限制</li>
<li><em>Anti-recommendation 已補 overview 路由</em>：本頁新增「Anti-recommendation 與升級路由」作為總入口；各 deep article 之後仍可逐篇補「何時維持簡單設計」段。</li>
<li><em>Real case anchor 已下沉</em>：本頁「真實案例 anchor」把 Shopify、Slack、GitHub gh-ost、YouTube / Vitess 與既有 09 case 串回 deep article；Shopify CDC、gh-ost workflow、YouTube / Vitess 與 Netflix Aurora consolidation 已補到對應 deep article 的 production case 段。</li>
<li><em>PG 對比 narrative</em>：對比段公允度尚可、但 PG 弱點（vacuum ops 開銷 / connection-per-process model / replication slot 治理）較少在 MySQL 視角展開、單方面對比偶有偏 MySQL 不利</li>
</ul>
<h2 id="案例對照">案例對照</h2>
<p>MySQL 沒有直接的 09 case（大規模 MySQL 多在 engineering blog、不在 vendor case study）、但作為 baseline / 遷移源 在多處出現：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 MySQL 的關係</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/cases/netflix-aurora-consolidation/" data-link-title="9.C23 Netflix：把關聯式 DB 統一到 Aurora、效能 &#43;75%、成本 -28%" data-link-desc="Netflix 把多套關聯式 DB 統一到 Aurora、效能提升 75%、成本下降 28%、串流數十億小時">9.C23 Netflix Aurora consolidation</a></td>
          <td>從多套 RDBMS（含 MySQL）統一到 Aurora MySQL</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/cases/zomato-tidb-to-dynamodb-migration/" data-link-title="9.C20 Zomato：從 TiDB 遷移到 DynamoDB、吞吐 4 倍、延遲降 90%、成本減 50%" data-link-desc="Zomato 帳單系統從 TiDB 遷移到 DynamoDB、吞吐 2K→8K RPM、延遲降 90%、成本減 50%">9.C20 Zomato TiDB → DynamoDB</a></td>
          <td>TiDB（MySQL 相容）→ DynamoDB 對比</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/cases/ntt-docomo-lemino-japanese-streaming/" data-link-title="9.C29 NTT DOCOMO Lemino：3 個月達 500 萬 MAU 的串流後端" data-link-desc="Lemino 用 DynamoDB &#43; AWS Media Services 撐 30 channels live &#43; 5M MAU、工程工時下降 90%">9.C29 Lemino RDB connection limit</a></td>
          <td>MySQL connection 限制問題（同 PostgreSQL）</td>
      </tr>
  </tbody>
</table>
<h2 id="真實案例-anchor">真實案例 anchor</h2>
<p>MySQL 真實案例的責任是把大規模 OLTP 的機制壓力放回正文。案例不只證明「某公司使用 MySQL」，而是提供 schema change、CDC、sharding、connection、queue 整合或 managed migration 的壓力來源。</p>
<table>
  <thead>
      <tr>
          <th>案例 / 來源</th>
          <th>回收的工程訊號</th>
          <th>對應正文路由</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/kafka-shopify-debezium-cdc/" data-link-title="3.C13 Shopify：Debezium CDC over sharded MySQL" data-link-desc="Shopify 100&#43; MySQL shard、150 Debezium connector、Black Friday 100K records/sec P99 &lt; 10s。">Shopify Debezium CDC over sharded MySQL</a></td>
          <td>100+ shard、~150 Debezium connector、BFCM 100K records/sec、snapshot lock 與 oversized payload</td>
          <td><a href="binlog-cdc/">Binary Log + CDC</a>、<a href="/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">Database Sharding</a>、<a href="/blog/backend/03-message-queue/vendors/kafka/" data-link-title="Apache Kafka" data-link-desc="Distributed event streaming platform、log-based 模型">Kafka vendor</a></td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/slack-job-queue-kafka-redis/" data-link-title="3.C5 Slack：Job Queue 演進到 Kafka &#43; Redis" data-link-desc="背景工作通道在成長期如何從單一路徑演進成組合式架構。">Slack Job Queue 演進到 Kafka + Redis</a></td>
          <td>成長期把背景工作拆成多條傳遞路徑，揭露單一資料路徑與 queue 路徑分工</td>
          <td>MySQL 只承擔 OLTP <a href="/blog/backend/knowledge-cards/source-of-truth/" data-link-title="Source of Truth" data-link-desc="說明正式資料來源如何決定資料判斷、修復與一致性責任">source of truth</a>；queue / cache 路徑回 <a href="/blog/backend/03-message-queue/" data-link-title="模組三：訊息佇列與事件傳遞" data-link-desc="整理 durable queue、broker、retry、outbox 與 idempotency 的後端實務">03 Message Queue</a></td>
      </tr>
      <tr>
          <td>gh-ost / GitHub operation workflow</td>
          <td>大表 schema change 需要 throttle、pause / resume、cutover 控制</td>
          <td><a href="online-schema-change-tools/">Online Schema Change Tools</a></td>
      </tr>
      <tr>
          <td>YouTube / Vitess</td>
          <td>MySQL sharding layer 需要 VTGate、VTTablet、VReplication、VSchema</td>
          <td><a href="vitess-sharding/">Vitess Sharding</a>、<a href="/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">Database Sharding</a>、<a href="migrate-to-planetscale/">→ PlanetScale</a></td>
      </tr>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/cases/netflix-aurora-consolidation/" data-link-title="9.C23 Netflix：把關聯式 DB 統一到 Aurora、效能 &#43;75%、成本 -28%" data-link-desc="Netflix 把多套關聯式 DB 統一到 Aurora、效能提升 75%、成本下降 28%、串流數十億小時">9.C23 Netflix Aurora consolidation</a></td>
          <td>多套 RDBMS 整併到 managed Aurora，揭露 operation transfer driver</td>
          <td><a href="migrate-to-aurora/">→ Aurora</a>、<a href="/blog/backend/01-database/vendors/aurora/" data-link-title="AWS Aurora" data-link-desc="AWS managed PostgreSQL / MySQL、storage / compute 分離、&#43;75% 效能改善的 production 證據">Aurora vendor</a></td>
      </tr>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/cases/ntt-docomo-lemino-japanese-streaming/" data-link-title="9.C29 NTT DOCOMO Lemino：3 個月達 500 萬 MAU 的串流後端" data-link-desc="Lemino 用 DynamoDB &#43; AWS Media Services 撐 30 channels live &#43; 5M MAU、工程工時下降 90%">9.C29 Lemino RDB connection limit</a></td>
          <td>surge 場景 connection limit 讓 RDB 退到 DynamoDB 類 access pattern</td>
          <td><a href="proxysql-config/">ProxySQL Config</a>、<a href="/blog/backend/01-database/kv-document-capacity-planning/" data-link-title="1.10 KV / Document DB 容量規劃" data-link-desc="DynamoDB / Cosmos DB / Bigtable / MongoDB 等 KV / Document DB 的容量設計、partition key 取捨、capacity mode 選擇">1.10 KV / Document DB 容量規劃</a></td>
      </tr>
  </tbody>
</table>
<p>案例下沉規則是先放 overview，再進 deep article。當某個案例只支撐服務定位，留在本頁；當案例提供具體操作訊號，例如 Shopify 的 Debezium connector scaling、GitHub 的 gh-ost workflow 或 YouTube 的 Vitess topology，對應 deep article 要保留 production case 段、讓讀者能從機制直接跳到案例。</p>
<h2 id="常見陷阱">常見陷阱</h2>
<ul>
<li><strong>直接 ALTER TABLE 大表</strong>：lock 表 hours、production 停擺、必須用 online schema change</li>
<li><strong>不用 GTID</strong>：replication topology 變更困難、recover from failure 容易出錯</li>
<li><strong>buffer pool 太小</strong>：cache miss 高、IOPS 飆升</li>
<li><strong>shard key 選錯</strong>：hot shard 出現、整體吞吐達不到名義</li>
<li><strong>connection 沒 pool</strong>：跟 PostgreSQL 同樣問題、用 ProxySQL</li>
<li><strong>semi-sync 對高吞吐 workload</strong>：每次 commit 等 ack、寫吞吐降一半</li>
</ul>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>完整 T1 對照：<a href="/blog/backend/01-database/vendors/" data-link-title="資料庫 Vendor 清單" data-link-desc="規劃 SQL、managed SQL、document、KV 與 distributed SQL 的服務頁撰寫順序與教學大綱">01-database vendors index</a></li>
<li>平行：<a href="/blog/backend/01-database/vendors/postgresql/" data-link-title="PostgreSQL" data-link-desc="多用途 OLTP 主流關聯式資料庫、MVCC、豐富 SQL 特性、是 Aurora / Cosmos DB / Spanner / CockroachDB / Aurora DSQL 的相容目標">PostgreSQL vendor</a>、<a href="/blog/backend/01-database/vendors/aurora/" data-link-title="AWS Aurora" data-link-desc="AWS managed PostgreSQL / MySQL、storage / compute 分離、&#43;75% 效能改善的 production 證據">Aurora vendor</a>（managed MySQL）</li>
<li>操作：<a href="/blog/backend/01-database/vendors/mysql/hands-on/" data-link-title="MySQL Hands-on 操作路線" data-link-desc="MySQL local lab、ProxySQL routing、online schema change、replication failover、backup restore 與 Vitess sandbox 的操作型章節設計">MySQL Hands-on</a>（local lab、ProxySQL、OSC、replication failover、backup restore、Vitess sandbox）</li>
<li>上游：<a href="/blog/backend/01-database/high-concurrency-access/" data-link-title="1.1 高併發下的 SQL 讀寫邊界" data-link-desc="說明高併發服務如何共用資料庫 client、控制 transaction、管理 connection pool、避免資料庫成為瓶頸">1.1 高併發資料存取</a>、<a href="/blog/backend/01-database/transaction-boundary/" data-link-title="1.3 Transaction 與一致性邊界" data-link-desc="交易邊界、isolation level、retry 策略、distributed transaction（2PC、Saga）與跨 region 強一致取捨">1.3 Transaction Boundary</a></li>
<li>下游：<a href="/blog/backend/01-database/kv-document-capacity-planning/" data-link-title="1.10 KV / Document DB 容量規劃" data-link-desc="DynamoDB / Cosmos DB / Bigtable / MongoDB 等 KV / Document DB 的容量設計、partition key 取捨、capacity mode 選擇">1.10 KV / Document DB 容量規劃</a>（MySQL 不適用時的替代）</li>
<li>跨模組：<a href="/blog/backend/09-performance-capacity/bottleneck-localization/" data-link-title="9.5 瓶頸定位流程" data-link-desc="從 app 到 DB / cache / broker / 第三方 quota 的逐層瓶頸定位">9.5 瓶頸定位流程</a> — connection / replication / lock contention 常見 MySQL bottleneck</li>
<li>官方：<a href="https://dev.mysql.com/doc/">MySQL Documentation</a>、<a href="https://vitess.io/">Vitess</a>、<a href="https://planetscale.com/">PlanetScale</a></li>
</ul>
]]></content:encoded></item><item><title>Apache Kafka</title><link>https://tarrragon.github.io/blog/backend/03-message-queue/vendors/kafka/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/03-message-queue/vendors/kafka/</guid><description>&lt;p>Kafka 是 distributed event streaming platform、承擔三個責任：log-based 訊息儲存（partition + replication）、事件流分發（consumer group 各自進度）、跨系統事件總線（schema-aware contract）。設計取捨偏向「寫入即承諾、可長期保留、多 consumer 各自 replay」、broker 級可靠性與 consumer 端 idempotency 拆開、broker 不負責業務正確性。&lt;/p>
&lt;p>對「事件驅動架構、CDC、跨系統事件分發、長期保留 + replay」這條路徑、Kafka 是業界事實標準。本頁先給最短路徑、再展開日常 producer / consumer 操作與 topic 設計、最後進階治理（多租戶、跨區、自動修復）跟排錯。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>用 docker-compose 跑起 Kafka + KRaft、驗證 broker 健康&lt;/li>
&lt;li>用 CLI 建 topic、produce / consume 訊息、看 partition 分布&lt;/li>
&lt;li>設計 producer acks / idempotence / consumer commit 策略對齊 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/delivery-semantics/" data-link-title="Delivery Semantics" data-link-desc="說明事件投遞語意如何定義遺失、重複、順序與補償策略">delivery semantics&lt;/a>&lt;/li>
&lt;li>看懂 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/consumer-lag/" data-link-title="Consumer Lag" data-link-desc="說明 consumer lag 如何反映訊息堆積、處理能力與容量風險">consumer lag&lt;/a>、ISR shrink、rebalance 訊號、定位故障層&lt;/li>
&lt;li>評估 multi-tenant、cross-region、tiered storage、self-healing 等規模化議題&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑5-分鐘把-kafka-跑起來">最短路徑：5 分鐘把 Kafka 跑起來&lt;/h2>
&lt;p>最短路徑用 KRaft 模式（取代 ZooKeeper、單節點即可跑）、避免初學者卡在 ZK 安裝。&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 1. 啟動 Kafka（apache/kafka 內建 KRaft、單一容器即含 broker + controller）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">docker run -d --name kafka -p 9092:9092 apache/kafka:latest
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="c1"># 2. 建 topic（CLI 在容器內 /opt/kafka/bin/）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">docker &lt;span class="nb">exec&lt;/span> kafka /opt/kafka/bin/kafka-topics.sh --create --topic demo --partitions &lt;span class="m">3&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> --bootstrap-server localhost:9092
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">docker &lt;span class="nb">exec&lt;/span> kafka /opt/kafka/bin/kafka-topics.sh --describe --topic demo &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> --bootstrap-server localhost:9092
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="c1"># 3. 驗證 produce / consume&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">docker &lt;span class="nb">exec&lt;/span> kafka bash -c &lt;span class="s2">&amp;#34;echo hello | /opt/kafka/bin/kafka-console-producer.sh \
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">&lt;span class="s2"> --topic demo --bootstrap-server localhost:9092&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">docker &lt;span class="nb">exec&lt;/span> kafka /opt/kafka/bin/kafka-console-consumer.sh --topic demo &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> --from-beginning --max-messages &lt;span class="m">1&lt;/span> --bootstrap-server localhost:9092&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>最短路徑只驗證「broker 起來、能寫能讀」。實際寫程式用 producer / consumer client、見&lt;a href="#%e6%97%a5%e5%b8%b8%e6%93%8d%e4%bd%9c%e8%88%87%e6%b1%ba%e7%ad%96%e5%bd%a2%e7%8b%80">日常操作&lt;/a>。&lt;/p>
&lt;h2 id="日常操作與決策形狀">日常操作與決策形狀&lt;/h2>
&lt;h3 id="cli-與-client-api">CLI 與 client API&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>CLI 指令對照表（kafka-topics / kafka-configs / kafka-consumer-groups / kafka-acls）&lt;/li>
&lt;li>Producer client 配置：acks / batch.size / linger.ms / compression / enable.idempotence&lt;/li>
&lt;li>Consumer client 配置：auto.offset.reset / enable.auto.commit / max.poll.records / max.poll.interval.ms&lt;/li>
&lt;li>對應指令範例：&lt;code>kafka-topics.sh --describe&lt;/code>、&lt;code>kafka-consumer-groups.sh --describe --group &amp;lt;id&amp;gt;&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="topic-設計">Topic 設計&lt;/h3>
&lt;p>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/topic/" data-link-title="Topic" data-link-desc="說明 topic 如何把事件依主題分流給不同訂閱者">Topic&lt;/a> 承擔事件的邏輯邊界。子議題：&lt;/p></description><content:encoded><![CDATA[<p>Kafka 是 distributed event streaming platform、承擔三個責任：log-based 訊息儲存（partition + replication）、事件流分發（consumer group 各自進度）、跨系統事件總線（schema-aware contract）。設計取捨偏向「寫入即承諾、可長期保留、多 consumer 各自 replay」、broker 級可靠性與 consumer 端 idempotency 拆開、broker 不負責業務正確性。</p>
<p>對「事件驅動架構、CDC、跨系統事件分發、長期保留 + replay」這條路徑、Kafka 是業界事實標準。本頁先給最短路徑、再展開日常 producer / consumer 操作與 topic 設計、最後進階治理（多租戶、跨區、自動修復）跟排錯。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>用 docker-compose 跑起 Kafka + KRaft、驗證 broker 健康</li>
<li>用 CLI 建 topic、produce / consume 訊息、看 partition 分布</li>
<li>設計 producer acks / idempotence / consumer commit 策略對齊 <a href="/blog/backend/knowledge-cards/delivery-semantics/" data-link-title="Delivery Semantics" data-link-desc="說明事件投遞語意如何定義遺失、重複、順序與補償策略">delivery semantics</a></li>
<li>看懂 <a href="/blog/backend/knowledge-cards/consumer-lag/" data-link-title="Consumer Lag" data-link-desc="說明 consumer lag 如何反映訊息堆積、處理能力與容量風險">consumer lag</a>、ISR shrink、rebalance 訊號、定位故障層</li>
<li>評估 multi-tenant、cross-region、tiered storage、self-healing 等規模化議題</li>
</ol>
<h2 id="最短路徑5-分鐘把-kafka-跑起來">最短路徑：5 分鐘把 Kafka 跑起來</h2>
<p>最短路徑用 KRaft 模式（取代 ZooKeeper、單節點即可跑）、避免初學者卡在 ZK 安裝。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># 1. 啟動 Kafka（apache/kafka 內建 KRaft、單一容器即含 broker + controller）</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">docker run -d --name kafka -p 9092:9092 apache/kafka:latest
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c1"># 2. 建 topic（CLI 在容器內 /opt/kafka/bin/）</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">docker <span class="nb">exec</span> kafka /opt/kafka/bin/kafka-topics.sh --create --topic demo --partitions <span class="m">3</span> <span class="se">\
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="se"></span>  --bootstrap-server localhost:9092
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">docker <span class="nb">exec</span> kafka /opt/kafka/bin/kafka-topics.sh --describe --topic demo <span class="se">\
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="se"></span>  --bootstrap-server localhost:9092
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="c1"># 3. 驗證 produce / consume</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">docker <span class="nb">exec</span> kafka bash -c <span class="s2">&#34;echo hello | /opt/kafka/bin/kafka-console-producer.sh \
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="s2">  --topic demo --bootstrap-server localhost:9092&#34;</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">docker <span class="nb">exec</span> kafka /opt/kafka/bin/kafka-console-consumer.sh --topic demo <span class="se">\
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="se"></span>  --from-beginning --max-messages <span class="m">1</span> --bootstrap-server localhost:9092</span></span></code></pre></div><p>最短路徑只驗證「broker 起來、能寫能讀」。實際寫程式用 producer / consumer client、見<a href="#%e6%97%a5%e5%b8%b8%e6%93%8d%e4%bd%9c%e8%88%87%e6%b1%ba%e7%ad%96%e5%bd%a2%e7%8b%80">日常操作</a>。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="cli-與-client-api">CLI 與 client API</h3>
<p>子議題：</p>
<ul>
<li>CLI 指令對照表（kafka-topics / kafka-configs / kafka-consumer-groups / kafka-acls）</li>
<li>Producer client 配置：acks / batch.size / linger.ms / compression / enable.idempotence</li>
<li>Consumer client 配置：auto.offset.reset / enable.auto.commit / max.poll.records / max.poll.interval.ms</li>
<li>對應指令範例：<code>kafka-topics.sh --describe</code>、<code>kafka-consumer-groups.sh --describe --group &lt;id&gt;</code></li>
</ul>
<h3 id="topic-設計">Topic 設計</h3>
<p><a href="/blog/backend/knowledge-cards/topic/" data-link-title="Topic" data-link-desc="說明 topic 如何把事件依主題分流給不同訂閱者">Topic</a> 承擔事件的邏輯邊界。子議題：</p>
<ul>
<li><a href="/blog/backend/knowledge-cards/partition/" data-link-title="Partition" data-link-desc="說明事件流如何切分成多個可並行處理的有序片段">Partition</a> 數規劃（並行度 vs metadata 成本）</li>
<li>Replication factor 與 min.insync.replicas（資料保護等級）</li>
<li>Retention policy（time-based vs size-based、compact vs delete）</li>
<li>Key 策略（ordering 範圍、hot partition 避免）</li>
</ul>
<h3 id="producer-與-consumer-設計">Producer 與 Consumer 設計</h3>
<p>設計決定 <a href="/blog/backend/knowledge-cards/delivery-semantics/" data-link-title="Delivery Semantics" data-link-desc="說明事件投遞語意如何定義遺失、重複、順序與補償策略">delivery semantics</a> 實際達成。子議題：</p>
<ul>
<li>Producer：acks=0/1/all 對應的可靠性取捨、idempotence、transaction 邊界</li>
<li>Consumer：commit 策略（auto vs manual）、commit 時機與 at-least-once / at-most-once 對應</li>
<li><a href="/blog/backend/knowledge-cards/consumer-group/" data-link-title="Consumer Group" data-link-desc="說明一組 consumer 如何共同分攤 stream 或 topic 的處理責任">Consumer group</a>：rebalance protocol（eager vs cooperative）、static membership</li>
<li>對應指令：producer 配置範例、consumer 配置範例、<code>kafka-consumer-groups.sh --describe</code></li>
</ul>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<p>本段主題多數已展開為 deep article：<a href="consumer-rebalance-lag-diagnosis/">consumer rebalance 與 lag 診斷</a>、<a href="replication-isr-exactly-once/">replication / ISR / exactly-once</a>、<a href="retention-tiered-storage/">retention 與 tiered storage</a>、<a href="schema-registry-evolution/">Schema Registry 與 schema 演進</a>、<a href="multi-tenant-quota-acl/">multi-tenant quota 與 ACL 治理</a>。下列子議題段保留每個主題的選題判讀入口。</p>
<h3 id="multi-tenant-與配額治理">Multi-tenant 與配額治理</h3>
<p>對應案例 <a href="/blog/backend/03-message-queue/cases/uber-kafka-infrastructure-evolution/" data-link-title="3.C6 Uber：Kafka 事件平台演進" data-link-desc="事件平台從團隊自管走向多租戶共享基礎設施。">3.C6 Uber Kafka 事件平台</a>。子議題：</p>
<ul>
<li>Producer / Consumer quota（byte rate、request rate）</li>
<li>ACL 設計（principal、resource、operation）</li>
<li>Topic 命名規範與 ownership</li>
<li>對應指令：<code>kafka-configs.sh --alter --add-config 'producer_byte_rate=...'</code>、<code>kafka-acls.sh --add</code></li>
</ul>
<h3 id="cross-region-與分層叢集">Cross-region 與分層叢集</h3>
<p>對應案例 <a href="/blog/backend/03-message-queue/cases/meta-foqs-global-migration/" data-link-title="3.C1 Meta：FOQS 從區域到全域佇列遷移" data-link-desc="佇列架構如何在不中斷下升級成 disaster-ready 模式。">3.C1 Meta FOQS</a> 與 <a href="/blog/backend/03-message-queue/cases/linkedin-kafka-tiered-clusters/" data-link-title="3.C4 LinkedIn：Kafka 分層叢集治理" data-link-desc="Kafka 從單叢集走向 tiered clusters 的轉換案例。">3.C4 LinkedIn Tiered Clusters</a>。子議題：</p>
<ul>
<li>MirrorMaker 2 配置（active-active vs active-passive）</li>
<li>分層叢集策略（critical / standard / experimental）</li>
<li>跨區 consumer 路徑與 routing freshness</li>
</ul>
<h3 id="topic-生命週期治理">Topic 生命週期治理</h3>
<p>對應案例 <a href="/blog/backend/03-message-queue/cases/linkedin-topicgc-kafka-governance/" data-link-title="3.C3 LinkedIn：TopicGC 與 Kafka 治理轉換" data-link-desc="Kafka topic 從手動治理轉自動治理對叢集的影響。">3.C3 LinkedIn TopicGC</a>。子議題：</p>
<ul>
<li>Topic 活躍判準（last produce / consume timestamp）</li>
<li>自動回收條件與稽核</li>
<li>Metadata 壓力訊號（controller log、partition 數量上限）</li>
</ul>
<h3 id="replication-與-exactly-once-升級">Replication 與 exactly-once 升級</h3>
<p>對應案例 <a href="/blog/backend/03-message-queue/cases/failure-queue-semantics-mismatch-cutover/" data-link-title="3.C9 反例：Queue 語義切換誤配" data-link-desc="at-least-once / exactly-once 語義誤配導致資料重複與遺漏。">3.C9 反例：語義誤配</a>。子議題：</p>
<ul>
<li>acks=all + min.insync.replicas ≥ 2 + producer idempotence</li>
<li>Kafka transaction 與 read_committed 邊界</li>
<li>端到端 exactly-once（Kafka Streams 場景）</li>
</ul>
<h3 id="self-healing-與自動修復">Self-healing 與自動修復</h3>
<p>對應案例 <a href="/blog/backend/03-message-queue/cases/linkedin-kafka-self-healing-automation/" data-link-title="3.C7 LinkedIn：Kafka 自動修復治理" data-link-desc="Kafka 維運從人工處置轉向自動修復的案例。">3.C7 LinkedIn Self-Healing</a>。子議題：</p>
<ul>
<li>可自動修復故障類型（disk full、broker offline、under-replicated partition）</li>
<li>自動修復 vs 人工升級邊界</li>
<li>修復過程的證據鏈納入觀測</li>
</ul>
<h3 id="kraft-與-schema-registry">KRaft 與 Schema Registry</h3>
<p>子議題：</p>
<ul>
<li>KRaft mode 取代 ZooKeeper（運維簡化、metadata 治理）</li>
<li>Schema Registry（Confluent / Apicurio）與 Avro / Protobuf</li>
<li>Schema 演進策略（forward / backward / full compatibility）</li>
</ul>
<h3 id="tiered-storage">Tiered storage</h3>
<p>子議題：</p>
<ul>
<li>冷熱分層（hot tier on local disk、cold tier on S3）</li>
<li>Retention 設計與成本</li>
<li>Read 路徑差異（hot vs cold）</li>
</ul>
<h3 id="kafka-connect-與-cdc">Kafka Connect 與 CDC</h3>
<p>子議題：</p>
<ul>
<li>Source connector / Sink connector 模型</li>
<li>Debezium CDC pipeline 與 outbox 整合</li>
<li>Connect cluster 治理與 schema evolution</li>
</ul>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<h3 id="consumer-lag-暴增">Consumer lag 暴增</h3>
<p>操作原則：先看 lag 是「均勻分布」還是「集中在少數 partition」、再定位 consumer 慢 vs partition 不平衡。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">kafka-consumer-groups.sh --describe --group &lt;id&gt; --bootstrap-server localhost:9092
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># 輸出含 CURRENT-OFFSET / LOG-END-OFFSET / LAG 逐 partition 列、可看 lag 集中在哪幾個 partition</span></span></span></code></pre></div><p>判讀路徑：consumer 慢（CPU / GC / 下游 I/O）→ producer 突增 → partition 不平衡（key 分布）。</p>
<h3 id="isr-shrink-與-under-replicated-partition">ISR shrink 與 under-replicated partition</h3>
<p>操作原則：ISR 縮小代表 follower 跟不上 leader、看 broker 健康 / 網路 / disk。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">kafka-topics.sh --describe --under-replicated-partitions --bootstrap-server localhost:9092
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># 輸出為空代表所有 partition 同步正常；列出的 partition 即 ISR 落後者</span></span></span></code></pre></div><h3 id="rebalance-storm">Rebalance storm</h3>
<p>操作原則：consumer 頻繁加入 / 離開觸發 rebalance、看 session.timeout.ms 與 max.poll.interval.ms。</p>
<h3 id="offset-reset-或重複消費">Offset reset 或重複消費</h3>
<p>對應反例 <a href="/blog/backend/03-message-queue/cases/failure-queue-semantics-mismatch-cutover/" data-link-title="3.C9 反例：Queue 語義切換誤配" data-link-desc="at-least-once / exactly-once 語義誤配導致資料重複與遺漏。">3.C9</a>。判讀路徑：commit 策略錯誤、broker 端 offset 過期、auto.offset.reset = earliest。</p>
<h3 id="schema-不相容">Schema 不相容</h3>
<p>操作原則：producer 升級 schema、consumer 未升、看 compatibility level。</p>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>任務隊列（中等吞吐、複雜 routing）</td>
          <td><a href="/blog/backend/03-message-queue/vendors/rabbitmq/" data-link-title="RabbitMQ" data-link-desc="Classic message broker、AMQP routing 為主">RabbitMQ</a></td>
      </tr>
      <tr>
          <td>Managed queue（AWS 生態、簡單）</td>
          <td><a href="/blog/backend/03-message-queue/vendors/aws-sqs/" data-link-title="AWS SQS" data-link-desc="AWS managed queue、簡單可靠、無 ordering（standard）">AWS SQS</a></td>
      </tr>
      <tr>
          <td>Managed pub/sub（GCP 生態）</td>
          <td><a href="/blog/backend/03-message-queue/vendors/google-pubsub/" data-link-title="Google Cloud Pub/Sub" data-link-desc="GCP managed pub/sub、global routing、push/pull">Google Pub/Sub</a>（遷移路徑見 <a href="/blog/backend/03-message-queue/vendors/google-pubsub/migrate-from-kafka/" data-link-title="Kafka → Google Cloud Pub/Sub：從 partition 到 topic-subscription 的模型轉換" data-link-desc="從 Apache Kafka 遷移到 Google Cloud Pub/Sub，處理 partition → topic 模型轉換、ordering 語意差異、consumer group → subscription 對應、offset → ack deadline 切換的階段化流程">Kafka → Pub/Sub</a>）</td>
      </tr>
      <tr>
          <td>輕量 messaging + 微服務通訊</td>
          <td><a href="/blog/backend/03-message-queue/vendors/nats/" data-link-title="NATS" data-link-desc="Lightweight messaging、JetStream 加持久化與 streams">NATS</a></td>
      </tr>
      <tr>
          <td>Redis 生態內 stream</td>
          <td><a href="/blog/backend/03-message-queue/vendors/redis-streams/" data-link-title="Redis Streams" data-link-desc="Redis 生態內的 streams、append-only log &#43; consumer group">Redis Streams</a></td>
      </tr>
      <tr>
          <td>Managed Kafka</td>
          <td>AWS MSK / Confluent Cloud（見 <a href="/blog/backend/03-message-queue/cases/vmware-kafka-to-msk/" data-link-title="3.C2 VMware Tanzu CloudHealth：Kafka 轉 Amazon MSK" data-link-desc="自管 Kafka 遷移到託管平台時的治理重點。">3.C2</a>）</td>
      </tr>
      <tr>
          <td>Kafka 相容、單 binary</td>
          <td>Redpanda（T2 候選）</td>
      </tr>
      <tr>
          <td>多租戶 + 分層儲存原生</td>
          <td>Apache Pulsar（T2 候選）</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>各語言 client API reference（依官方文件）</li>
<li>Kafka Streams / ksqlDB（另開 stream processing 章節）</li>
<li>Confluent 商業功能（Confluent Cloud、Control Center）</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<h3 id="既有通用案例c1-c10">既有通用案例（C1-C10）</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>主討論議題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/meta-foqs-global-migration/" data-link-title="3.C1 Meta：FOQS 從區域到全域佇列遷移" data-link-desc="佇列架構如何在不中斷下升級成 disaster-ready 模式。">3.C1 Meta FOQS</a></td>
          <td>跨區 queue、tenant 遷移節奏</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/vmware-kafka-to-msk/" data-link-title="3.C2 VMware Tanzu CloudHealth：Kafka 轉 Amazon MSK" data-link-desc="自管 Kafka 遷移到託管平台時的治理重點。">3.C2 VMware → MSK</a></td>
          <td>自管轉 managed、ACL / cutover</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/linkedin-topicgc-kafka-governance/" data-link-title="3.C3 LinkedIn：TopicGC 與 Kafka 治理轉換" data-link-desc="Kafka topic 從手動治理轉自動治理對叢集的影響。">3.C3 LinkedIn TopicGC</a></td>
          <td>Topic 生命週期治理</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/linkedin-kafka-tiered-clusters/" data-link-title="3.C4 LinkedIn：Kafka 分層叢集治理" data-link-desc="Kafka 從單叢集走向 tiered clusters 的轉換案例。">3.C4 LinkedIn Tiered Clusters</a></td>
          <td>分層叢集策略</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/slack-job-queue-kafka-redis/" data-link-title="3.C5 Slack：Job Queue 演進到 Kafka &#43; Redis" data-link-desc="背景工作通道在成長期如何從單一路徑演進成組合式架構。">3.C5 Slack Kafka+Redis</a></td>
          <td>多 broker 組合拓樸</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/uber-kafka-infrastructure-evolution/" data-link-title="3.C6 Uber：Kafka 事件平台演進" data-link-desc="事件平台從團隊自管走向多租戶共享基礎設施。">3.C6 Uber Kafka</a></td>
          <td>多租戶 + 平台治理</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/linkedin-kafka-self-healing-automation/" data-link-title="3.C7 LinkedIn：Kafka 自動修復治理" data-link-desc="Kafka 維運從人工處置轉向自動修復的案例。">3.C7 LinkedIn Self-Healing</a></td>
          <td>自動修復</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/cloudflare-queues-global-delivery-model/" data-link-title="3.C8 Cloudflare：Queues 全球交付模型" data-link-desc="事件佇列服務在全球網路下的交付語義與治理案例。">3.C8 Cloudflare Queues</a></td>
          <td>全球交付（對比）</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/failure-queue-semantics-mismatch-cutover/" data-link-title="3.C9 反例：Queue 語義切換誤配" data-link-desc="at-least-once / exactly-once 語義誤配導致資料重複與遺漏。">3.C9 反例：語義誤配</a></td>
          <td>Replication + idempotence 升級</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/contrast-queue-model-by-scale/" data-link-title="3.C10 對照：規模差異下的佇列模型" data-link-desc="同一 queue 模型在不同規模下的治理與失敗邊界差異。">3.C10 規模對照</a></td>
          <td>不同規模下的佇列模型</td>
      </tr>
  </tbody>
</table>
<h3 id="kafka-專屬案例c11-c22">Kafka 專屬案例（C11-C22）</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>主討論議題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/kafka-pinterest-tiered-storage/" data-link-title="3.C11 Pinterest：Kafka tiered storage broker-decoupled" data-link-desc="Pinterest 採 broker-decoupled tiered storage、把 ~200 TB/day 熱資料卸到 S3、broker 不再是熱路徑。">3.C11 Pinterest Tiered Storage</a></td>
          <td>Broker-decoupled tiered storage / S3</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/kafka-pinterest-shallow-mirror/" data-link-title="3.C12 Pinterest：Shallow Mirror 優化 MirrorMaker" data-link-desc="Pinterest 跨 3 region MirrorMaker、原版解壓&#43;重壓造成 CPU/memory 2-10x spike、改 RecordBatch 層淺迭代。">3.C12 Pinterest Shallow Mirror</a></td>
          <td>MirrorMaker CPU/memory 優化</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/kafka-shopify-debezium-cdc/" data-link-title="3.C13 Shopify：Debezium CDC over sharded MySQL" data-link-desc="Shopify 100&#43; MySQL shard、150 Debezium connector、Black Friday 100K records/sec P99 &lt; 10s。">3.C13 Shopify Debezium CDC</a></td>
          <td>Sharded MySQL CDC pipeline</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/kafka-yelp-schematizer/" data-link-title="3.C14 Yelp：Schematizer 自建 Schema Registry" data-link-desc="Yelp data pipeline 強制所有 message 走 Avro、自建 Schematizer 做 schema evolution 與 topic 自動分配。">3.C14 Yelp Schematizer</a></td>
          <td>Schema Registry + 強制 compatibility</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/kafka-airbnb-spark-streaming-rebalance/" data-link-title="3.C15 Airbnb：Spark Streaming Kafka reader rebalance" data-link-desc="Airbnb logging pipeline 解 partition-task 1:1 造成的 data skew、catch-up 4 小時 lag 要再花 4 小時的反效率。">3.C15 Airbnb Spark Streaming</a></td>
          <td>Partition-task 解耦 / data skew</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/kafka-robinhood-faust-python-streaming/" data-link-title="3.C16 Robinhood：Faust Python stream processing" data-link-desc="Robinhood 每天 billions of events、Python 團隊不想用 JVM 生態、把 Kafka Streams 移植到 Python。">3.C16 Robinhood Faust</a></td>
          <td>Python stream processing 生態</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/kafka-walmart-mps-rebalance/" data-link-title="3.C17 Walmart：Messaging Proxy Service 解 rebalance storm" data-link-desc="Walmart 每天 trillions of message、25K&#43; consumer 在 K8s、partition-consumer 1:1 模型撞到擴張極限。">3.C17 Walmart MPS</a></td>
          <td>Partition-consumer 1:1 解耦 / K8s 擴張</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/kafka-wix-greyhound-troubleshooting/" data-link-title="3.C18 Wix：Greyhound TLLSR 解 consumer 卡住" data-link-desc="Wix 2000&#43; microservice 66B msg/day、自建 Greyhound 抽象、TLLSR 框架解 single-partition lag / poison pill / handler 卡住。">3.C18 Wix Greyhound</a></td>
          <td>TLLSR consumer troubleshooting</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/kafka-wix-multi-cluster-migration/" data-link-title="3.C19 Wix：Multi-cluster Kafka zero-downtime 遷移" data-link-desc="Wix metadata 從 5K topic 漲到 20K topic / 200K partition、controller startup 跟 broker stability 受壓垮、分多 cluster 解決。">3.C19 Wix Multi-cluster</a></td>
          <td>Metadata scaling ceiling / 分群</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/kafka-spotify-event-delivery-exodus/" data-link-title="3.C20 Spotify：Event Delivery 從 Kafka 遷出（反例）" data-link-desc="Spotify Kafka 0.7 MirrorMaker best-effort 會掉資料但回報成功、broker restart 後 producer 無法恢復、決定遷到 GCP Pub/Sub。">3.C20 Spotify 遷出 Kafka</a></td>
          <td>（反例）early Kafka 版本可靠性硬限制</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/kafka-goldman-sachs-msk-migration/" data-link-title="3.C21 Goldman Sachs：MSK 遷移 with MirrorMaker 2" data-link-desc="Goldman Sachs Global Investment Research 從 on-prem Kafka 遷到 MSK、用 MM2 同步 topic/ACL/offset、atomic cutover 7 小時完成。">3.C21 Goldman Sachs MSK</a></td>
          <td>MM2 + LB + timeout 整合 pitfall</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/kafka-trivago-keda-scale-to-zero/" data-link-title="3.C22 Trivago：KEDA scale-to-zero by Kafka lag" data-link-desc="Trivago 50&#43; Kafka sink、CPU/mem autoscaling 無效（I/O bottleneck）、KEDA 以 consumer lag 為訊號達到 scale-to-zero。">3.C22 Trivago KEDA</a></td>
          <td>Consumer lag 驅動 scale-to-zero</td>
      </tr>
  </tbody>
</table>
<p><strong>KRaft 缺直接 customer case</strong>：目前依官方 KIP-833 / Confluent 公告為準、後續若有 customer 一手案例可補。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游概念：<a href="/blog/backend/00-service-selection/async-delivery-selection/" data-link-title="0.3 非同步與事件傳遞選型" data-link-desc="區分背景工作、durable queue、stream、pub/sub 與 outbox 的選型邊界">0.3 非同步選型</a>、<a href="/blog/backend/03-message-queue/broker-basics/" data-link-title="3.1 broker 基礎與投遞模型" data-link-desc="先理解 broker、queue、consumer 與 delivery semantics">3.1 broker basics</a></li>
<li>平行 vendor：<a href="/blog/backend/03-message-queue/vendors/rabbitmq/" data-link-title="RabbitMQ" data-link-desc="Classic message broker、AMQP routing 為主">RabbitMQ</a>、<a href="/blog/backend/03-message-queue/vendors/nats/" data-link-title="NATS" data-link-desc="Lightweight messaging、JetStream 加持久化與 streams">NATS</a></li>
<li>下游能力：<a href="/blog/backend/03-message-queue/consumer-design/" data-link-title="3.4 consumer 設計與去重" data-link-desc="整理 consumer、checkpoint 與 replay safety">3.4 consumer 設計</a>、<a href="/blog/backend/06-reliability/idempotency-replay/" data-link-title="6.12 Idempotency 與 Replay 驗證" data-link-desc="把重試、重播與冪等性從口頭約定變成可驗證屬性">6.12 idempotency / replay</a></li>
</ul>
]]></content:encoded></item><item><title>CircleCI</title><link>https://tarrragon.github.io/blog/backend/06-reliability/vendors/circleci/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/06-reliability/vendors/circleci/</guid><description>&lt;p>CircleCI 是獨立 CI/CD 平台、承擔三個責任：強進階 cache（layer-aware）+ parallelism（test splitting）、跨 VCS（GitHub / Bitbucket / GitLab）、resource class 彈性（含 macOS / ARM / GPU）。設計取捨偏向「進階 cache + 並行加速 + cross-VCS」、適合需要極致 build speed 跟 macOS runner 的團隊。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>寫 .circleci/config.yml workflow&lt;/li>
&lt;li>設計 cache + workspace 加速 build&lt;/li>
&lt;li>用 parallelism + test splitting&lt;/li>
&lt;li>選 resource class（CPU / memory / macOS / GPU）&lt;/li>
&lt;li>評估 CircleCI vs GitHub Actions 的選用&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑5-分鐘把-circleci-跑起來">最短路徑：5 分鐘把 CircleCI 跑起來&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c"># .circleci/config.yml&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">version&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">2.1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">jobs&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">test&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">docker&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">[&lt;/span>{&lt;span class="nt">image&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">cimg/node:20}]&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">steps&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">checkout&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">run&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">npm test&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">workflows&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">ci&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">jobs&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="l">test]&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="日常操作與決策形狀">日常操作與決策形狀&lt;/h2>
&lt;h3 id="pipeline--workflow--job-模型">Pipeline / workflow / job 模型&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>Pipeline（一次 trigger 的執行）&lt;/li>
&lt;li>Workflow（多 job 編排、DAG）&lt;/li>
&lt;li>Job（一組 step）&lt;/li>
&lt;li>對應指令範例：&lt;code>circleci local execute&lt;/code>（本地測 config）&lt;/li>
&lt;/ul>
&lt;h3 id="orb-重用">Orb 重用&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>Orb = package of reusable config（types / commands / jobs / executors）&lt;/li>
&lt;li>Public orb registry（circleci.com/developer/orbs）&lt;/li>
&lt;li>Private orb for company&lt;/li>
&lt;/ul>
&lt;h3 id="cache--workspace">Cache + workspace&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>Cache：跨 build 保留（dependency / build artifact）&lt;/li>
&lt;li>Workspace：同 workflow 內 job 之間傳遞&lt;/li>
&lt;li>Cache key 設計（與 GitHub Actions 類似）&lt;/li>
&lt;/ul>
&lt;h2 id="進階主題按需閱讀">進階主題（按需閱讀）&lt;/h2>
&lt;h3 id="parallelism--test-splitting">Parallelism + test splitting&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>Job parallelism N&lt;/li>
&lt;li>Test splitting by timing / name / class&lt;/li>
&lt;li>對應 test suite 加速&lt;/li>
&lt;/ul>
&lt;h3 id="resource-class">Resource class&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>small / medium / large / xlarge / 2xlarge&lt;/li>
&lt;li>macOS / Arm / GPU classes&lt;/li>
&lt;li>跟 cost 平衡&lt;/li>
&lt;/ul>
&lt;h3 id="self-hosted-runner">Self-hosted runner&lt;/h3>
&lt;p>子議題：&lt;/p></description><content:encoded><![CDATA[<p>CircleCI 是獨立 CI/CD 平台、承擔三個責任：強進階 cache（layer-aware）+ parallelism（test splitting）、跨 VCS（GitHub / Bitbucket / GitLab）、resource class 彈性（含 macOS / ARM / GPU）。設計取捨偏向「進階 cache + 並行加速 + cross-VCS」、適合需要極致 build speed 跟 macOS runner 的團隊。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>寫 .circleci/config.yml workflow</li>
<li>設計 cache + workspace 加速 build</li>
<li>用 parallelism + test splitting</li>
<li>選 resource class（CPU / memory / macOS / GPU）</li>
<li>評估 CircleCI vs GitHub Actions 的選用</li>
</ol>
<h2 id="最短路徑5-分鐘把-circleci-跑起來">最短路徑：5 分鐘把 CircleCI 跑起來</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c"># .circleci/config.yml</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="w"></span><span class="nt">version</span><span class="p">:</span><span class="w"> </span><span class="m">2.1</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="w"></span><span class="nt">jobs</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="w">  </span><span class="nt">test</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="w">    </span><span class="nt">docker</span><span class="p">:</span><span class="w"> </span><span class="p">[</span>{<span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">cimg/node:20}]</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="w">    </span><span class="nt">steps</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="w">      </span>- <span class="l">checkout</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="w">      </span>- <span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="l">npm test</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="w"></span><span class="nt">workflows</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="w">  </span><span class="nt">ci</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="w">    </span><span class="nt">jobs</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="l">test]</span></span></span></code></pre></div><h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="pipeline--workflow--job-模型">Pipeline / workflow / job 模型</h3>
<p>子議題：</p>
<ul>
<li>Pipeline（一次 trigger 的執行）</li>
<li>Workflow（多 job 編排、DAG）</li>
<li>Job（一組 step）</li>
<li>對應指令範例：<code>circleci local execute</code>（本地測 config）</li>
</ul>
<h3 id="orb-重用">Orb 重用</h3>
<p>子議題：</p>
<ul>
<li>Orb = package of reusable config（types / commands / jobs / executors）</li>
<li>Public orb registry（circleci.com/developer/orbs）</li>
<li>Private orb for company</li>
</ul>
<h3 id="cache--workspace">Cache + workspace</h3>
<p>子議題：</p>
<ul>
<li>Cache：跨 build 保留（dependency / build artifact）</li>
<li>Workspace：同 workflow 內 job 之間傳遞</li>
<li>Cache key 設計（與 GitHub Actions 類似）</li>
</ul>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<h3 id="parallelism--test-splitting">Parallelism + test splitting</h3>
<p>子議題：</p>
<ul>
<li>Job parallelism N</li>
<li>Test splitting by timing / name / class</li>
<li>對應 test suite 加速</li>
</ul>
<h3 id="resource-class">Resource class</h3>
<p>子議題：</p>
<ul>
<li>small / medium / large / xlarge / 2xlarge</li>
<li>macOS / Arm / GPU classes</li>
<li>跟 cost 平衡</li>
</ul>
<h3 id="self-hosted-runner">Self-hosted runner</h3>
<p>子議題：</p>
<ul>
<li>Runner agent</li>
<li>適合：內網 / 特殊環境</li>
</ul>
<h3 id="oidc-integration">OIDC integration</h3>
<p>子議題：</p>
<ul>
<li>OIDC token → AWS / GCP（無 long-lived secret）</li>
<li>跟 GitHub Actions 同 pattern</li>
</ul>
<h3 id="approval-job">Approval job</h3>
<p>子議題：</p>
<ul>
<li>type: approval job：人工介入</li>
<li>對應 <a href="/blog/backend/06-reliability/release-gate/" data-link-title="6.8 Release Gate 與變更節奏" data-link-desc="把驗證、migration、相容性納入放行判準">6.8 Release Gate</a></li>
</ul>
<h3 id="cross-vcs-support">Cross-VCS support</h3>
<p>子議題：</p>
<ul>
<li>GitHub / Bitbucket / GitLab</li>
<li>跟 GitHub Actions 只 GitHub 對比</li>
</ul>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<h3 id="build-慢">Build 慢</h3>
<p>操作原則：cache miss / test 沒 split / resource class 太小。</p>
<h3 id="cache-不命中">Cache 不命中</h3>
<p>操作原則：cache key 設計問題 / key change。</p>
<h3 id="parallelism-不均勻">Parallelism 不均勻</h3>
<p>操作原則：test split strategy（timing 最好但要 historical data）。</p>
<h3 id="approval-卡住">Approval 卡住</h3>
<p>操作原則：approval job 沒人按 / on-call 不在。</p>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>GitHub-hosted</td>
          <td><a href="/blog/backend/06-reliability/vendors/github-actions/" data-link-title="GitHub Actions" data-link-desc="GitHub 原生 CI/CD、PR check、deploy gate">GitHub Actions</a></td>
      </tr>
      <tr>
          <td>Self-hosted enterprise</td>
          <td>Jenkins / Buildkite / Tekton</td>
      </tr>
      <tr>
          <td>GitLab-hosted</td>
          <td>GitLab CI</td>
      </tr>
      <tr>
          <td>複雜 DAG / K8s-native</td>
          <td>Tekton / Argo Workflows</td>
      </tr>
      <tr>
          <td>預算敏感</td>
          <td>GitHub Actions / self-hosted Jenkins</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>各 Orb 細節</li>
<li>CircleCI Server（self-host enterprise）</li>
<li>Pricing 細節</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<table>
  <thead>
      <tr>
          <th>案例方向</th>
          <th>對應主題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/06-reliability/cases/stripe/idempotency-and-zero-downtime-migration/" data-link-title="Stripe：Idempotency 與零停機遷移的交易安全設計" data-link-desc="把 API 重試與資料遷移放在同一套安全模型，維持支付交易的一致結果。">Stripe：Idempotency 與零停機遷移</a></td>
          <td>canary deploy / approval job 的部署節奏</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/06-reliability/cases/shopify/bfcm-capacity-and-game-day/" data-link-title="Shopify：BFCM 容量治理與 Game Day 驗證節奏" data-link-desc="把季節性流量峰值轉成年度可靠性流程，透過容量模型、演練與隔離策略提前吸收風險。">Shopify：BFCM 容量治理與 Game Day</a></td>
          <td>峰值前 CI workflow 跑 capacity test</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/06-reliability/cases/microsoft/change-management-and-reliability-governance/" data-link-title="Microsoft：變更治理與可靠性門檻" data-link-desc="透過分層變更管理與發布閘門，降低大型 SaaS 平台的系統性回歸風險。">Microsoft：變更治理與可靠性門檻</a></td>
          <td>approval job 對應變更分層審查</td>
      </tr>
  </tbody>
</table>
<p><strong>待補 CircleCI customer case</strong>：大規模 CircleCI 採用、macOS / iOS CI 加速案例、CircleCI → GitHub Actions 遷移案例。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游概念：<a href="/blog/backend/06-reliability/release-gate/" data-link-title="6.8 Release Gate 與變更節奏" data-link-desc="把驗證、migration、相容性納入放行判準">6.8 Release Gate</a></li>
<li>平行 vendor：<a href="/blog/backend/06-reliability/vendors/github-actions/" data-link-title="GitHub Actions" data-link-desc="GitHub 原生 CI/CD、PR check、deploy gate">GitHub Actions</a></li>
<li>下游能力：<a href="/blog/backend/07-security-data-protection/" data-link-title="模組七：資安與資料保護" data-link-desc="以問題驅動方式擴充資安知識網：先定義服務環節問題，再以案例作為觸發式參考">07 security</a>、<a href="/blog/backend/05-deployment-platform/" data-link-title="模組五：部署平台與網路入口" data-link-desc="整理 Kubernetes、systemd、load balancer、container 與服務生命週期合約">5 deployment</a></li>
</ul>
]]></content:encoded></item><item><title>Docker</title><link>https://tarrragon.github.io/blog/backend/05-deployment-platform/vendors/docker/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/05-deployment-platform/vendors/docker/</guid><description>&lt;p>Docker 是最早 popularize container 的工具、承擔三個責任：container image build（Dockerfile / BuildKit）、local container runtime（docker run / Compose）、image distribution（Docker Hub / private registry）。設計取捨偏向「dev experience + image format standard」、production orchestration 多被 Kubernetes + containerd 取代、但 image build / dev workflow / OCI image 仍是事實標準。&lt;/p>
&lt;p>對「Local dev / CI container 工具、image build pipeline、小規模 dev 環境」這條路徑、Docker 是首選。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>寫 Dockerfile + 跑 docker build / run&lt;/li>
&lt;li>用 multi-stage build / BuildKit 優化 image&lt;/li>
&lt;li>用 Docker Compose 編排 dev 環境&lt;/li>
&lt;li>配置 image registry + scanning + SBOM&lt;/li>
&lt;li>評估 Docker Desktop license 對團隊的影響、選替代（Podman / Rancher Desktop）&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑5-分鐘把-docker-跑起來">最短路徑：5 分鐘把 Docker 跑起來&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 1. 安裝（macOS 擇一）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">brew install --cask docker &lt;span class="c1"># Docker Desktop（商業企業需付費授權）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="c1"># brew install podman # 替代方案：Podman（無 daemon、免費）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">&lt;span class="c1"># 2. 跑 container&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">docker run -d -p 8080:80 --name web nginx:stable-alpine
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">docker ps &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> docker logs web
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="c1"># 3. Build + push image&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">docker build -t myapp:1 .
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">docker tag myapp:1 ghcr.io/&amp;lt;org&amp;gt;/myapp:1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">docker push ghcr.io/&amp;lt;org&amp;gt;/myapp:1&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="日常操作與決策形狀">日常操作與決策形狀&lt;/h2>
&lt;h3 id="dockerfile-設計">Dockerfile 設計&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>FROM / RUN / COPY / WORKDIR / EXPOSE / CMD / ENTRYPOINT&lt;/li>
&lt;li>Multi-stage build（build stage + runtime stage 分離）&lt;/li>
&lt;li>Layer cache 設計（COPY 順序影響 cache hit）&lt;/li>
&lt;li>對應指令：&lt;code>docker build --no-cache&lt;/code>、&lt;code>docker history &amp;lt;image&amp;gt;&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="buildkit--buildx">BuildKit / Buildx&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>BuildKit：新 builder、parallel + cache mount + secret + SSH agent&lt;/li>
&lt;li>Buildx：cross-platform build（amd64 / arm64）&lt;/li>
&lt;li>Cache backend（local / registry / S3 / GHA）&lt;/li>
&lt;li>對應指令：&lt;code>docker buildx create --use&lt;/code>、&lt;code>docker buildx build --platform=linux/amd64,linux/arm64&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="docker-compose">Docker Compose&lt;/h3>
&lt;p>子議題：&lt;/p></description><content:encoded><![CDATA[<p>Docker 是最早 popularize container 的工具、承擔三個責任：container image build（Dockerfile / BuildKit）、local container runtime（docker run / Compose）、image distribution（Docker Hub / private registry）。設計取捨偏向「dev experience + image format standard」、production orchestration 多被 Kubernetes + containerd 取代、但 image build / dev workflow / OCI image 仍是事實標準。</p>
<p>對「Local dev / CI container 工具、image build pipeline、小規模 dev 環境」這條路徑、Docker 是首選。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>寫 Dockerfile + 跑 docker build / run</li>
<li>用 multi-stage build / BuildKit 優化 image</li>
<li>用 Docker Compose 編排 dev 環境</li>
<li>配置 image registry + scanning + SBOM</li>
<li>評估 Docker Desktop license 對團隊的影響、選替代（Podman / Rancher Desktop）</li>
</ol>
<h2 id="最短路徑5-分鐘把-docker-跑起來">最短路徑：5 分鐘把 Docker 跑起來</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># 1. 安裝（macOS 擇一）</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">brew install --cask docker            <span class="c1"># Docker Desktop（商業企業需付費授權）</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="c1"># brew install podman                 # 替代方案：Podman（無 daemon、免費）</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="c1"># 2. 跑 container</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">docker run -d -p 8080:80 --name web nginx:stable-alpine
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">docker ps <span class="o">&amp;&amp;</span> docker logs web
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="c1"># 3. Build + push image</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">docker build -t myapp:1 .
</span></span><span class="line"><span class="ln">11</span><span class="cl">docker tag myapp:1 ghcr.io/&lt;org&gt;/myapp:1
</span></span><span class="line"><span class="ln">12</span><span class="cl">docker push ghcr.io/&lt;org&gt;/myapp:1</span></span></code></pre></div><h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="dockerfile-設計">Dockerfile 設計</h3>
<p>子議題：</p>
<ul>
<li>FROM / RUN / COPY / WORKDIR / EXPOSE / CMD / ENTRYPOINT</li>
<li>Multi-stage build（build stage + runtime stage 分離）</li>
<li>Layer cache 設計（COPY 順序影響 cache hit）</li>
<li>對應指令：<code>docker build --no-cache</code>、<code>docker history &lt;image&gt;</code></li>
</ul>
<h3 id="buildkit--buildx">BuildKit / Buildx</h3>
<p>子議題：</p>
<ul>
<li>BuildKit：新 builder、parallel + cache mount + secret + SSH agent</li>
<li>Buildx：cross-platform build（amd64 / arm64）</li>
<li>Cache backend（local / registry / S3 / GHA）</li>
<li>對應指令：<code>docker buildx create --use</code>、<code>docker buildx build --platform=linux/amd64,linux/arm64</code></li>
</ul>
<h3 id="docker-compose">Docker Compose</h3>
<p>子議題：</p>
<ul>
<li>docker-compose.yml：service / network / volume 配置</li>
<li>適合：local dev 多 container（DB + cache + app）</li>
<li>不適合：production（用 K8s）</li>
<li>對應 <a href="/blog/backend/05-deployment-platform/kubernetes-deployment/" data-link-title="5.2 Kubernetes 部署策略" data-link-desc="整理 deployment、probe 與 rolling update">5.2 K8s deployment</a></li>
</ul>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<h3 id="image-security--scanning--sbom">Image security / scanning / SBOM</h3>
<p>子議題：</p>
<ul>
<li>Trivy / Grype / Snyk image vulnerability scanning</li>
<li>SBOM 產生（syft / Docker scout）</li>
<li>Sign image（cosign / notary v2）</li>
<li>對應 <a href="/blog/backend/07-security-data-protection/" data-link-title="模組七：資安與資料保護" data-link-desc="以問題驅動方式擴充資安知識網：先定義服務環節問題，再以案例作為觸發式參考">07 security</a> supply chain</li>
</ul>
<h3 id="image-registry-選擇">Image registry 選擇</h3>
<p>子議題：</p>
<ul>
<li>Docker Hub（public + rate limit issue）</li>
<li>雲端：ECR / GCR / Artifact Registry / ACR</li>
<li>Self-host：Harbor / GitLab Container Registry / Nexus</li>
<li>對應 image pull credentials 管理</li>
</ul>
<h3 id="docker-desktop-license">Docker Desktop license</h3>
<p>子議題：</p>
<ul>
<li>2021 改授權：商業企業（&gt; 250 員工 / &gt; $10M）需付費</li>
<li>替代：Podman Desktop / Rancher Desktop / Colima / Lima</li>
<li>替代品的 daemon / rootless 差異</li>
<li>對應企業 IT 採購決策</li>
</ul>
<h3 id="containerd--cri-o-在-production">Containerd / CRI-O 在 production</h3>
<p>子議題：</p>
<ul>
<li>K8s 1.24+ 移除 dockershim、改用 containerd / CRI-O</li>
<li>Docker image 跟 containerd 相容（OCI standard）</li>
<li>production 不用 Docker、用 containerd</li>
</ul>
<h3 id="image-size-優化">Image size 優化</h3>
<p>子議題：</p>
<ul>
<li>Base image 選擇（distroless / alpine / scratch）</li>
<li>Multi-stage build + layer combine</li>
<li>Build context（.dockerignore）</li>
<li>跟 image scanning 跟 deploy speed 對應</li>
</ul>
<h3 id="rootless--安全強化">Rootless / 安全強化</h3>
<p>子議題：</p>
<ul>
<li>Rootless mode（Docker / Podman 都支援）</li>
<li>User namespace mapping</li>
<li>Seccomp / AppArmor / SELinux profile</li>
<li>對應 <a href="/blog/backend/07-security-data-protection/" data-link-title="模組七：資安與資料保護" data-link-desc="以問題驅動方式擴充資安知識網：先定義服務環節問題，再以案例作為觸發式參考">07 security</a> container security</li>
</ul>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<h3 id="image-build-cache-不命中">Image build cache 不命中</h3>
<p>操作原則：COPY 順序錯、<code>.dockerignore</code> 缺、變動的 layer 在前面。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">docker build --progress<span class="o">=</span>plain --no-cache -t myapp:debug .   <span class="c1"># 逐層輸出、比對哪層吃時間</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">docker <span class="nb">history</span> myapp:debug                                  <span class="c1"># 看每層大小</span></span></span></code></pre></div><h3 id="image-過大">Image 過大</h3>
<p>操作原則：base image 太重 / 沒 multi-stage / build context 過大。判讀：<code>docker history</code> 看 layer 大小。</p>
<h3 id="container-起不來">Container 起不來</h3>
<p>操作原則：<code>docker logs</code> + <code>docker inspect</code> 看 exit code + state。</p>
<h3 id="network-port-不通">Network port 不通</h3>
<p>操作原則：<code>-p</code> mapping vs <code>EXPOSE</code> 差異、host network vs bridge network、firewall。</p>
<h3 id="volume-權限問題">Volume 權限問題</h3>
<p>操作原則：container UID 跟 host UID 不對齊、rootless mode 特別容易踩。</p>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Production orchestration</td>
          <td><a href="/blog/backend/05-deployment-platform/vendors/kubernetes/" data-link-title="Kubernetes" data-link-desc="Container orchestration 主流、GKE / EKS / AKS / 自管">Kubernetes</a></td>
      </tr>
      <tr>
          <td>Rootless / 安全強化</td>
          <td>Podman</td>
      </tr>
      <tr>
          <td>替代 Docker Desktop（cost）</td>
          <td>Rancher Desktop / Colima / Lima</td>
      </tr>
      <tr>
          <td>純單機 service</td>
          <td><a href="/blog/backend/05-deployment-platform/vendors/systemd/" data-link-title="systemd" data-link-desc="Linux init system、VM / 單機 service lifecycle">systemd</a></td>
      </tr>
      <tr>
          <td>雲端 managed container</td>
          <td>ECS / Cloud Run / Container Apps</td>
      </tr>
      <tr>
          <td>Build-only（無 daemon）</td>
          <td>Buildah / Kaniko / BuildKit standalone</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Dockerfile 完整 reference</li>
<li>Docker Compose v2 進階配置</li>
<li>Container runtime spec（runc / OCI）</li>
<li>各 registry 完整 API</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<h3 id="跨-vendor-對照">跨 vendor 對照</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>對 Docker 的對應</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/05-deployment-platform/cases/orbitera-managed-kubernetes-migration/" data-link-title="5.C3 Orbitera：遷移到 Managed Kubernetes" data-link-desc="平台重置時如何讓產品不中斷地完成編排層轉換。">5.C3 Orbitera managed K8s</a></td>
          <td>Container image 是平台遷移的可攜介面、orchestrator 換但 image 不換</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/05-deployment-platform/cases/contrast-platform-migration-by-scale/" data-link-title="5.C10 對照：規模差異下的平台遷移" data-link-desc="平台遷移策略在小中大型組織下的差異。">5.C10 規模對照</a></td>
          <td>小規模直接 Docker / Compose、中大型才走 K8s（Docker 退到 build only）</td>
      </tr>
  </tbody>
</table>
<p><strong>待補 Docker 案例</strong>：Docker Hub rate limit incident、企業 license 遷移到 Podman 案例、image scanning supply chain 案例。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游概念：<a href="/blog/backend/05-deployment-platform/container-runtime/" data-link-title="5.1 container 與 runtime" data-link-desc="整理 image、resource limit 與啟動行為">5.1 container runtime</a></li>
<li>平行 vendor：<a href="/blog/backend/05-deployment-platform/vendors/kubernetes/" data-link-title="Kubernetes" data-link-desc="Container orchestration 主流、GKE / EKS / AKS / 自管">Kubernetes</a>、<a href="/blog/backend/05-deployment-platform/vendors/systemd/" data-link-title="systemd" data-link-desc="Linux init system、VM / 單機 service lifecycle">systemd</a></li>
<li>下游能力：<a href="/blog/backend/07-security-data-protection/" data-link-title="模組七：資安與資料保護" data-link-desc="以問題驅動方式擴充資安知識網：先定義服務環節問題，再以案例作為觸發式參考">07 security</a>（image scanning / SBOM）</li>
</ul>
]]></content:encoded></item><item><title>Opsgenie</title><link>https://tarrragon.github.io/blog/backend/08-incident-response/vendors/opsgenie/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/08-incident-response/vendors/opsgenie/</guid><description>&lt;p>Opsgenie 是 Atlassian 出品的 on-call 平台、承擔三個責任：alert routing + escalation policy、跟 Atlassian 套件（Jira Service Management / Statuspage / Confluence）深度整合、heartbeat monitoring（被動觀察 service 是否還在）。已被併入 Jira Service Management Cloud、原獨立服務逐漸 deprecated。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Opsgenie 的核心定位是 &lt;em>Atlassian 生態內的 on-call 元件&lt;/em>、跟 &lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/vendors/pagerduty/" data-link-title="PagerDuty" data-link-desc="On-call / alerting 主流 SaaS、IR 平台演化">PagerDuty&lt;/a> 比、它的差異在 &lt;em>跟 Jira Service Management / Confluence / Statuspage 的整合深度&lt;/em>、paging 能力本身相近：ticket、runbook、status page、incident 都在同一個身份體系（Atlassian Identity）內、不用跨 SaaS 串 SSO 跟 webhook。Atlassian-heavy enterprise 通常已經買了 JSM / Confluence / Statuspage、再買獨立 PagerDuty 等於多一條供應商線、ROI 不一定划算。&lt;/p>
&lt;p>2025 年 Atlassian 公開宣布 &lt;em>Opsgenie 將在 2027 年 4 月 EOL&lt;/em>、原 Opsgenie standalone 客戶要遷移到 &lt;a href="https://www.atlassian.com/software/jira/service-management">Jira Service Management Premium / Enterprise&lt;/a> 內建的 on-call 能力。這是現有 Opsgenie 客戶在 2025-2027 期間的最大議題、新案不該再選 Opsgenie standalone。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;ol>
&lt;li>配置 Opsgenie team / schedule / escalation&lt;/li>
&lt;li>設計 alert routing 與 deduplication&lt;/li>
&lt;li>整合 Jira Service Management / Statuspage / Confluence&lt;/li>
&lt;li>用 Heartbeat monitoring 守護 cron / scheduled job&lt;/li>
&lt;li>評估 Opsgenie → JSM Cloud 遷移路徑&lt;/li>
&lt;/ol>
&lt;h2 id="最短判讀路徑">最短判讀路徑&lt;/h2>
&lt;p>判斷 Opsgenie deployment 是否健康、最少看四件事：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>誰能 ack alert&lt;/strong>：schedule rotation 是否真的有人在線、override 機制是否被濫用（永久 override 掩蓋人力缺口）、escalation policy 的 final step 是否有 fallback team 而非無限循環&lt;/li>
&lt;li>&lt;strong>跟 JSM migration plan&lt;/strong>：是否已盤點 standalone Opsgenie 跟 JSM on-call 的 feature gap、現有 integration（Datadog / Prometheus webhook、Slack routing、custom API）在 JSM on-call 是否 parity、API token / Terraform config 的轉換路徑&lt;/li>
&lt;li>&lt;strong>Atlassian Identity 整合&lt;/strong>：是否走 Atlassian Access（IdP SSO + SCIM provision + audit log）、還是停留在 Opsgenie 自己的 user store；後者在 migration / offboarding / compliance 都是坑&lt;/li>
&lt;li>&lt;strong>Slack notification routing&lt;/strong>：alert routing 規則是 fan-out 到所有 team channel（吵雜）還是 priority-based（P1 → on-call DM + channel、P3 → channel only）；Slack 是事實上的 incident war room、routing 不對 SOC 就漏接&lt;/li>
&lt;/ul>
&lt;p>四件事任一缺失、就是 &lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/drills-and-oncall-readiness/" data-link-title="8.6 演練與值班能力建設" data-link-desc="用演練與值班訓練提升事故反應品質">Drills and On-call Readiness&lt;/a> 邊界的待補項目。&lt;/p></description><content:encoded><![CDATA[<p>Opsgenie 是 Atlassian 出品的 on-call 平台、承擔三個責任：alert routing + escalation policy、跟 Atlassian 套件（Jira Service Management / Statuspage / Confluence）深度整合、heartbeat monitoring（被動觀察 service 是否還在）。已被併入 Jira Service Management Cloud、原獨立服務逐漸 deprecated。</p>
<h2 id="服務定位">服務定位</h2>
<p>Opsgenie 的核心定位是 <em>Atlassian 生態內的 on-call 元件</em>、跟 <a href="/blog/backend/08-incident-response/vendors/pagerduty/" data-link-title="PagerDuty" data-link-desc="On-call / alerting 主流 SaaS、IR 平台演化">PagerDuty</a> 比、它的差異在 <em>跟 Jira Service Management / Confluence / Statuspage 的整合深度</em>、paging 能力本身相近：ticket、runbook、status page、incident 都在同一個身份體系（Atlassian Identity）內、不用跨 SaaS 串 SSO 跟 webhook。Atlassian-heavy enterprise 通常已經買了 JSM / Confluence / Statuspage、再買獨立 PagerDuty 等於多一條供應商線、ROI 不一定划算。</p>
<p>2025 年 Atlassian 公開宣布 <em>Opsgenie 將在 2027 年 4 月 EOL</em>、原 Opsgenie standalone 客戶要遷移到 <a href="https://www.atlassian.com/software/jira/service-management">Jira Service Management Premium / Enterprise</a> 內建的 on-call 能力。這是現有 Opsgenie 客戶在 2025-2027 期間的最大議題、新案不該再選 Opsgenie standalone。</p>
<h2 id="本章目標">本章目標</h2>
<ol>
<li>配置 Opsgenie team / schedule / escalation</li>
<li>設計 alert routing 與 deduplication</li>
<li>整合 Jira Service Management / Statuspage / Confluence</li>
<li>用 Heartbeat monitoring 守護 cron / scheduled job</li>
<li>評估 Opsgenie → JSM Cloud 遷移路徑</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Opsgenie deployment 是否健康、最少看四件事：</p>
<ul>
<li><strong>誰能 ack alert</strong>：schedule rotation 是否真的有人在線、override 機制是否被濫用（永久 override 掩蓋人力缺口）、escalation policy 的 final step 是否有 fallback team 而非無限循環</li>
<li><strong>跟 JSM migration plan</strong>：是否已盤點 standalone Opsgenie 跟 JSM on-call 的 feature gap、現有 integration（Datadog / Prometheus webhook、Slack routing、custom API）在 JSM on-call 是否 parity、API token / Terraform config 的轉換路徑</li>
<li><strong>Atlassian Identity 整合</strong>：是否走 Atlassian Access（IdP SSO + SCIM provision + audit log）、還是停留在 Opsgenie 自己的 user store；後者在 migration / offboarding / compliance 都是坑</li>
<li><strong>Slack notification routing</strong>：alert routing 規則是 fan-out 到所有 team channel（吵雜）還是 priority-based（P1 → on-call DM + channel、P3 → channel only）；Slack 是事實上的 incident war room、routing 不對 SOC 就漏接</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/08-incident-response/drills-and-oncall-readiness/" data-link-title="8.6 演練與值班能力建設" data-link-desc="用演練與值班訓練提升事故反應品質">Drills and On-call Readiness</a> 邊界的待補項目。</p>
<h2 id="最短路徑">最短路徑</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 1. Atlassian admin 啟用 Opsgenie / JSM</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># 2. 建 team / schedule</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="c1"># 3. 配置 integration（Datadog / Prometheus webhook）</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 4. 試 alert + escalation</span></span></span></code></pre></div><h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="team--schedule--escalation">Team / schedule / escalation</h3>
<p>子議題：</p>
<ul>
<li>Team 對應 service 或 component</li>
<li>Schedule rotation / override</li>
<li>Escalation policy（多 step / responder）</li>
</ul>
<h3 id="alert-routing--atlassian-套件整合">Alert routing + Atlassian 套件整合</h3>
<p>子議題：</p>
<ul>
<li>Routing rule（priority / source）+ deduplication</li>
<li>Jira Service Management（ITSM workflow）</li>
<li>Statuspage（incident → public update）</li>
<li>Confluence runbook</li>
<li>Slack / Teams 通知</li>
</ul>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Opsgenie</th>
          <th>PagerDuty</th>
          <th>incident.io</th>
          <th>Grafana OnCall</th>
          <th>JSM Premium on-call</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>生態錨點</td>
          <td>Atlassian（JSM / Confluence / Statuspage）</td>
          <td>獨立 SaaS、整合廣</td>
          <td>Slack-first、incident workflow</td>
          <td>Grafana stack（OSS-friendly）</td>
          <td>Atlassian 內建</td>
      </tr>
      <tr>
          <td>計費模型</td>
          <td>按 user / month</td>
          <td>按 user / month + add-on</td>
          <td>按 user / month</td>
          <td>OSS 免費 / Grafana Cloud 付費</td>
          <td>包在 JSM Premium / Enterprise license</td>
      </tr>
      <tr>
          <td>身份整合</td>
          <td>Atlassian Identity / Access SSO</td>
          <td>自家 + SAML / SCIM</td>
          <td>Slack identity + SAML</td>
          <td>Grafana auth + OAuth</td>
          <td>Atlassian Identity（原生）</td>
      </tr>
      <tr>
          <td>Runbook / postmortem</td>
          <td>Confluence runbook + 基本 postmortem</td>
          <td>Runbook Automation + Jeli postmortem</td>
          <td>內建 incident timeline + retrospective</td>
          <td>Grafana dashboard runbook（弱）</td>
          <td>Confluence + JSM workflow</td>
      </tr>
      <tr>
          <td>長期路徑</td>
          <td>2027/4 EOL、移到 JSM on-call</td>
          <td>持續演進、Process Automation 加深</td>
          <td>持續演進、IR workflow 強化</td>
          <td>持續演進、OSS 路線</td>
          <td>跟 JSM 同步演進</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>既有 Opsgenie 客戶 migration 期、無新案</td>
          <td>不在 Atlassian 生態、跨工具堆疊</td>
          <td>Slack-native IR、incident workflow 重</td>
          <td>OSS / 預算敏感、Grafana 已用</td>
          <td>Atlassian-heavy enterprise</td>
      </tr>
  </tbody>
</table>
<p>選 Opsgenie 的核心訴求現在 <em>只有一個</em>：既有客戶在 EOL 前的 migration 緩衝期。新案應該直接走 JSM Premium on-call（已在 Atlassian 生態）、PagerDuty（不在 Atlassian 生態）或 incident.io（Slack-native）。</p>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<h3 id="heartbeat-monitoring">Heartbeat monitoring</h3>
<p>子議題：主動 ping 監控、schedule heartbeat（cron / batch job 守護）。Heartbeat 是 <em>被動 alert</em> 的補位 — cron 跑完該打 ping、ping 沒到就 alert；常見坑是 network 路徑或 outbound proxy 擋掉 ping、cron 其實正常但 Opsgenie 收不到、變成 false positive 半夜叫人。</p>
<h3 id="atlassian-整合深度">Atlassian 整合深度</h3>
<p>子議題：Issue creation / sync、SLA / OLA tracking、audit log。跟 PagerDuty + Jira webhook 比、Opsgenie 的差異是 <em>同身份體系 + native field mapping</em> — incident 直接綁 JSM ticket、Statuspage component 跟 Opsgenie service 同 schema、Confluence runbook 在 Opsgenie alert 內可直接 inline 預覽。</p>
<h3 id="team-based-routing-跟-service-ownership">Team-based routing 跟 service ownership</h3>
<p>子議題：team 對應 service / component 的 ownership model、global schedule 跟 team-local schedule 的分層、cross-team escalation（DB team alert escalate 到 platform team）。跟 PagerDuty 比 Opsgenie 的 team 是 first-class concept、跟 JSM project / Confluence space 雙向綁、ownership 邊界比 PagerDuty service 更貼近組織結構。</p>
<h3 id="atlassian-identity-sso--audit">Atlassian Identity SSO + audit</h3>
<p>子議題：<a href="https://www.atlassian.com/software/access">Atlassian Access</a> 統一 IdP SSO（Okta / Azure AD / Google Workspace）+ SCIM 自動 provision / deprovision、audit log 集中。沒走 Atlassian Access 的 Opsgenie 是 <em>身份孤島</em> — 離職員工 JSM 已 deprovision 但 Opsgenie schedule 還在、半夜還會被 page。</p>
<h3 id="opsgenie--jsm-cloud--jsm-premium-on-call-過渡">Opsgenie → JSM Cloud / JSM Premium on-call 過渡</h3>
<p>子議題：原 Opsgenie 用戶遷移時程（Atlassian 官方公告 2027/4 EOL）、功能 parity 盤點（migration 前確認 integration / API / Terraform config 都有對應）、API 兼容（Opsgenie REST API 在 JSM 上是否保留 / 改路徑）。migration 不是換工具、是換產品架構 — schedule / escalation / integration / runbook 的 ID 都會變、要規劃 <em>parallel run 期</em> 而非 cutover。</p>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<ul>
<li><strong>Alert 不觸發</strong>：integration / API key / routing rule</li>
<li><strong>Heartbeat false alarm</strong>：cron 跑了但 ping 沒到 / network</li>
<li><strong>Atlassian 整合斷裂</strong>：JSM permission / project mapping</li>
<li><strong>通知 missed</strong>：mobile app / push / SMS provider</li>
<li><strong>Escalation 跨時區壞掉</strong>：schedule timezone 設錯（team timezone vs user timezone）、override 把全 24hr 都蓋掉、final step 沒 fallback team — 跑 game day 驗證實際 paging 路徑、不只看 config</li>
<li><strong>Stale schedule</strong>：有人離職但 schedule 沒撤、半夜叫到前同事；走 Atlassian Access SCIM auto-deprovision、或定期 schedule audit</li>
<li><strong>Atlassian Cloud authentication trap</strong>：API token 過期 / 換 region / Atlassian Access policy 變更導致 integration 全斷；token 走 secret manager、Atlassian Access policy 變更前先 dry-run integration</li>
<li><strong>JSM migration drift</strong>：migration 期間 standalone Opsgenie 跟 JSM on-call 兩邊 schedule / escalation 不同步、alert 兩邊都觸發或都沒觸發；parallel run 期要有 <em>single source of truth</em> 跟 reconciliation script</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>不在 Atlassian 生態</td>
          <td><a href="/blog/backend/08-incident-response/vendors/pagerduty/" data-link-title="PagerDuty" data-link-desc="On-call / alerting 主流 SaaS、IR 平台演化">PagerDuty</a></td>
      </tr>
      <tr>
          <td>OSS 偏好</td>
          <td><a href="/blog/backend/08-incident-response/vendors/grafana-oncall/" data-link-title="Grafana OnCall" data-link-desc="OSS-friendly on-call 平台、Grafana Labs 維護、Apache 2.0、Grafana IRM bundle 把 OnCall &#43; Incident 收進一個 alert-to-resolve 流程">Grafana OnCall</a></td>
      </tr>
      <tr>
          <td>Slack-native IR</td>
          <td><a href="/blog/backend/08-incident-response/vendors/incident-io/" data-link-title="incident.io" data-link-desc="Slack-native IR 平台、整合 paging / response / retro">incident.io</a></td>
      </tr>
      <tr>
          <td>Microsoft Teams + IR</td>
          <td><a href="/blog/backend/08-incident-response/vendors/firehydrant/" data-link-title="FireHydrant" data-link-desc="IR &#43; retrospective 平台、Slack / Teams 整合、service catalog &#43; runbook automation 為核心">FireHydrant</a></td>
      </tr>
      <tr>
          <td>新案、Atlassian-heavy</td>
          <td>JSM Premium / Enterprise 內建 on-call（取代 Opsgenie standalone）</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Jira Service Management 完整 ITSM workflow / Atlassian Cloud admin / Statuspage 細節</li>
<li>JSM Premium on-call 完整 feature set（屬 Atlassian product roadmap、跟 Opsgenie EOL 公告同期演進）</li>
<li>Atlassian Access 完整 IdP / SCIM 設定（屬 identity 模組）</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p><strong>Opsgenie 是 Atlassian 自家產品</strong>：Atlassian 內部 incident routing / on-call 走 Opsgenie + Jira Service Management、其多租戶事故的協作流程是 Opsgenie 在大型 IR 場景的代表樣本。Atlassian-heavy enterprise 看這個案例的角度不是「PagerDuty 也能做」、而是「同身份體系 + JSM ticket / Confluence runbook / Statuspage 在 14 天事故內怎麼協作」— 這是 Opsgenie 在生態整合上的代表性場景。</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>對應主題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/08-incident-response/cases/atlassian/" data-link-title="Atlassian" data-link-desc="Atlassian 多租戶事故時間線與架構脈絡">Atlassian cases</a></td>
          <td>14 天事故的 incident commander 輪值與 paging 節奏</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/08-incident-response/drills-and-oncall-readiness/" data-link-title="8.6 演練與值班能力建設" data-link-desc="用演練與值班訓練提升事故反應品質">Drills and On-call Readiness</a></li>
<li>平行：<a href="/blog/backend/08-incident-response/vendors/pagerduty/" data-link-title="PagerDuty" data-link-desc="On-call / alerting 主流 SaaS、IR 平台演化">PagerDuty</a>、<a href="/blog/backend/08-incident-response/vendors/atlassian-statuspage/" data-link-title="Atlassian Statuspage" data-link-desc="公開狀態頁 SaaS、Atlassian 出品、enterprise polish &#43; Atlassian 生態整合、subscriber notification &#43; component dependency 是核心責任">Atlassian Statuspage</a></li>
<li>下游：<a href="/blog/backend/08-incident-response/incident-decision-log/" data-link-title="8.19 Incident Decision Log" data-link-desc="把事中假設、決策、證據、回退條件與責任人留下可復盤紀錄">8.19 Incident Decision Log</a></li>
</ul>
]]></content:encoded></item><item><title>Prometheus</title><link>https://tarrragon.github.io/blog/backend/04-observability/vendors/prometheus/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/04-observability/vendors/prometheus/</guid><description>&lt;p>Prometheus 是 CNCF graduated 的 metrics 系統、承擔三個責任：pull-based metrics scraping（service discovery + scrape）、PromQL 查詢與 recording rules、Alertmanager 告警與路由。設計取捨偏向「短中期 metrics + 簡單部署 + cloud-native 整合」、長期儲存交給 Mimir / Thanos / Cortex。是 Kubernetes 生態 metrics 的事實標準。&lt;/p>
&lt;p>對「K8s metrics、service metrics、需要 PromQL 表達能力、自管 metrics 棧」這條路徑、Prometheus 是首選。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>用 docker 跑起 Prometheus、配置 scrape target&lt;/li>
&lt;li>用 PromQL 查詢 metrics、寫 recording rules / alerting rules&lt;/li>
&lt;li>設計 service discovery（K8s / Consul / file_sd）&lt;/li>
&lt;li>看懂 cardinality 訊號、避免 label explosion&lt;/li>
&lt;li>評估長期儲存（Thanos / Mimir / Cortex）跟 remote write 的選擇&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑5-分鐘把-prometheus-跑起來">最短路徑：5 分鐘把 Prometheus 跑起來&lt;/h2>
&lt;p>先建最小 config 檔（Prometheus scrape 自己）：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c"># prometheus.yml&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">global&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">scrape_interval&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">15s&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">scrape_configs&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">job_name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;prometheus&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">static_configs&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">targets&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;localhost:9090&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>啟動並驗證：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 1. 啟動 Prometheus&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">docker run -d --name prom -p 9090:9090 &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> -v &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>&lt;span class="nb">pwd&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">/prometheus.yml:/etc/prometheus/prometheus.yml&amp;#34;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> prom/prometheus
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="c1"># 2. 確認 target 正常（等 15 秒讓第一次 scrape 完成）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">curl -s http://localhost:9090/api/v1/targets &lt;span class="p">|&lt;/span> jq &lt;span class="s1">&amp;#39;.data.activeTargets[].health&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="c1"># 3. 查詢驗證&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">curl -s &lt;span class="s1">&amp;#39;http://localhost:9090/api/v1/query?query=up&amp;#39;&lt;/span> &lt;span class="p">|&lt;/span> jq &lt;span class="s1">&amp;#39;.data.result[].value[1]&amp;#39;&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>up&lt;/code> 回傳 &lt;code>&amp;quot;1&amp;quot;&lt;/code> 代表 Prometheus 能 scrape 自己。瀏覽器訪 &lt;code>http://localhost:9090&lt;/code> 可用 PromQL UI 互動查詢。實際 production 要配 retention、alerting rules 與 HA。&lt;/p>
&lt;h2 id="日常操作與決策形狀">日常操作與決策形狀&lt;/h2>
&lt;h3 id="scrape-配置與-service-discovery">Scrape 配置與 service discovery&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>Static config：手動列 target、適合小規模&lt;/li>
&lt;li>File SD：動態檔案、適合外部系統推送&lt;/li>
&lt;li>Kubernetes SD：K8s API server 動態發現&lt;/li>
&lt;li>Consul SD：跟 Consul service registry 整合&lt;/li>
&lt;li>對應配置：&lt;code>scrape_configs&lt;/code> 區段&lt;/li>
&lt;/ul>
&lt;h3 id="promql-查詢">PromQL 查詢&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>Instant query vs range query&lt;/li>
&lt;li>Aggregation：sum / avg / max / min / count + by / without&lt;/li>
&lt;li>Rate / increase（counter 處理）&lt;/li>
&lt;li>Histogram quantile（histogram_quantile + bucket）&lt;/li>
&lt;li>對應指令：HTTP API &lt;code>/api/v1/query&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="recording-rules--alerting-rules">Recording rules / Alerting rules&lt;/h3>
&lt;p>子議題：&lt;/p></description><content:encoded><![CDATA[<p>Prometheus 是 CNCF graduated 的 metrics 系統、承擔三個責任：pull-based metrics scraping（service discovery + scrape）、PromQL 查詢與 recording rules、Alertmanager 告警與路由。設計取捨偏向「短中期 metrics + 簡單部署 + cloud-native 整合」、長期儲存交給 Mimir / Thanos / Cortex。是 Kubernetes 生態 metrics 的事實標準。</p>
<p>對「K8s metrics、service metrics、需要 PromQL 表達能力、自管 metrics 棧」這條路徑、Prometheus 是首選。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>用 docker 跑起 Prometheus、配置 scrape target</li>
<li>用 PromQL 查詢 metrics、寫 recording rules / alerting rules</li>
<li>設計 service discovery（K8s / Consul / file_sd）</li>
<li>看懂 cardinality 訊號、避免 label explosion</li>
<li>評估長期儲存（Thanos / Mimir / Cortex）跟 remote write 的選擇</li>
</ol>
<h2 id="最短路徑5-分鐘把-prometheus-跑起來">最短路徑：5 分鐘把 Prometheus 跑起來</h2>
<p>先建最小 config 檔（Prometheus scrape 自己）：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="ln">1</span><span class="cl"><span class="c"># prometheus.yml</span><span class="w">
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="w"></span><span class="nt">global</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="w">  </span><span class="nt">scrape_interval</span><span class="p">:</span><span class="w"> </span><span class="l">15s</span><span class="w">
</span></span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="w"></span><span class="nt">scrape_configs</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="w">  </span>- <span class="nt">job_name</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;prometheus&#34;</span><span class="w">
</span></span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="w">    </span><span class="nt">static_configs</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="w">      </span>- <span class="nt">targets</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&#34;localhost:9090&#34;</span><span class="p">]</span></span></span></code></pre></div><p>啟動並驗證：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># 1. 啟動 Prometheus</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">docker run -d --name prom -p 9090:9090 <span class="se">\
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="se"></span>  -v <span class="s2">&#34;</span><span class="k">$(</span><span class="nb">pwd</span><span class="k">)</span><span class="s2">/prometheus.yml:/etc/prometheus/prometheus.yml&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="se"></span>  prom/prometheus
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="c1"># 2. 確認 target 正常（等 15 秒讓第一次 scrape 完成）</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">curl -s http://localhost:9090/api/v1/targets <span class="p">|</span> jq <span class="s1">&#39;.data.activeTargets[].health&#39;</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="c1"># 3. 查詢驗證</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">curl -s <span class="s1">&#39;http://localhost:9090/api/v1/query?query=up&#39;</span> <span class="p">|</span> jq <span class="s1">&#39;.data.result[].value[1]&#39;</span></span></span></code></pre></div><p><code>up</code> 回傳 <code>&quot;1&quot;</code> 代表 Prometheus 能 scrape 自己。瀏覽器訪 <code>http://localhost:9090</code> 可用 PromQL UI 互動查詢。實際 production 要配 retention、alerting rules 與 HA。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="scrape-配置與-service-discovery">Scrape 配置與 service discovery</h3>
<p>子議題：</p>
<ul>
<li>Static config：手動列 target、適合小規模</li>
<li>File SD：動態檔案、適合外部系統推送</li>
<li>Kubernetes SD：K8s API server 動態發現</li>
<li>Consul SD：跟 Consul service registry 整合</li>
<li>對應配置：<code>scrape_configs</code> 區段</li>
</ul>
<h3 id="promql-查詢">PromQL 查詢</h3>
<p>子議題：</p>
<ul>
<li>Instant query vs range query</li>
<li>Aggregation：sum / avg / max / min / count + by / without</li>
<li>Rate / increase（counter 處理）</li>
<li>Histogram quantile（histogram_quantile + bucket）</li>
<li>對應指令：HTTP API <code>/api/v1/query</code></li>
</ul>
<h3 id="recording-rules--alerting-rules">Recording rules / Alerting rules</h3>
<p>子議題：</p>
<ul>
<li>Recording rules：預先計算昂貴 query、降低 dashboard 查詢成本</li>
<li>Alerting rules：定義 alert condition + for duration + labels / annotations</li>
<li>Alertmanager：去重 / 抑制 / 分組 / routing</li>
<li>對應配置：<code>rule_files</code></li>
</ul>
<h2 id="deep-article">Deep Article</h2>
<ul>
<li><a href="capacity-failure-modes/">Prometheus 容量規劃與故障模式</a>：單機容量邊界、cardinality 與 retention 的資源模型、常見故障模式與判讀</li>
<li><a href="promql-recording-rules/">PromQL 與 Recording Rules 實務</a>：常見 SLI 查詢模式、recording rules 設計慣例、效能陷阱與故障判讀</li>
<li><a href="remote-write-long-term-storage/">Remote Write 與長期儲存整合</a>：remote write 配置、Mimir / Thanos / Cortex 三家比較、故障模式與容量規劃</li>
</ul>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<h3 id="high-availability">High availability</h3>
<p>子議題：</p>
<ul>
<li>Prometheus 沒原生 HA — 跑兩個 instance scrape 同 target、靠下游去重</li>
<li>Thanos：sidecar 模式、跨 Prometheus instance 查詢統一</li>
<li>Mimir：fully replicated metric storage（多 Prometheus → Mimir）</li>
<li>對應案例 <a href="/blog/backend/04-observability/cases/airbnb-observability-k8s-scale-signals/" data-link-title="4.C8 Airbnb：Kubernetes 規模化下的觀測訊號治理" data-link-desc="叢集擴縮與工作負載變動如何回寫觀測模型。">4.C8 Airbnb K8s scale signals</a></li>
</ul>
<h3 id="cardinality-管理">Cardinality 管理</h3>
<p>對應案例 <a href="/blog/backend/04-observability/cases/gaming-peak-signal-freshness-and-cardinality/" data-link-title="Gaming：高峰流量下的訊號新鮮度與 Cardinality" data-link-desc="在高峰事件中控制訊號延遲與維度爆炸，維持告警與定位可信度。">4.C2 Gaming peak cardinality</a>。子議題：</p>
<ul>
<li>Cardinality = unique label combinations 數量</li>
<li>High-cardinality label（user_id / request_id / trace_id）會炸 Prometheus</li>
<li>偵測：<code>prometheus_tsdb_head_series</code> metric</li>
<li>修法：drop label / aggregation / 改用 traces backend（Honeycomb）</li>
</ul>
<h3 id="remote-write--read">Remote write / read</h3>
<p>子議題：</p>
<ul>
<li>Remote write：Prometheus → 長期儲存（Mimir / Cortex / Thanos / Datadog / Grafana Cloud）</li>
<li>Remote read：查詢時拉長期儲存資料</li>
<li>用 receiver / agent 模式（無 local TSDB）</li>
<li>對應配置：<code>remote_write</code> / <code>remote_read</code></li>
</ul>
<h3 id="exporters-生態">Exporters 生態</h3>
<p>子議題：</p>
<ul>
<li>Node exporter（host metrics）</li>
<li>Blackbox exporter（HTTP / TCP / ICMP probing）</li>
<li>Database exporters（postgres / mysql / redis）</li>
<li>應用層 metrics：用 client library（prometheus_client）原生暴露</li>
<li>對應 ServiceMonitor / PodMonitor（Prometheus Operator）</li>
</ul>
<h3 id="prometheus-operatork8s">Prometheus Operator（K8s）</h3>
<p>子議題：</p>
<ul>
<li>CRD：Prometheus / ServiceMonitor / PodMonitor / PrometheusRule / Alertmanager</li>
<li>自動發現 ServiceMonitor 物件、不手動改 scrape config</li>
<li>kube-prometheus-stack Helm chart</li>
<li>對應 <a href="/blog/backend/04-observability/cases/adot-eks-observability-pipeline-migration/" data-link-title="4.C6 AWS：ADOT on EKS 管線遷移" data-link-desc="從分散式 agent 組合轉成 OpenTelemetry collector 管線治理。">4.C6 ADOT EKS</a> 對照</li>
</ul>
<h3 id="pull-vs-push-model">Pull vs Push model</h3>
<p>子議題：</p>
<ul>
<li>Pull model（Prometheus default）：service discovery、health check 自然</li>
<li>Push model（Pushgateway）：適合 short-lived job、不建議常駐 service</li>
<li>為何 Pushgateway 不推：cardinality 不易管、scrape semantics 違反</li>
</ul>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<h3 id="scrape-failure">Scrape failure</h3>
<p>操作原則：先看 target 是否健康、再看 network 跟認證。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">curl -s http://localhost:9090/api/v1/targets <span class="p">|</span> jq <span class="s1">&#39;.data.activeTargets[] | {job: .labels.job, health, lastError}&#39;</span></span></span></code></pre></div><h3 id="cardinality-explosion">Cardinality explosion</h3>
<p>操作原則：series 數量持續增長、可能 OOM。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">curl -s <span class="s1">&#39;http://localhost:9090/api/v1/query?query=prometheus_tsdb_head_series&#39;</span> <span class="p">|</span> jq <span class="s1">&#39;.data.result[].value[1]&#39;</span></span></span></code></pre></div><p>對應 <a href="/blog/backend/04-observability/cases/gaming-peak-signal-freshness-and-cardinality/" data-link-title="Gaming：高峰流量下的訊號新鮮度與 Cardinality" data-link-desc="在高峰事件中控制訊號延遲與維度爆炸，維持告警與定位可信度。">4.C2 Gaming peak</a> 的處理路徑。</p>
<h3 id="query-過慢">Query 過慢</h3>
<p>操作原則：query 過大範圍 / aggregation 過多 → Recording rules 預先聚合。</p>
<h3 id="alert-flapping--noise">Alert flapping / noise</h3>
<p>操作原則：alert 觸發頻繁但無實際問題、調整 <code>for:</code> duration、加 absent() check、用 Alertmanager inhibition。</p>
<h3 id="memory-pressure">Memory pressure</h3>
<p>操作原則：Prometheus retention 跟 cardinality 決定 memory。判讀：cardinality 太大 → remote write 卸載長期儲存。</p>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>長期 retention（年級）</td>
          <td>Thanos / Mimir / Cortex / <a href="/blog/backend/04-observability/vendors/grafana-stack/" data-link-title="Grafana Stack" data-link-desc="Grafana / Loki / Tempo / Mimir / Pyroscope 全棧">Grafana Cloud</a></td>
      </tr>
      <tr>
          <td>需要 logs / traces</td>
          <td><a href="/blog/backend/04-observability/vendors/grafana-stack/" data-link-title="Grafana Stack" data-link-desc="Grafana / Loki / Tempo / Mimir / Pyroscope 全棧">Grafana Stack</a> (Loki/Tempo) / <a href="/blog/backend/04-observability/vendors/elastic-stack/" data-link-title="Elastic Stack" data-link-desc="ELK：Elasticsearch / Logstash / Kibana &#43; Beats / APM">Elastic</a></td>
      </tr>
      <tr>
          <td>Auto-instrumentation</td>
          <td><a href="/blog/backend/04-observability/vendors/opentelemetry/" data-link-title="OpenTelemetry" data-link-desc="可觀測性開放標準、SDK 與 Collector">OpenTelemetry</a> + Prometheus exporter</td>
      </tr>
      <tr>
          <td>SaaS turnkey</td>
          <td><a href="/blog/backend/04-observability/vendors/datadog/" data-link-title="Datadog" data-link-desc="All-in-one SaaS 觀測平台、APM / Logs / Metrics / RUM / Security">Datadog</a></td>
      </tr>
      <tr>
          <td>High-cardinality debug</td>
          <td><a href="/blog/backend/04-observability/vendors/honeycomb/" data-link-title="Honeycomb" data-link-desc="High-cardinality observability 平台、events-based 模型">Honeycomb</a></td>
      </tr>
      <tr>
          <td>AWS-native</td>
          <td><a href="/blog/backend/04-observability/vendors/aws-cloudwatch/" data-link-title="AWS CloudWatch" data-link-desc="AWS 原生觀測性服務、Logs / Metrics / Traces (X-Ray)">CloudWatch</a> + Managed Prometheus</td>
      </tr>
      <tr>
          <td>Pure push model</td>
          <td>StatsD / InfluxDB（不在本模組）</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>PromQL 完整 syntax reference（prometheus.io/docs/prometheus/latest/querying/）</li>
<li>Exporter 內部實作</li>
<li>Alertmanager routing tree 細節</li>
<li>Operator CRD spec</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<h3 id="直接相關案例">直接相關案例</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>主討論議題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/gaming-peak-signal-freshness-and-cardinality/" data-link-title="Gaming：高峰流量下的訊號新鮮度與 Cardinality" data-link-desc="在高峰事件中控制訊號延遲與維度爆炸，維持告警與定位可信度。">4.C2 Gaming peak cardinality</a></td>
          <td>Cardinality 管理 / freshness 取捨</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/adot-eks-observability-pipeline-migration/" data-link-title="4.C6 AWS：ADOT on EKS 管線遷移" data-link-desc="從分散式 agent 組合轉成 OpenTelemetry collector 管線治理。">4.C6 ADOT EKS</a></td>
          <td>AWS Distro + Prometheus 整合</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/airbnb-observability-k8s-scale-signals/" data-link-title="4.C8 Airbnb：Kubernetes 規模化下的觀測訊號治理" data-link-desc="叢集擴縮與工作負載變動如何回寫觀測模型。">4.C8 Airbnb K8s scale</a></td>
          <td>K8s metrics + Prometheus 規模化</td>
      </tr>
  </tbody>
</table>
<h3 id="跨-vendor-對照">跨 vendor 對照</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>對 Prometheus 的對應</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/datadog-otel-migration-practice/" data-link-title="4.C7 Datadog：OTel 相容遷移實務" data-link-desc="APM 採集從專有代理轉向 OTel 相容模式的治理案例。">4.C7 Datadog OTel migration</a></td>
          <td>從 Prometheus + Datadog 雙軌走向 OTel 對齊</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/failure-otel-migration-signal-drift/" data-link-title="4.C9 反例：OTel 遷移後訊號漂移" data-link-desc="雙軌採集未對齊導致告警與 SLO 判讀失真。">4.C9 OTel migration signal drift</a></td>
          <td>（反例）Prometheus 指標跟新管線的語意對不齊</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/contrast-observability-rollout-by-scale/" data-link-title="4.C10 對照：規模差異下的觀測遷移" data-link-desc="觀測遷移在不同規模團隊下的流程與風險差異。">4.C10 規模對照</a></td>
          <td>小型單 instance / 中型 Operator / 大型 + Mimir</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游概念：<a href="/blog/backend/04-observability/metrics-basics/" data-link-title="4.2 metrics 與 SLI/SLO" data-link-desc="整理 counter、gauge、histogram 與服務健康指標">Metrics Basics</a></li>
<li>平行 vendor：<a href="/blog/backend/04-observability/vendors/grafana-stack/" data-link-title="Grafana Stack" data-link-desc="Grafana / Loki / Tempo / Mimir / Pyroscope 全棧">Grafana Stack</a>（Mimir）、<a href="/blog/backend/04-observability/vendors/opentelemetry/" data-link-title="OpenTelemetry" data-link-desc="可觀測性開放標準、SDK 與 Collector">OpenTelemetry</a></li>
<li>下游能力：<a href="/blog/backend/04-observability/observability-evidence-package/" data-link-title="4.20 Observability Evidence Package" data-link-desc="把 log、metric、trace、audit 與資料品質限制包成可交接證據">4.20 Observability Evidence Package</a></li>
</ul>
]]></content:encoded></item><item><title>Valkey</title><link>https://tarrragon.github.io/blog/backend/02-cache-redis/vendors/valkey/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/02-cache-redis/vendors/valkey/</guid><description>&lt;p>Valkey 是 2024 年從 Redis 7.2.4 fork 的開源專案、承擔三個責任：維持 Redis API 相容（drop-in 替換）、提供 OSI 認可的開源授權（BSD 3-clause）、由 Linux Foundation 託管避免單一公司控制。設計取捨偏向「相容 Redis 既有 client / 工具 + 開源治理透明 + 多雲廠商共同維護」、不追求功能超越 Redis Inc。&lt;/p>
&lt;p>對「既有 Redis 部署、需要 OSI 認可授權、多雲避免 vendor lock-in、合規敏感」這條路徑、Valkey 是 Redis 的替代首選。AWS / Google / Oracle / Ericsson 等共同支援、AWS ElastiCache 已把 Valkey 設為 default engine。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>跑起 Valkey、用 redis-cli 驗證 API 相容性&lt;/li>
&lt;li>評估從 Redis 遷移到 Valkey 的相容性風險（module / Stack 功能）&lt;/li>
&lt;li>看懂 Valkey vs Redis Inc 的版本對應跟功能差距&lt;/li>
&lt;li>評估管雲端 managed Valkey（ElastiCache）的選用判斷&lt;/li>
&lt;li>區分 Valkey 跟 Redis 商業版本對你的合規 / 採購 / SLA 影響&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑5-分鐘把-valkey-跑起來">最短路徑：5 分鐘把 Valkey 跑起來&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 1. 啟動 Valkey（Redis API 相容、可直接用 redis-cli）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">docker run -d --name valkey -p 6379:6379 valkey/valkey:8
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="c1"># 2. 驗證讀寫（valkey-cli 與 redis-cli 命令一致）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">docker &lt;span class="nb">exec&lt;/span> valkey valkey-cli SET foo bar &lt;span class="c1"># → OK&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">docker &lt;span class="nb">exec&lt;/span> valkey valkey-cli GET foo &lt;span class="c1"># → bar&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="c1"># 3. 確認版本：Valkey 同時回報相容的 redis_version 與自身 valkey_version&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">docker &lt;span class="nb">exec&lt;/span> valkey valkey-cli INFO server &lt;span class="p">|&lt;/span> grep -E &lt;span class="s2">&amp;#34;redis_version|valkey_version|server_name&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="c1"># redis_version:7.2.4 ← client library 以此判斷相容性（fork 自 Redis 7.2.4）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">&lt;span class="c1"># server_name:valkey&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">&lt;span class="c1"># valkey_version:8.1.8 ← Valkey 自身版本&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>第三步是相容性的關鍵證據：既有 Redis client library 看到 &lt;code>redis_version:7.2.4&lt;/code> 就以 Redis 7.2.4 的行為運作、無需改 code；&lt;code>valkey_version&lt;/code> 才是 Valkey 自身的演進線。實機驗證於 valkey/valkey:8 image、最後檢查日 2026-06-16。實際遷移路徑見&lt;a href="#%e5%be%9e-redis-%e9%81%b7%e7%a7%bb">進階主題：從 Redis 遷移&lt;/a>。&lt;/p>
&lt;h2 id="日常操作與決策形狀">日常操作與決策形狀&lt;/h2>
&lt;h3 id="cli-與-client-api">CLI 與 client API&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>valkey-cli vs redis-cli：兩個 binary 都可連 Valkey、命令一致&lt;/li>
&lt;li>Client library 配置：所有 Redis client 自動相容（無需 Valkey-specific client）&lt;/li>
&lt;li>對應指令範例：&lt;code>INFO server&lt;/code> 顯示 valkey_version 而非 redis_version&lt;/li>
&lt;/ul>
&lt;h3 id="跟-redis-的相容邊界">跟 Redis 的相容邊界&lt;/h3>
&lt;p>子議題：&lt;/p></description><content:encoded><![CDATA[<p>Valkey 是 2024 年從 Redis 7.2.4 fork 的開源專案、承擔三個責任：維持 Redis API 相容（drop-in 替換）、提供 OSI 認可的開源授權（BSD 3-clause）、由 Linux Foundation 託管避免單一公司控制。設計取捨偏向「相容 Redis 既有 client / 工具 + 開源治理透明 + 多雲廠商共同維護」、不追求功能超越 Redis Inc。</p>
<p>對「既有 Redis 部署、需要 OSI 認可授權、多雲避免 vendor lock-in、合規敏感」這條路徑、Valkey 是 Redis 的替代首選。AWS / Google / Oracle / Ericsson 等共同支援、AWS ElastiCache 已把 Valkey 設為 default engine。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>跑起 Valkey、用 redis-cli 驗證 API 相容性</li>
<li>評估從 Redis 遷移到 Valkey 的相容性風險（module / Stack 功能）</li>
<li>看懂 Valkey vs Redis Inc 的版本對應跟功能差距</li>
<li>評估管雲端 managed Valkey（ElastiCache）的選用判斷</li>
<li>區分 Valkey 跟 Redis 商業版本對你的合規 / 採購 / SLA 影響</li>
</ol>
<h2 id="最短路徑5-分鐘把-valkey-跑起來">最短路徑：5 分鐘把 Valkey 跑起來</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># 1. 啟動 Valkey（Redis API 相容、可直接用 redis-cli）</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">docker run -d --name valkey -p 6379:6379 valkey/valkey:8
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c1"># 2. 驗證讀寫（valkey-cli 與 redis-cli 命令一致）</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">docker <span class="nb">exec</span> valkey valkey-cli SET foo bar   <span class="c1"># → OK</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">docker <span class="nb">exec</span> valkey valkey-cli GET foo       <span class="c1"># → bar</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="c1"># 3. 確認版本：Valkey 同時回報相容的 redis_version 與自身 valkey_version</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">docker <span class="nb">exec</span> valkey valkey-cli INFO server <span class="p">|</span> grep -E <span class="s2">&#34;redis_version|valkey_version|server_name&#34;</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="c1"># redis_version:7.2.4    ← client library 以此判斷相容性（fork 自 Redis 7.2.4）</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="c1"># server_name:valkey</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="c1"># valkey_version:8.1.8   ← Valkey 自身版本</span></span></span></code></pre></div><p>第三步是相容性的關鍵證據：既有 Redis client library 看到 <code>redis_version:7.2.4</code> 就以 Redis 7.2.4 的行為運作、無需改 code；<code>valkey_version</code> 才是 Valkey 自身的演進線。實機驗證於 valkey/valkey:8 image、最後檢查日 2026-06-16。實際遷移路徑見<a href="#%e5%be%9e-redis-%e9%81%b7%e7%a7%bb">進階主題：從 Redis 遷移</a>。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="cli-與-client-api">CLI 與 client API</h3>
<p>子議題：</p>
<ul>
<li>valkey-cli vs redis-cli：兩個 binary 都可連 Valkey、命令一致</li>
<li>Client library 配置：所有 Redis client 自動相容（無需 Valkey-specific client）</li>
<li>對應指令範例：<code>INFO server</code> 顯示 valkey_version 而非 redis_version</li>
</ul>
<h3 id="跟-redis-的相容邊界">跟 Redis 的相容邊界</h3>
<p>子議題：</p>
<ul>
<li>Core data types / commands：100% 相容（fork 自 Redis 7.2.4）</li>
<li>Eviction / persistence / cluster：相容</li>
<li>Pub/Sub / Streams：相容</li>
<li><strong>不相容</strong>：Redis 7.4+ 引入的功能、Redis Stack 商業 modules</li>
</ul>
<h3 id="遷移評估">遷移評估</h3>
<p>子議題：</p>
<ul>
<li>AOF / RDB 文件格式相容、可直接拷貝資料目錄</li>
<li>Client library 完全相容、無需改 code</li>
<li>監控工具相容（RedisInsight 雖偏 Redis Inc、但基本命令通用）</li>
<li>需確認 modules 使用狀況（Stack modules 未必有 Valkey fork）</li>
</ul>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<h3 id="從-redis-遷移">從 Redis 遷移</h3>
<p>子議題：</p>
<ul>
<li>評估 module 使用：列出當前使用的 Redis modules、確認 Valkey 對應替代</li>
<li>評估 Redis 7.4+ 功能使用（Functions、CLIENT NO-TOUCH 等）</li>
<li>遷移路徑：rolling restart with replica swap / 雙寫 / 直接 cutover</li>
<li>對應雲端 managed：AWS ElastiCache for Valkey 自動遷移工具</li>
</ul>
<h3 id="授權合規評估">授權合規評估</h3>
<p>子議題：</p>
<ul>
<li>為何 Redis 改 RSALv2 / SSPL — OSI 認知（不算 OSI 認可開源）</li>
<li>Valkey BSD 3-clause — 商業使用無限制</li>
<li>對 SaaS 供應商：Redis 限制把 Redis 當成 service 對外提供、Valkey 無此限制</li>
<li>對企業 / 公部門：開源合規政策可能要求 OSI 認可、Valkey 通過、Redis 不過</li>
</ul>
<h3 id="module-生態相容性">Module 生態相容性</h3>
<p>子議題：</p>
<ul>
<li>Valkey 計畫自有 modules（valkey-search / valkey-bloom 等）</li>
<li>Redis Stack modules（RedisJSON / RedisSearch）部分有 fork</li>
<li>評估你用的 modules 是否有 Valkey 替代、否則考慮遷 module-free 設計</li>
</ul>
<h3 id="雲端-managed-valkey">雲端 managed Valkey</h3>
<p>子議題：</p>
<ul>
<li>AWS ElastiCache for Valkey（成本比 Redis 低 ~20%、AWS 推）</li>
<li>GCP Memorystore（規劃 Valkey 支援）</li>
<li>Azure Cache（規劃中）</li>
<li>managed 邊界跟 ElastiCache for Redis 一致</li>
</ul>
<h3 id="跟-redis-8-的功能差距">跟 Redis 8 的功能差距</h3>
<p>子議題：</p>
<ul>
<li>Redis 8 新功能對 Valkey 的影響（功能落後幾個月）</li>
<li>Valkey 自有 roadmap（valkey.io/blog 追蹤）</li>
<li>何時 Redis 新功能值得遷回（罕見、通常 Valkey 跟上）</li>
</ul>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<h3 id="client-連不上api-相容問題">Client 連不上（API 相容問題）</h3>
<p>操作原則：先確認 Valkey 回報的相容版本、再對照 client library 支援到 Redis 哪個版本。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">valkey-cli INFO server <span class="p">|</span> grep -E <span class="s2">&#34;redis_version|valkey_version&#34;</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># redis_version:7.2.4    ← client library 用這個判斷相容性</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="c1"># valkey_version:8.1.8</span></span></span></code></pre></div><p>絕大多數情況直接相容、若失敗多是 client library 太舊（不支援 Redis 7.2 對應版本）。</p>
<h3 id="module-不可用">Module 不可用</h3>
<p>操作原則：Valkey 對 Redis Stack modules 不一定有 fork、看 Valkey modules 清單。</p>
<h3 id="監控工具相容性">監控工具相容性</h3>
<p>操作原則：RedisInsight 連 Valkey 可能 partial 工作（部分 vendor-specific 命令缺）、用通用工具（valkey-cli、Prometheus + redis_exporter）較穩。</p>
<h3 id="performance-regressionvs-redis">Performance regression（vs Redis）</h3>
<p>操作原則：Valkey 跟 Redis 7.2.4 為 baseline、效能應接近、差距 &lt; 5% 屬於正常。明顯回歸要看 Valkey roadmap 是否有 known issue。</p>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>依賴 Redis Stack 商業 modules</td>
          <td><a href="/blog/backend/02-cache-redis/vendors/redis/" data-link-title="Redis" data-link-desc="OSS in-memory data structure store、cache 主流">Redis</a>（Redis Inc 商業版）</td>
      </tr>
      <tr>
          <td>純 KV cache 不需 data types</td>
          <td><a href="/blog/backend/02-cache-redis/vendors/memcached/" data-link-title="Memcached" data-link-desc="純記憶體 key-value cache、無持久化">Memcached</a></td>
      </tr>
      <tr>
          <td>極高 throughput / 多核</td>
          <td><a href="/blog/backend/02-cache-redis/vendors/dragonflydb/" data-link-title="DragonflyDB" data-link-desc="高效能 Redis / Memcached 相容替代、多核架構">DragonflyDB</a></td>
      </tr>
      <tr>
          <td>AWS managed</td>
          <td><a href="/blog/backend/02-cache-redis/vendors/aws-elasticache/" data-link-title="AWS ElastiCache" data-link-desc="AWS managed Redis / Valkey / Memcached">AWS ElastiCache</a>（已 default Valkey）</td>
      </tr>
      <tr>
          <td>Durable Redis-compatible</td>
          <td>AWS MemoryDB</td>
      </tr>
      <tr>
          <td>跨雲 fully-portable</td>
          <td>Valkey self-host（無 vendor lock-in）</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>完整 Valkey command reference（valkey.io/commands）</li>
<li>Linux Foundation governance 細節</li>
<li>各語言 client compatibility matrix</li>
<li>Redis Stack module 對應替代清單</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<h3 id="直接相關案例沿用-redis-同源案例--待補-valkey-specific-case">直接相關案例（沿用 Redis 同源案例 + 待補 Valkey-specific case）</h3>
<p>Valkey 從 Redis 7.2.4 fork、API 與行為 100% 相容、Redis-on-Valkey 同源案例可直接套用。截至本文時 Valkey-specific production case 仍累積中。</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>對 Valkey 的對應</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/shopify-cache-serialization-migration/" data-link-title="2.C3 Shopify：快取序列化格式遷移" data-link-desc="快取 payload 從 Marshal 轉 MessagePack 的遷移策略。">2.C3 Shopify serialization</a></td>
          <td>Payload 雙軌遷移策略 client-side 實作、Valkey 跟 Redis 行為一致</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/shopify-write-through-cache-at-scale/" data-link-title="2.C5 Shopify：Write-through Cache 在高讀流量的實作" data-link-desc="read-heavy 服務如何轉向 write-through 快取模型。">2.C5 Shopify write-through</a></td>
          <td>Write-through 在 Valkey 上跟 Redis 同樣 API、無遷移風險</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/meta-cache-consistency-upgrade/" data-link-title="2.C1 Meta：Cache Consistency 升級" data-link-desc="快取 invalidation 一致性如何從常見錯誤演進到高可信治理。">2.C1 Meta cache consistency</a></td>
          <td>invalidation / shard move 一致性議題、Valkey Cluster 沿用 Redis Cluster 模型</td>
      </tr>
  </tbody>
</table>
<p><strong>待補 Valkey-specific 案例</strong>：Linux Foundation Valkey customer adoption stories、AWS ElastiCache for Valkey 客戶遷移個案、re:Invent 2025+ talks、企業 OSI 合規驅動的遷移路徑公開分享。</p>
<h3 id="跨-vendor-對照">跨 vendor 對照</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>對 Valkey 的對應</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/contrast-cache-strategy-by-scale/" data-link-title="2.C10 對照：規模差異下的快取策略" data-link-desc="同一快取策略在小中大型服務下會產生不同風險。">2.C10 規模對照</a></td>
          <td>Valkey 跟 Redis 規模化路徑一致（fork 同源）、小型 single / 中型 Sentinel / 大型 Cluster</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/failure-cache-stampede-rollout-regression/" data-link-title="2.C9 反例：快取切換引發 Stampede 回歸" data-link-desc="快取策略切換若缺乏保護，會導致回源壓力與錯誤率連鎖上升。">2.C9 Cache Stampede</a></td>
          <td>TTL jitter / singleflight 通用、Valkey 行為跟 Redis 一致</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/meta-mcrouter-global-cache-routing/" data-link-title="2.C2 Meta：mcrouter 與跨區快取路由" data-link-desc="快取從單點最佳化演進到分散式路由層的案例。">2.C2 Meta mcrouter</a></td>
          <td>Memcached routing 案例、Valkey 對應為 Cluster + client-side routing 或 Envoy Redis proxy</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/netflix-evcache-global-cache-layer/" data-link-title="2.C6 Netflix：EVCache 全域快取層" data-link-desc="快取從本地層演進為跨區分散式能力的案例。">2.C6 Netflix EVCache</a></td>
          <td>EVCache 為 Memcached based、Valkey 對應為 Global Datastore（ElastiCache for Valkey）</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游概念：<a href="/blog/backend/02-cache-redis/cache-aside/" data-link-title="2.2 cache aside 與失效策略" data-link-desc="整理 read-through 思路、cache miss 與 invalidation">2.2 Cache Aside</a></li>
<li>平行 vendor：<a href="/blog/backend/02-cache-redis/vendors/redis/" data-link-title="Redis" data-link-desc="OSS in-memory data structure store、cache 主流">Redis</a>（fork 源頭）、<a href="/blog/backend/02-cache-redis/vendors/aws-elasticache/" data-link-title="AWS ElastiCache" data-link-desc="AWS managed Redis / Valkey / Memcached">ElastiCache</a></li>
<li>下游能力：跟 Redis 完全一致、見 Redis vendor 頁的下游連結</li>
</ul>
]]></content:encoded></item><item><title>Datadog Security</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/datadog-security/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/datadog-security/</guid><description>&lt;p>Datadog Security 是 Datadog observability platform 上的 security 套件、跟 Datadog logs / metrics / APM / infrastructure 共用同一個 control plane 與 data plane。它的設計起點不是 SIEM、是 &lt;em>把資安訊號當成 observability 的一個維度&lt;/em>：alert 不只看 log、可以同時 pivot 到 APM trace、infra metrics 與 host context。這個定位決定了它的優勢（cloud-native + 混合 incident 偵測）與限制（SaaS-only + 計費隨 host 量線性漲、不適合 on-prem-heavy 或預算敏感場景）。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Datadog Security 由四個 product 構成、共用 Datadog Agent 與 backend：&lt;em>Cloud SIEM&lt;/em>（log-based detection、跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &amp;#43; indexer &amp;#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk Enterprise Security&lt;/a> 同類）、&lt;em>Cloud Security Management (CSM)&lt;/em> — 涵蓋 &lt;em>CSPM&lt;/em>（cloud config posture）與 &lt;em>Cloud Workload Security (CWS)&lt;/em>（container / Linux runtime via eBPF）、&lt;em>App and API Protection (AAP、前 ASM)&lt;/em> — RASP-style 在 app runtime 收 attack signal、&lt;em>Sensitive Data Scanner&lt;/em> — scan log 中的 PII / credential 並 redact。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &amp;#43; indexer &amp;#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk&lt;/a> 比、Datadog 走 &lt;em>observability-first + security 是 view&lt;/em>、Splunk 是 &lt;em>security-first&lt;/em>。Splunk 在 enterprise SOC tooling 深度（SOAR playbook、RBA、CIM data model）與跨 on-prem 部署上更成熟、Datadog SaaS-only 但跟 APM / Infra 同 plane、混合 incident（latency 異常是攻擊還是容量？）的判讀路徑更短。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &amp;#43; EDR &amp;#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security&lt;/a> 比、Elastic 可跨 on-prem + OSS、Datadog 只給 SaaS；Elastic 要自己整合 observability 訊號、Datadog 出廠就有。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/google-security-operations/" data-link-title="Google Security Operations" data-link-desc="Google 雲原生 SIEM &amp;#43; SOAR &amp;#43; Mandiant threat intel 三合一（前 Chronicle）、UDM &amp;#43; YARA-L、fixed-price by data tier、PB-scale 友善">Google Security Operations&lt;/a> 比、Google 走 &lt;em>fixed-price by data、PB-scale 划算&lt;/em>、Datadog 隨 host 線性漲、中等規模友善但破千 host 後 cost 曲線變陡。&lt;/p></description><content:encoded><![CDATA[<p>Datadog Security 是 Datadog observability platform 上的 security 套件、跟 Datadog logs / metrics / APM / infrastructure 共用同一個 control plane 與 data plane。它的設計起點不是 SIEM、是 <em>把資安訊號當成 observability 的一個維度</em>：alert 不只看 log、可以同時 pivot 到 APM trace、infra metrics 與 host context。這個定位決定了它的優勢（cloud-native + 混合 incident 偵測）與限制（SaaS-only + 計費隨 host 量線性漲、不適合 on-prem-heavy 或預算敏感場景）。</p>
<h2 id="服務定位">服務定位</h2>
<p>Datadog Security 由四個 product 構成、共用 Datadog Agent 與 backend：<em>Cloud SIEM</em>（log-based detection、跟 <a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk Enterprise Security</a> 同類）、<em>Cloud Security Management (CSM)</em> — 涵蓋 <em>CSPM</em>（cloud config posture）與 <em>Cloud Workload Security (CWS)</em>（container / Linux runtime via eBPF）、<em>App and API Protection (AAP、前 ASM)</em> — RASP-style 在 app runtime 收 attack signal、<em>Sensitive Data Scanner</em> — scan log 中的 PII / credential 並 redact。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> 比、Datadog 走 <em>observability-first + security 是 view</em>、Splunk 是 <em>security-first</em>。Splunk 在 enterprise SOC tooling 深度（SOAR playbook、RBA、CIM data model）與跨 on-prem 部署上更成熟、Datadog SaaS-only 但跟 APM / Infra 同 plane、混合 incident（latency 異常是攻擊還是容量？）的判讀路徑更短。跟 <a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a> 比、Elastic 可跨 on-prem + OSS、Datadog 只給 SaaS；Elastic 要自己整合 observability 訊號、Datadog 出廠就有。跟 <a href="/blog/backend/07-security-data-protection/vendors/google-security-operations/" data-link-title="Google Security Operations" data-link-desc="Google 雲原生 SIEM &#43; SOAR &#43; Mandiant threat intel 三合一（前 Chronicle）、UDM &#43; YARA-L、fixed-price by data tier、PB-scale 友善">Google Security Operations</a> 比、Google 走 <em>fixed-price by data、PB-scale 划算</em>、Datadog 隨 host 線性漲、中等規模友善但破千 host 後 cost 曲線變陡。</p>
<p>關鍵張力：<em>observability 與 security 同 plane</em> 是 Datadog 最大賣點、也是 cost 風險來源。host count 跟 events/month 同時是 observability 跟 security 的計費基準、security 加上去後 bill 不會獨立 — 預算要從 <em>整個 Datadog 帳單</em> 看、不是 security 單列。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>Datadog Security 在 SOC stack 中承擔哪一段（log SIEM / CSPM / 容器 runtime / WAF-runtime / log DLP）、哪些要外接（<a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a>、<a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a> IdP log、edge WAF）</li>
<li>observability + security 同 plane 的優勢何時成立、何時是 vendor lock-in 風險</li>
<li>Cloud SIEM 計費（events/month + indexed）跟 Standard / Flex Logs retention tier 的成本治理</li>
<li>何時用 Datadog、何時走 Splunk / Elastic / Google Security Ops 的取捨</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Datadog Security 部署是否健康、最少看四件事：</p>
<ul>
<li><strong>Datadog Agent coverage</strong>：agent 是否裝在所有 host / container / serverless wrapper、log forwarder 是否覆蓋 cloud control plane（AWS CloudTrail / GCP Audit Log / Azure Activity Log）、IdP（<a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a>）audit log 是否進來 — 缺一個就是 detection 盲點</li>
<li><strong>Detection rule ownership</strong>：Cloud SIEM rule 是用內建還是 custom、custom rule 是否走 Git 版控（Terraform <code>datadog_security_monitoring_rule</code>）、staging 環境是否 dry-run 24-48hr 才 promote production</li>
<li><strong>CSPM compliance check 治理</strong>：CIS / NIST / PCI baseline 開哪些、findings 是否進 ticket workflow、misconfig 修復 SLA 有沒有定義（critical 24hr、high 7d、medium 30d）</li>
<li><strong>Events/month + Indexed Log 預算</strong>：Cloud SIEM 按 events/month + indexed event 計費、新加 source 前是否估算 ingestion impact、Standard / Flex Logs retention tier 是否依 log priority 分流</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">Detection Coverage and Signal Governance</a> 邊界的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>Datadog Agent 採集</strong>：log / metrics / trace / security event 走同一個 Agent、用 integration（150+）抓 cloud / SaaS / database / queue。security event 跟 observability event 在後端用 <em>attribute tag</em>（<code>env</code>、<code>service</code>、<code>host</code>、<code>trace_id</code>）關聯、查 incident 時可以從 log alert pivot 到同 trace_id 的 APM trace 看 attack 發生的 application context。</p>
<p><strong>Cloud SIEM detection rule</strong>：rule 形式類似 SPL 的 query — <code>source:okta @evt.name:user.authentication.auth_via_mfa @outcome:failure</code> 加 <em>signal aggregation</em>（rolling window count、new value、anomaly detection、impossible travel）。內建 rule 跟 MITRE ATT&amp;CK 對應、跟 <a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk Security Content</a> 同類但 rule 數量較少；custom rule 走 Terraform provider 進版控、不在 UI 直改 production。</p>
<p><strong>CSPM compliance check</strong>：scan AWS / GCP / Azure 配置 vs CIS / NIST 800-53 / PCI / SOC 2 baseline、發現 misconfig（public S3 bucket、overly permissive IAM、不安全 SG rule）。跟 Wiz / Prisma Cloud 同類但跟 Datadog Infra 同 dashboard、findings 可以直接看到 affected resource 的 metrics / log。優勢是 <em>資安發現可以直接看業務影響</em>、限制是 graph-based attack path（Wiz 強項）不及專業 CNAPP。</p>
<p><strong>Cloud Workload Security（CWS）</strong>：用 Linux eBPF probe 在 kernel 層觀察 container / process behavior、偵測 cryptominer / privilege escalation / 異常 syscall / file integrity 變動。跟 <a href="https://falco.org/">Falco</a> 同類但跟 Datadog Infra 同 plane、CWS alert 可以直接 pivot 到該 container 的 CPU / memory / trace。Linux eBPF 對 kernel 版本敏感、舊 kernel 部份功能不可用、production 前要確認 fleet kernel matrix。</p>
<p><strong>App and API Protection（AAP）</strong>：RASP-style protection、Datadog APM library 在 application runtime 收 attack signal（SQLi / XSS / SSRF / 異常 traffic pattern）。跟 <a href="/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &#43; DDoS &#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF</a> / <a href="/blog/backend/07-security-data-protection/vendors/aws-waf/" data-link-title="AWS WAF" data-link-desc="AWS-internal WAF、跟 ALB / CloudFront / API Gateway 直接整合、Web ACL &#43; Managed Rule Group &#43; Rate-based Rule、Shield Standard 內含">AWS WAF</a> 不同層 — WAF 在 edge / CDN、AAP 在 app runtime 看到的是真實 request handler / DB query。兩者互補不互斥：edge WAF 擋 volumetric attack 跟已知 pattern、AAP 補 app-specific business logic abuse。</p>
<p><strong>Sensitive Data Scanner</strong>：scan ingest 進來的 log、用內建或 custom pattern 偵測 PII / credential / payment card / API key、發現後可以 redact、quarantine 或 alert。是 <em>DLP-lite</em> — 比不上 <a href="/blog/backend/07-security-data-protection/vendors/google-dlp/" data-link-title="Google DLP" data-link-desc="GCP 原生 Sensitive Data Protection：infoType discovery &#43; transformation (mask / FPE / tokenize / k-anonymity)、整合 BigQuery / GCS / Cloud SQL">Google DLP</a> / <a href="/blog/backend/07-security-data-protection/vendors/microsoft-purview/" data-link-title="Microsoft Purview" data-link-desc="Microsoft 跨 M365 / Azure / endpoint 的 data governance &#43; information protection &#43; DLP &#43; insider risk 統合平台、label-driven">Microsoft Purview</a> 的 sensitive data discovery / classification / lineage 全套、但對 <em>log 中誤洩 secret</em> 的場景夠用、是 detection signal source 也是 DLP 補位。</p>
<p><strong>Notebooks + Workflow Automation</strong>：Notebooks 是 incident investigation 用的 query workbook、混 log query + metric chart + APM trace + 註記、跟 <a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk Search</a> 比較像 Jupyter notebook 的 SOC 版。Workflow Automation 是輕量 SOAR、接 PagerDuty / Slack / Jira / Webhook / <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a> API、playbook 走 visual builder + Python。SOAR 深度不到 Splunk SOAR、但對中等規模 SOC（10-50 人）的常見 response 動作（rotate credential / block IP / open ticket）夠用。</p>
<p><strong>Standard Logs / Flex Logs + retention tier</strong>：log 進 Datadog 後分 <em>Indexed</em>（hot、可全文搜尋、貴）、<em>Flex Logs</em>（warm、retention 長、查詢延遲較高、cost 1/3-1/5）、<em>Archive</em>（cold、丟 S3 / GCS、純儲存）三層。Cloud SIEM detection 跑在 indexed log 上、所以 <em>哪些 log 走 indexed</em> 直接決定 detection coverage 跟 bill。tier 1 source（IdP / cloud control plane / payment）必 indexed、tier 2 source（app log）按 sampling、tier 3（debug）走 Flex 或 Archive。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Datadog Security</th>
          <th>Splunk</th>
          <th>Elastic Security</th>
          <th>Google Security Operations</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>設計起點</td>
          <td>Observability + security 同 plane</td>
          <td>Security-first、log 統一查詢平台</td>
          <td>Search-first、ELK stack 延伸</td>
          <td>Massive scale ingestion、Google threat intel</td>
      </tr>
      <tr>
          <td>計費模型</td>
          <td>Per-host + per-event（events/month）</td>
          <td>Ingestion-based（GB/day、累進）</td>
          <td>Resource-based（node / cluster）</td>
          <td>Fixed price by data tier（PB-scale 划算）</td>
      </tr>
      <tr>
          <td>部署模型</td>
          <td>SaaS only</td>
          <td>Self-hosted / SaaS</td>
          <td>Self-hosted / Cloud / Serverless</td>
          <td>SaaS only（Google Cloud）</td>
      </tr>
      <tr>
          <td>觀測整合</td>
          <td>Native — log + APM + metrics + infra 同 query</td>
          <td>需自接（Splunk Observability 另收）</td>
          <td>需自接（Elastic Observability 另開）</td>
          <td>弱 — 跨產品 federation</td>
      </tr>
      <tr>
          <td>雲端 posture (CSPM)</td>
          <td>內建（CSM）</td>
          <td>第三方 add-on / Cisco 整合</td>
          <td>第三方 / Wazuh</td>
          <td>第三方 / Mandiant 整合</td>
      </tr>
      <tr>
          <td>容器 runtime</td>
          <td>內建 CWS（eBPF）</td>
          <td>需 Falco / 第三方</td>
          <td>Elastic Defend</td>
          <td>需 Falco / 第三方</td>
      </tr>
      <tr>
          <td>App runtime（RASP）</td>
          <td>內建 AAP</td>
          <td>需第三方</td>
          <td>第三方</td>
          <td>第三方</td>
      </tr>
      <tr>
          <td>SOAR / Response</td>
          <td>Workflow Automation（輕量）</td>
          <td>Splunk SOAR（業界先驅）</td>
          <td>Cases + Endpoint response</td>
          <td>SOAR 內建（前 Siemplify）</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>Cloud-native + 已用 Datadog + 中等規模 SOC</td>
          <td>Enterprise + 跨 on-prem、預算允許</td>
          <td>OSS-friendly、Elastic stack 已用</td>
          <td>超大規模 ingestion、Google 雲</td>
      </tr>
  </tbody>
</table>
<p>選 Datadog 的核心訴求：<em>已經用 Datadog observability、cloud-native 為主、SOC 規模中等（10-50 人）、需要 observability + security 同 plane 的 incident 判讀路徑</em>。on-prem 為主、預算敏感（host 量 1000+）、需要 enterprise SOAR / RBA 深度、走 Splunk；OSS-friendly、跨 on-prem、走 Elastic。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Cross-product correlation（log + APM + metrics 同 trace_id）</strong>：Datadog 最特別的偵測形狀 — security alert 不只 log line、而是綁 trace_id 的 <em>integrated incident view</em>。例如 API endpoint 出現 SQLi 嘗試、Cloud SIEM 開 signal、同時 APM 看到該 request 的 DB query 跟 latency、infra 看到該 host 的 CPU。對「query latency 異常是不是被攻擊」這種混合 incident 偵測有結構性優勢、跟 <a href="/blog/backend/07-security-data-protection/red-team/cases/data-exfiltration/snowflake-2024-credential-abuse/" data-link-title="7.R7.4.2 Snowflake 2024：憑證濫用與資料竊取" data-link-desc="外洩憑證與 MFA 缺口如何在資料平台形成高風險外送事件">Snowflake 2024 Credential Abuse</a> 的調查路徑直接對應。</p>
<p><strong>CWS Linux eBPF 行為偵測</strong>：eBPF probe 在 kernel 層、不需要 kernel module、不影響 process performance（&lt; 1% overhead）。可以偵測的行為包括 file integrity（<code>/etc/passwd</code> 被改）、process tree（<code>bash → curl → /tmp/payload</code> 異常 chain）、network connection（容器對外連 cryptominer pool）、syscall pattern（<code>ptrace</code> 用於 process injection）。跟 <a href="https://falco.org/">Falco</a> 同樣用 eBPF、差別是 Datadog CWS 不需要單獨部署 + 跟 Datadog 其他 signal 同 plane。</p>
<p><strong>Datadog Threat Intelligence</strong>：內建 threat feed（malicious IP / domain / file hash）、自動標記 log / network event 命中 IoC。可以加自家 STIX/TAXII feed、不過深度比不上 <a href="https://www.mandiant.com/">Mandiant</a> / Recorded Future / 專業 TI platform；中等規模 SOC 夠用、嚴重 APT 對抗場景要外接專業 TI。</p>
<p><strong>跟 Datadog Incident Management 整合</strong>：security signal 可以直接開 Datadog Incident（內建 incident channel + timeline + post-mortem template）、跟 <a href="/blog/backend/08-incident-response/vendors/pagerduty/" data-link-title="PagerDuty" data-link-desc="On-call / alerting 主流 SaaS、IR 平台演化">PagerDuty</a> 同類但跟 observability 同 plane。對 <em>資安事件升級成全公司 incident</em> 的場景（<a href="/blog/backend/07-security-data-protection/red-team/cases/data-exfiltration/change-healthcare-2024-ops-impact/" data-link-title="7.R7.4.3 Change Healthcare 2024：資料事件轉為營運中斷" data-link-desc="醫療支付中樞事件如何同時衝擊資料安全與業務連續性">Change Healthcare 2024 Operations Impact</a> 那種規模）可以共用 incident commander 視角、不用兩套 timeline 拼起來。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Cloud SIEM 偵測 lag / 沒 alert</strong>：events 沒進 indexed log（走了 Flex）、retention tier 設錯 — 檢查 log pipeline rule 是否把 security-critical source 標 indexed</li>
<li><strong>Events/month 暴衝</strong>：debug log / verbose log 進 Cloud SIEM index、CWS event 量爆 — log pipeline 前置 filter（Datadog Observability Pipeline 或 Cribl）、CWS rule 收斂 noisy 行為</li>
<li><strong>CSPM findings 100+ 沒人修</strong>：findings 沒進 ticket workflow、沒分 priority — 整合 Jira / ServiceNow、severity 對應 SLA、findings 老化超 30 天升級</li>
<li><strong>CWS 在舊 kernel host 沒資料</strong>：eBPF feature 對 kernel 版本敏感（&lt; 4.18 部份功能不支援）— 升級 kernel 或標記該 host 為 CWS-incompatible、補位用 host-based agent</li>
<li><strong>AAP false positive 卡 user</strong>：RASP 在 app runtime 直接 block、誤殺正常 request — AAP 先走 monitor mode 1-2 週收 baseline、tune 後再轉 protect mode</li>
<li><strong>Sensitive Data Scanner miss PII</strong>：custom pattern 沒寫對、log format 嵌套（JSON 內又是 JSON）— 用 sample log 跑 dry-run、scanner 跑在 ingest 階段不是 retroactive</li>
<li><strong>Workflow Automation playbook 黑箱</strong>：自動 rotate credential 結果誤殺 prod service account — playbook high-impact action 走 approval gate、default 走 containment 不走 deletion</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Enterprise + 跨 on-prem、預算允許</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a></td>
      </tr>
      <tr>
          <td>OSS-friendly / Elastic stack 已用</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a></td>
      </tr>
      <tr>
          <td>超大規模 ingestion + Google 雲</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/google-security-operations/" data-link-title="Google Security Operations" data-link-desc="Google 雲原生 SIEM &#43; SOAR &#43; Mandiant threat intel 三合一（前 Chronicle）、UDM &#43; YARA-L、fixed-price by data tier、PB-scale 友善">Google Security Operations</a></td>
      </tr>
      <tr>
          <td>嚴格 DLP / 資料分類</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/google-dlp/" data-link-title="Google DLP" data-link-desc="GCP 原生 Sensitive Data Protection：infoType discovery &#43; transformation (mask / FPE / tokenize / k-anonymity)、整合 BigQuery / GCS / Cloud SQL">Google DLP</a> / <a href="/blog/backend/07-security-data-protection/vendors/microsoft-purview/" data-link-title="Microsoft Purview" data-link-desc="Microsoft 跨 M365 / Azure / endpoint 的 data governance &#43; information protection &#43; DLP &#43; insider risk 統合平台、label-driven">Microsoft Purview</a></td>
      </tr>
      <tr>
          <td>Cloud posture graph / attack path</td>
          <td>Wiz / Prisma Cloud / Lacework</td>
      </tr>
      <tr>
          <td>Edge WAF / volumetric attack</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &#43; DDoS &#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF</a> / <a href="/blog/backend/07-security-data-protection/vendors/aws-waf/" data-link-title="AWS WAF" data-link-desc="AWS-internal WAF、跟 ALB / CloudFront / API Gateway 直接整合、Web ACL &#43; Managed Rule Group &#43; Rate-based Rule、Shield Standard 內含">AWS WAF</a></td>
      </tr>
      <tr>
          <td>Endpoint EDR</td>
          <td>CrowdStrike Falcon / Microsoft Defender for Endpoint</td>
      </tr>
      <tr>
          <td>Incident routing</td>
          <td><a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Datadog Agent 完整 configuration reference、custom check 撰寫</li>
<li>Datadog observability（APM / RUM / Synthetics / DBM）細節 — 屬 <a href="/blog/backend/04-observability/" data-link-title="模組四：可觀測性平台" data-link-desc="整理 log、metric、trace、dashboard 與 alert 的後端操作實務">4 observability</a> 模組</li>
<li>Cloud SIEM rule 完整語法 reference</li>
<li>CWS eBPF probe 撰寫（custom rule via Agent Expression Language）細節</li>
<li>Datadog Incident Management workflow（屬 <a href="/blog/backend/08-incident-response/" data-link-title="模組八：事故處理與復盤" data-link-desc="用 IR 領域詞彙建問題節點、以服務級案例庫累積事故脈絡，先建概念與案例庫再進實作交接">8 IR</a> 模組）</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>Datadog Security 在 07 案例庫沒有直接 vendor-level 事件、但 observability + security 同 plane 的偵測形狀讓部份案例的調查路徑變短、值得對照：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 Datadog Security 的關係（對照啟示）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/data-exfiltration/snowflake-2024-credential-abuse/" data-link-title="7.R7.4.2 Snowflake 2024：憑證濫用與資料竊取" data-link-desc="外洩憑證與 MFA 缺口如何在資料平台形成高風險外送事件">Snowflake 2024 Credential Abuse</a></td>
          <td>Query volume + 連接數 + CPU 負載異常是 Datadog 同 plane 的強項、Cloud SIEM rule + DBM metrics 同 query 不用 SIEM + 監控工具拼接</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/data-exfiltration/change-healthcare-2024-ops-impact/" data-link-title="7.R7.4.3 Change Healthcare 2024：資料事件轉為營運中斷" data-link-desc="醫療支付中樞事件如何同時衝擊資料安全與業務連續性">Change Healthcare 2024 Operations Impact</a></td>
          <td>業務中樞事件的影響評估、APM + Infra 可秒級判斷 latency 異常源自資安 vs 容量、Datadog Incident 共用 IC 視角</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/data-exfiltration/mailchimp-2023-support-tool-abuse/" data-link-title="7.R7.4.4 Mailchimp 2023：支援工具路徑與客戶資料風險" data-link-desc="社交工程進入客服工具後，如何形成特定客戶資料存取風險">Mailchimp 2023 Support Tool Abuse</a></td>
          <td>APM span correlation 可看到單一 operator 短時間跨多 tenant access 的 trace pattern、log-only SIEM 看不到 application-level tenant 切換</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/uber-2022-mfa-fatigue/" data-link-title="7.R7.1.1 Uber 2022：MFA 疲勞與內部工具擴散" data-link-desc="從社交工程到內部工具存取，拆解身分流程與權限邊界的失效點">Uber 2022 MFA Fatigue</a></td>
          <td>Cloud SIEM detection rule 配 <a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a> MFA log + APM error rate correlation、不靠單一 log source</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">Detection Coverage and Signal Governance (section)</a></td>
          <td>Standard / Flex Logs + retention tier 是 detection coverage 治理的工具、tier 1 source 必 indexed、tier 2 / 3 走 Flex / Archive</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">7.13 偵測覆蓋率與訊號治理</a>、<a href="/blog/backend/07-security-data-protection/blue-team/detection-engineering-lifecycle/" data-link-title="7.B5 Detection Engineering Lifecycle" data-link-desc="把偵測規則視為可維護資產，建立從來源、測試、調校到退場的完整生命週期">Detection Engineering Lifecycle</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a>、<a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a>、<a href="/blog/backend/07-security-data-protection/vendors/google-security-operations/" data-link-title="Google Security Operations" data-link-desc="Google 雲原生 SIEM &#43; SOAR &#43; Mandiant threat intel 三合一（前 Chronicle）、UDM &#43; YARA-L、fixed-price by data tier、PB-scale 友善">Google Security Operations</a></li>
<li>下游：<a href="/blog/backend/07-security-data-protection/vendors/google-dlp/" data-link-title="Google DLP" data-link-desc="GCP 原生 Sensitive Data Protection：infoType discovery &#43; transformation (mask / FPE / tokenize / k-anonymity)、整合 BigQuery / GCS / Cloud SQL">Google DLP</a> / <a href="/blog/backend/07-security-data-protection/vendors/microsoft-purview/" data-link-title="Microsoft Purview" data-link-desc="Microsoft 跨 M365 / Azure / endpoint 的 data governance &#43; information protection &#43; DLP &#43; insider risk 統合平台、label-driven">Microsoft Purview</a>（DLP signal 進 Datadog）</li>
<li>跨類：<a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a>（IdP log source）、<a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a>（Workflow Automation 拉 API）、<a href="/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &#43; DDoS &#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF</a> / <a href="/blog/backend/07-security-data-protection/vendors/aws-waf/" data-link-title="AWS WAF" data-link-desc="AWS-internal WAF、跟 ALB / CloudFront / API Gateway 直接整合、Web ACL &#43; Managed Rule Group &#43; Rate-based Rule、Shield Standard 內含">AWS WAF</a>（edge WAF log 進 Cloud SIEM、AAP 在 app 層補位）</li>
<li>跨模組：<a href="/blog/backend/04-observability/" data-link-title="模組四：可觀測性平台" data-link-desc="整理 log、metric、trace、dashboard 與 alert 的後端操作實務">4 observability</a>（同 Agent / 同 plane）、<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（Datadog Incident → IR routing）</li>
<li>官方：<a href="https://docs.datadoghq.com/security/">Datadog Security Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>Fastly Next-Gen WAF</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/fastly-ngwaf/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/fastly-ngwaf/</guid><description>&lt;p>Fastly Next-Gen WAF（NG-WAF）的核心定位是 &lt;em>用語意分析 + behavioral detection 取代 regex signature&lt;/em> 的 web application firewall。它前身是 2020 年被 Fastly 收購的 Signal Sciences、跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &amp;#43; DDoS &amp;#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-waf/" data-link-title="AWS WAF" data-link-desc="AWS-internal WAF、跟 ALB / CloudFront / API Gateway 直接整合、Web ACL &amp;#43; Managed Rule Group &amp;#43; Rate-based Rule、Shield Standard 內含">AWS WAF&lt;/a> 的根本差異不在覆蓋面、在 &lt;em>偵測 mindset&lt;/em> — 不靠 pattern 比對、靠解析請求語意（這段內容像不像 SQL、像不像 shell command）跟跨請求行為模式（同一 token 在多 endpoint 連續觸發異常）下判斷。產出是 &lt;em>低 false positive 的 inline block 模式可以直接上 production&lt;/em>、不需要先養 Log Mode 兩週、不需要 SOC 全職人員跟 rule 戰。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Fastly NG-WAF 設計的第一順位是 &lt;em>production 可直接走 Block 模式&lt;/em>。Signature WAF 的成本不在 rule 本身、在 false positive — 一條 SQLi pattern 可能誤判合法 SQL-like 字串（搜尋查詢、CSV 上傳）、production 開 Block 立刻炸合法流量、所以多數 signature WAF 跑在 &lt;em>Detect / Log Only&lt;/em> 模式、攔不下真正攻擊。Fastly NG-WAF 走 &lt;em>Signal&lt;/em> 模型：每個請求被解析後標記若干 Signal（SQLi、XSS、CMDI、Traversal、Anomaly 等）、再依 &lt;em>threshold-based rule&lt;/em>（N 個 Signal 在 M 秒內聚集）才動作 — false positive 自然降低、Block 模式可開。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &amp;#43; DDoS &amp;#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF&lt;/a> 的對照：Cloudflare 走 signature + managed rule + ML 三層、覆蓋廣但需要 sensitivity tuning；Fastly NG-WAF 預設低 FP 但需要 &lt;em>客戶自己定義業務語意&lt;/em>（哪些 path 是 admin、哪些 header 不該出現、哪些 anomaly 對自家業務代表攻擊）— 用 &lt;em>Tag&lt;/em> + &lt;em>Match Conditions&lt;/em> 表達。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-waf/" data-link-title="AWS WAF" data-link-desc="AWS-internal WAF、跟 ALB / CloudFront / API Gateway 直接整合、Web ACL &amp;#43; Managed Rule Group &amp;#43; Rate-based Rule、Shield Standard 內含">AWS WAF&lt;/a> 的對照：AWS WAF 跟 ALB / CloudFront / API Gateway 整合深、跨雲弱；Fastly NG-WAF 部署模型多樣（Edge / Agent / Cloud）、跨 AWS / GCP / on-prem / K8s 一致。&lt;/p></description><content:encoded><![CDATA[<p>Fastly Next-Gen WAF（NG-WAF）的核心定位是 <em>用語意分析 + behavioral detection 取代 regex signature</em> 的 web application firewall。它前身是 2020 年被 Fastly 收購的 Signal Sciences、跟 <a href="/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &#43; DDoS &#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF</a> / <a href="/blog/backend/07-security-data-protection/vendors/aws-waf/" data-link-title="AWS WAF" data-link-desc="AWS-internal WAF、跟 ALB / CloudFront / API Gateway 直接整合、Web ACL &#43; Managed Rule Group &#43; Rate-based Rule、Shield Standard 內含">AWS WAF</a> 的根本差異不在覆蓋面、在 <em>偵測 mindset</em> — 不靠 pattern 比對、靠解析請求語意（這段內容像不像 SQL、像不像 shell command）跟跨請求行為模式（同一 token 在多 endpoint 連續觸發異常）下判斷。產出是 <em>低 false positive 的 inline block 模式可以直接上 production</em>、不需要先養 Log Mode 兩週、不需要 SOC 全職人員跟 rule 戰。</p>
<h2 id="服務定位">服務定位</h2>
<p>Fastly NG-WAF 設計的第一順位是 <em>production 可直接走 Block 模式</em>。Signature WAF 的成本不在 rule 本身、在 false positive — 一條 SQLi pattern 可能誤判合法 SQL-like 字串（搜尋查詢、CSV 上傳）、production 開 Block 立刻炸合法流量、所以多數 signature WAF 跑在 <em>Detect / Log Only</em> 模式、攔不下真正攻擊。Fastly NG-WAF 走 <em>Signal</em> 模型：每個請求被解析後標記若干 Signal（SQLi、XSS、CMDI、Traversal、Anomaly 等）、再依 <em>threshold-based rule</em>（N 個 Signal 在 M 秒內聚集）才動作 — false positive 自然降低、Block 模式可開。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &#43; DDoS &#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF</a> 的對照：Cloudflare 走 signature + managed rule + ML 三層、覆蓋廣但需要 sensitivity tuning；Fastly NG-WAF 預設低 FP 但需要 <em>客戶自己定義業務語意</em>（哪些 path 是 admin、哪些 header 不該出現、哪些 anomaly 對自家業務代表攻擊）— 用 <em>Tag</em> + <em>Match Conditions</em> 表達。跟 <a href="/blog/backend/07-security-data-protection/vendors/aws-waf/" data-link-title="AWS WAF" data-link-desc="AWS-internal WAF、跟 ALB / CloudFront / API Gateway 直接整合、Web ACL &#43; Managed Rule Group &#43; Rate-based Rule、Shield Standard 內含">AWS WAF</a> 的對照：AWS WAF 跟 ALB / CloudFront / API Gateway 整合深、跨雲弱；Fastly NG-WAF 部署模型多樣（Edge / Agent / Cloud）、跨 AWS / GCP / on-prem / K8s 一致。</p>
<p>關鍵張力：低 FP 的 <em>代價</em> 是要花時間理解自家業務語意。Signature WAF 是「裝上就有保護」、Fastly NG-WAF 是「裝上有 baseline、業務 anomaly 要自己標」。沒有人定義 Tag + Power Rules、就只用到產品 30% 能力。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>Fastly NG-WAF 的 Signal / Tag / Rule / Mode 四個核心 first-class concept 各承擔什麼責任</li>
<li>Edge / Agent + Module / Cloud Proxy 三種部署模型的選擇條件</li>
<li>Account Takeover Protection、Bot Protection、API discovery 三個進階 module 的適用情境</li>
<li>何時用 Fastly NG-WAF、何時走 <a href="/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &#43; DDoS &#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF</a> / <a href="/blog/backend/07-security-data-protection/vendors/aws-waf/" data-link-title="AWS WAF" data-link-desc="AWS-internal WAF、跟 ALB / CloudFront / API Gateway 直接整合、Web ACL &#43; Managed Rule Group &#43; Rate-based Rule、Shield Standard 內含">AWS WAF</a> 的取捨</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Fastly NG-WAF 配置是否健康、最少看四件事：</p>
<ul>
<li><strong>部署模型對齊架構</strong>：Fastly Edge inline（流量本來就過 Fastly CDN）/ Agent + Module（自管 Nginx / Apache / IIS / Envoy / .NET 加 sigsci-agent local process）/ Cloud Proxy（Fastly 接 origin proxy）三選一或混用、是否覆蓋所有入口（含 admin、internal API、staging）</li>
<li><strong>Signal 與 Tag 設計</strong>：預設 Signal（SQLi / XSS / CMDI / Traversal / Backdoor / Anomaly）是否全開、業務語意 Tag（admin-path、internal-only、payment-flow）是否定義並掛上 Match Conditions、Power Rules 是否組合多 Signal / Tag 走 threshold-based action</li>
<li><strong>Rule mode 與 threshold</strong>：Site-level 跟 Corp-level Rule 是 Block 還是 Off、threshold（連續幾個 Signal / 多久窗口）是否依 endpoint 業務調整、Template Rule（ATO、Bot）是否啟用</li>
<li><strong>Logging 與 sigsci-agent token 治理</strong>：Syslog / HTTP webhook / S3 / SIEM（Splunk / Datadog / Sumo Logic）整合是否 production-grade、sigsci-agent 連回控制面的 token 是否進 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a>、跨環境 token 是否分離</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">Audit Log</a> 與 <a href="/blog/backend/07-security-data-protection/entrypoint-and-server-protection/" data-link-title="7.3 入口治理與伺服器防護" data-link-desc="以問題驅動方式整理對外入口、管理平面與伺服器邊界">Entry Point Protection</a> 邊界的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>部署模型選擇</strong>：<em>Fastly Edge inline</em> 是最簡部署、流量已過 Fastly CDN 就 inline 加 NG-WAF、沒有額外 agent 要管；<em>Agent + Module</em> 是 self-managed Nginx / Apache / IIS / Envoy / HAProxy / .NET / Java（Tomcat）等加裝 sigsci-module（process 內 module 攔請求）+ sigsci-agent（本機 daemon、跟 Fastly 控制面 sync rule、collect event）— 適合 origin 不過 Fastly CDN、或 internal API；<em>Cloud Proxy</em> 是 Fastly 提供 reverse proxy 端點、客戶 DNS 指過去、origin 在後面 — 適合不想改 origin、又沒用 Fastly CDN。三種混用常見、大企業 edge 用 Fastly Edge、internal service 用 Agent + Module。</p>
<p><strong>Signal 是已知攻擊指標</strong>：Fastly NG-WAF 預定義 Signal 包含 <em>SQLi / XSS / CMDI（command injection）/ Traversal（路徑穿越）/ Backdoor / RCE / Anomaly</em> 等。Signal 是 <em>語意解析結果</em> — request body 被 parser 拆解（JSON / form / multipart）、每個欄位看「這像不像某類攻擊」、不是 regex 比對。意義是 <em>encoding 變化攔不住</em>（base64 / URL encode / Unicode normalize 都會被解開）、跟 signature WAF 的脆性對比明顯。</p>
<p><strong>Tag 是客戶自定 Signal</strong>：用 <em>Match Conditions</em>（path / method / IP / header / body content / query 參數）定義「什麼樣的請求叫某 tag」、例：<code>Path: /admin/* AND Source IP NOT IN internal_cidr → tag: admin-external-access</code>。Tag 之後可以走 Rule 處理（看到 admin-external-access 就 alert / block）。Tag 是 Fastly NG-WAF 表達 <em>業務語意</em> 的主要工具、不是用來補強 Signal。</p>
<p><strong>Rule 三層</strong>：<em>Site-level Rule</em>（單一 site / property）/ <em>Corp-level Rule</em>（整個 organization 共用、用於 corp-wide block list、跨 BU 統一 policy）/ <em>Template Rule</em>（Fastly 提供的預設複合 rule、如 ATO template、Bot template）。Rule 表達式組合 Signal / Tag / Source IP / Path / Method、走 Block / Off。Power Rules 是進階版 — 支援 <em>threshold</em> + <em>時間窗口</em> + <em>多條件 AND/OR</em>、例：「同 IP 在 60 秒內觸發 5 個 SQLi Signal 就 Block 10 分鐘」。</p>
<p><strong>Mode 兩種</strong>：<em>Block</em>（攔截、回 406 / 自訂 status）/ <em>Off</em>（不動作、純 log）。沒有 Cloudflare 的 Sensitivity 滑桿 — 因為 Signal 本身已是語意判讀結果、不需要敏感度調整、調整在 <em>threshold</em>（多少 Signal 才動作）。</p>
<p><strong>Account Takeover Protection（ATO）</strong>：偵測 credential stuffing pattern — 同 IP 多 login fail、跨 IP 同 account 多 login、impossible travel、unusual UA。Fastly NG-WAF 內建 <em>login endpoint detection</em>（自動 / 手動標記 <code>/login</code>、<code>/auth/signin</code> 等）、配合 ATO Template Rule 直接 inline 處理（rate limit、challenge、block）。對應 <a href="/blog/backend/07-security-data-protection/identity-access-boundary/" data-link-title="7.2 身分與授權邊界" data-link-desc="以問題驅動方式整理身分、授權、會話與供應商身分鏈">Identity Boundary</a> 的 ATO 對策、但是在 WAF 層直接攔、不等 IdP 內 ATO 邏輯。</p>
<p><strong>Bot Protection</strong>：跟 Cloudflare Bot Management 同類、走 behavioral + browser fingerprint + JS challenge、區分 verified bot / likely bot / human。比 user-agent 過濾穩、headless browser 攔得住。</p>
<p><strong>API discovery</strong>：Fastly NG-WAF 自動學習 site 的 API endpoint 與 schema、偵測 <em>schema drift</em>（突然出現的多餘欄位、缺欄位、type mismatch）— 比手動維護 OpenAPI schema 輕量、適合內部 API 多但沒寫完整 OpenAPI 的團隊。</p>
<p><strong>Logging 與 sigsci-agent 治理</strong>：所有 event 走 Fastly NG-WAF 控制面 + 客戶端 Syslog / HTTP webhook / S3 / SIEM（Splunk / Datadog / Sumo Logic）。sigsci-agent 連回控制面用 <em>Site API key</em> — 該 key 進 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a>、跨環境 prod / staging 分離、rotation 走標準 secret rotation 流程、不能寫死在 agent 配置檔。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Fastly Next-Gen WAF</th>
          <th>Cloudflare WAF</th>
          <th>AWS WAF</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>偵測模型</td>
          <td>Signal / 語意分析 / behavioral（低 FP）</td>
          <td>Signature + Managed Rule + ML</td>
          <td>Signature + Managed Rule + Lambda 自訂</td>
      </tr>
      <tr>
          <td>部署位置</td>
          <td>Fastly Edge / Agent + Module / Cloud Proxy</td>
          <td>Cloudflare global edge</td>
          <td>AWS region 內 ALB / CloudFront / API Gateway 前</td>
      </tr>
      <tr>
          <td>Block 模式可行性</td>
          <td>高 — 預設低 FP、production 可直開</td>
          <td>中 — 需 sensitivity tuning + Log Mode 觀察</td>
          <td>中 — managed rule FP 需排除、custom rule 自管</td>
      </tr>
      <tr>
          <td>業務語意表達</td>
          <td>Tag + Match Conditions + Power Rules（threshold）</td>
          <td>Custom Rule（Rules language）+ Bot Score</td>
          <td>JSON policy + Lambda 自訂</td>
      </tr>
      <tr>
          <td>自管伺服器支援</td>
          <td>強 — sigsci-agent + module 覆蓋 Nginx / Apache / IIS</td>
          <td>弱 — 必須流量過 Cloudflare edge</td>
          <td>弱 — 必須走 AWS service</td>
      </tr>
      <tr>
          <td>ATO 內建</td>
          <td>是 — Template Rule 直接 inline</td>
          <td>Exposed Credentials Check（部分覆蓋）</td>
          <td>AWS WAF Fraud Control（加價）</td>
      </tr>
      <tr>
          <td>Bot Protection</td>
          <td>內建（同層產品）</td>
          <td>加價 add-on（Pro / Business / Enterprise）</td>
          <td>AWS WAF Bot Control（加價）</td>
      </tr>
      <tr>
          <td>API discovery</td>
          <td>內建（auto schema learning）</td>
          <td>API Shield（Enterprise）</td>
          <td>API Gateway request validator</td>
      </tr>
      <tr>
          <td>學習曲線</td>
          <td>中 — Signal / Tag mindset 要轉、agent 安裝要熟</td>
          <td>中 — UI 易上手、Rules language 表達力強</td>
          <td>較陡 — JSON policy + 多 AWS service 整合</td>
      </tr>
      <tr>
          <td>價格</td>
          <td>較高 — Enterprise tier 為主、按請求量計</td>
          <td>分層（Free / Pro / Business / Enterprise）</td>
          <td>按 rule + request 量、起步低</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>低 FP 要求、API 重、自管伺服器多、跨雲 / on-prem</td>
          <td>多雲 / on-prem origin、要整套 edge security suite</td>
          <td>AWS-heavy、ALB / CloudFront / API Gateway 是主入口</td>
      </tr>
  </tbody>
</table>
<p>選 Fastly NG-WAF 的核心訴求：<em>production 直接 Block</em> + <em>API / schema-rich 業務</em> + <em>自管伺服器需要 inline agent</em> + <em>跨雲 / on-prem mix</em>、且有預算支付 Enterprise tier。純 AWS-internal 簡單 web app 用 AWS WAF 整合更直接；要整套 edge security suite 用 Cloudflare。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>VCL + Edge custom rule</strong>：Fastly Edge 部署模式下、NG-WAF 跟 <a href="https://www.fastly.com/">Fastly CDN</a> 的 VCL（Varnish Configuration Language）共存、複雜邏輯可寫 VCL 在 NG-WAF 處理前後攔截 — 例：geo block 在 VCL 做、NG-WAF 處理通過的請求。Compute@Edge（Fastly 的 edge serverless、類 Cloudflare Workers）也可以接 NG-WAF 結果做進一步處理。代價是 VCL / Compute@Edge code 變另一條 ops trace、要有版控與 staging。</p>
<p><strong>ATO 進階 — credential stuffing 場景</strong>：login endpoint 接 ATO Template Rule 後、可進一步整合 <em>已洩漏 credential check</em>（類 Have I Been Pwned 整合）、failed login burst → progressive challenge（先 CAPTCHA、再 block）。對應 <a href="/blog/backend/07-security-data-protection/identity-access-boundary/" data-link-title="7.2 身分與授權邊界" data-link-desc="以問題驅動方式整理身分、授權、會話與供應商身分鏈">Identity Boundary</a> 的 IdP ATO 邏輯、Fastly 在 WAF 層攔的好處是 <em>攻擊不會打到 IdP</em>、減少 IdP 端 rate limit 壓力。</p>
<p><strong>Bot Protection 進階</strong>：browser fingerprint + behavioral pattern + JS challenge 三層、可掛 <em>bot score threshold</em> 在 Power Rules 內、配合 ATO 做 <em>high-risk login flow</em>（bot score 高 + login endpoint → 強 challenge）。</p>
<p><strong>Agent + Module 在 K8s / VM</strong>：K8s 場景 sigsci-agent 走 sidecar 或 DaemonSet、sigsci-module 在 ingress controller（Nginx Ingress Controller 加 sigsci-nginx module）；VM 場景 sigsci-agent 走 systemd service、module 隨 web server 啟動。跨環境 token 隔離（prod / staging / dev）走 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a> dynamic secret 或環境變數注入、不寫死配置檔。</p>
<p><strong>Corp-level Rule 共用</strong>：多 BU / 多產品線在同一 Corp（Fastly NG-WAF 的 organization 概念）下、Corp Rule 跨所有 Site 生效 — 適合表達「全公司禁 IP X」「全公司 ATO Template 都開」、避免每個 Site 重複配置。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Signal 沒觸發、攻擊穿過</strong>：Encoding 異常 / parser 沒解析該 content-type — 確認 Content-Type 正確、body 大小沒超過 sigsci-module 限制（預設 100KB）、Signal scope 是否包含該 endpoint</li>
<li><strong>Tag 沒掛上</strong>：Match Conditions 寫錯（path 大小寫、trailing slash、wildcard 語意）— 在 Fastly NG-WAF console 用 <em>Rule Evaluation</em> 工具測試 request 是否命中</li>
<li><strong>Block 模式誤殺</strong>：Power Rules threshold 太低、單一合法請求觸發多 Signal — 調 threshold 或加 Site Rule exception 排除特定 path / source</li>
<li><strong>sigsci-agent 跟控制面失聯</strong>：Site API key 過期 / firewall block out-bound / agent 版本太舊 — agent log 看 connection status、輪換 token 走 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a>、保持 agent 在 supported version range</li>
<li><strong>sigsci-module load 失敗</strong>：web server 啟動報 module 載入錯 — 確認 module 版本跟 web server major version 對齊（Nginx 1.20 對 sigsci-nginx 對應版本）</li>
<li><strong>ATO Template 沒攔到</strong>：login endpoint detection 沒標到自家 path — 手動在 console 標記 login endpoint 路徑</li>
<li><strong>Logging gap</strong>：Syslog / webhook 送失敗、SIEM 沒收到 — 確認 destination accept、TLS cert 沒過期、retry policy</li>
<li><strong>跨環境 token 漏氣</strong>：staging token 流到 prod、改 staging 影響 prod rule — Vault 環境分離、token 加標籤、定期 audit token usage</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>AWS-only + ALB / CloudFront origin</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/aws-waf/" data-link-title="AWS WAF" data-link-desc="AWS-internal WAF、跟 ALB / CloudFront / API Gateway 直接整合、Web ACL &#43; Managed Rule Group &#43; Rate-based Rule、Shield Standard 內含">AWS WAF</a></td>
      </tr>
      <tr>
          <td>多雲 + 要整套 edge security suite</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &#43; DDoS &#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF</a></td>
      </tr>
      <tr>
          <td>純 internal mTLS / east-west</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/spire/" data-link-title="SPIRE" data-link-desc="SPIFFE Runtime Environment、attested workload identity、short-lived SVID &#43; Trust Bundle、跨組織 federation">SPIRE</a> + service mesh</td>
      </tr>
      <tr>
          <td>Cert lifecycle</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/cert-manager/" data-link-title="cert-manager" data-link-desc="K8s 原生 certificate lifecycle automation、支援 Let&#39;s Encrypt / Vault PKI / Venafi 等多 issuer、auto-renewal &#43; Challenge solver">cert-manager</a> / <a href="/blog/backend/07-security-data-protection/vendors/letsencrypt/" data-link-title="Let&#39;s Encrypt" data-link-desc="免費 &#43; 自動化的公共 ACME CA、90 天 TTL 強制自動化、跨雲跨平台 public TLS cert 的事實基礎">Let&rsquo;s Encrypt</a></td>
      </tr>
      <tr>
          <td>Bot management 為主要訴求、預算敏感</td>
          <td>Cloudflare Bot Management 入門 / AWS WAF Bot Control</td>
      </tr>
      <tr>
          <td>DDoS L3/L4 為主</td>
          <td>Cloudflare Magic Transit / AWS Shield Advanced</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Signal Sciences 收購前的 product line 演進細節</li>
<li>完整 Signal 清單與每個 Signal 的內部解析邏輯</li>
<li>VCL / Compute@Edge 完整語法 reference</li>
<li>Fastly CDN 本身的 caching / TLS / origin shielding 細節</li>
<li>Enterprise 合約細節、各國資料駐留選項</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>Fastly NG-WAF 沒有直接 vendor-level 公開事件、案例庫對照引用以「behavioral detection 在 zero-day / supply chain 場景的 inline mitigation 角色」為主：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 Fastly NG-WAF 的關係</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/log4shell-cve-2021-44228-component-chain/" data-link-title="7.R7.2.7 Log4Shell 2021：共用元件風險與修補鏈" data-link-desc="共用元件漏洞如何同步影響多服務，並迫使團隊建立依賴治理 workflow">Log4Shell CVE-2021-44228</a></td>
          <td>對照啟示 — Anomaly Signal 對 JNDI pattern 有 immediate inline detection、不需等 vendor signature 更新；但 exploitation 進後端後仍要靠 supply chain 治理</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/edge-exposure/citrix-bleed-2023-session-hijack/" data-link-title="7.R7.3.3 Citrix Bleed 2023：會話被劫持與重放風險" data-link-desc="邊界設備會話資料外洩後，如何演變成帳號與服務風險">Citrix Bleed 2023 Session Hijack</a></td>
          <td>對照啟示 — WAF 攔不住 edge appliance zero-day、需要「修補 + session 失效 + 異常清查」三同步、NG-WAF Power Rules 可在窗口期提供臨時 anomaly 偵測</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/edge-exposure/fortinet-cve-2023-27997-sslvpn-overflow/" data-link-title="7.R7.3.21 Fortinet 2023：CVE-2023-27997 SSL-VPN 溢位" data-link-desc="SSL-VPN 漏洞在邊界設備上會放大大規模掃描與利用速度">Fortinet SSL-VPN CVE 2023-27997</a></td>
          <td>對照啟示 — vendor patch 前用 Power Rules + Tag 快速部署臨時 mitigation、收斂可達來源是修補窗口期的標準動作</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/entrypoint-and-server-protection/" data-link-title="7.3 入口治理與伺服器防護" data-link-desc="以問題驅動方式整理對外入口、管理平面與伺服器邊界">7.3 入口治理與伺服器防護</a></td>
          <td>Fastly NG-WAF 是 entry point protection 的工具、低 FP 設計讓 production Block 模式可行、跟 signature WAF 的部署成本曲線根本不同</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/entrypoint-and-server-protection/" data-link-title="7.3 入口治理與伺服器防護" data-link-desc="以問題驅動方式整理對外入口、管理平面與伺服器邊界">7.3 入口治理與伺服器防護</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &#43; DDoS &#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF</a>、<a href="/blog/backend/07-security-data-protection/vendors/aws-waf/" data-link-title="AWS WAF" data-link-desc="AWS-internal WAF、跟 ALB / CloudFront / API Gateway 直接整合、Web ACL &#43; Managed Rule Group &#43; Rate-based Rule、Shield Standard 內含">AWS WAF</a></li>
<li>下游：<a href="/blog/backend/07-security-data-protection/data-protection-and-masking-governance/" data-link-title="7.4 資料保護與遮罩治理" data-link-desc="以問題驅動方式整理資料分級、遮罩、匯出與備份治理">7.4 資料保護與遮罩治理</a>（WAF block 不夠時、資料層也要遮罩）</li>
<li>跨類：<a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a>（sigsci-agent Site API key 存放）、<a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a>（Fastly admin 走 SSO）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（WAF block 事件 routing 進 IR）</li>
<li>官方：<a href="https://docs.fastly.com/products/next-gen-waf">Fastly Next-Gen WAF Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>Google Secret Manager</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/google-secret-manager/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/google-secret-manager/</guid><description>&lt;p>Google Secret Manager（GSM）是 GCP 原生的 &lt;em>static secret 集中保管&lt;/em> 服務、設計上刻意保持 &lt;em>簡單&lt;/em>：只負責 secret 儲存、版本管理、IAM 授權、跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/google-cloud-kms/" data-link-title="Google Cloud KMS" data-link-desc="GCP 原生 key management service、KeyRing / CryptoKey Version 設計、CMEK 整合 &amp;#43; Cloud HSM &amp;#43; External Key Manager">Cloud KMS&lt;/a> 整合的 envelope encryption。rotation orchestration、cross-region replication policy、dynamic credential issuing 都不在 GSM 自己做、留給上層用 Cloud Function / Cloud Run 自組。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-secrets-manager/" data-link-title="AWS Secrets Manager" data-link-desc="AWS 原生 secret store &amp;#43; 內建 RDS / Redshift rotation Lambda、Resource Policy 跨帳號共享、KMS 加密">AWS Secrets Manager&lt;/a> 最大的差異是 &lt;em>沒有 built-in rotation Lambda&lt;/em> — rotation logic 要自己寫、GSM 只提供 &lt;em>Rotation Schedule + Pub/Sub event&lt;/em> 當觸發點。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>GSM 的定位是 &lt;em>GCP-native 的 secret 集中點&lt;/em>、解決三件事：把 secret 從 environment variable / Cloud Build substitution / GitHub secret 收回單一受控位置；用 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google Cloud IAM&lt;/a> 的 &lt;em>role binding on secret resource&lt;/em> 控制誰能讀；走 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Workload Identity Federation&lt;/a> 讓 GKE / Cloud Run / 外部 workload（GitHub Actions / AWS / Azure）安全取用、避免長期 service account key 散落。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault&lt;/a> 比、GSM 沒有 dynamic credential engine、沒有 transit / PKI engine、沒有跨雲統一介面 — 但運維成本接近於零、跟 GCP IAM / KMS / Cloud Logging 的整合是 first-class。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-secrets-manager/" data-link-title="AWS Secrets Manager" data-link-desc="AWS 原生 secret store &amp;#43; 內建 RDS / Redshift rotation Lambda、Resource Policy 跨帳號共享、KMS 加密">AWS Secrets Manager&lt;/a> 比、GSM 把 rotation orchestration 推給應用層、自由度高但代價是 &lt;em>rotation 流程要自己設計&lt;/em>；跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/azure-key-vault/" data-link-title="Azure Key Vault" data-link-desc="Azure 三合一 service（Secret &amp;#43; Key &amp;#43; Certificate）、整合 Managed Identity &amp;#43; Entra ID RBAC、Premium tier 走 HSM">Azure Key Vault&lt;/a> 比、兩者 mindset 相近（單雲、IAM-driven、CMEK 整合）、各自綁雲。&lt;/p></description><content:encoded><![CDATA[<p>Google Secret Manager（GSM）是 GCP 原生的 <em>static secret 集中保管</em> 服務、設計上刻意保持 <em>簡單</em>：只負責 secret 儲存、版本管理、IAM 授權、跟 <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-kms/" data-link-title="Google Cloud KMS" data-link-desc="GCP 原生 key management service、KeyRing / CryptoKey Version 設計、CMEK 整合 &#43; Cloud HSM &#43; External Key Manager">Cloud KMS</a> 整合的 envelope encryption。rotation orchestration、cross-region replication policy、dynamic credential issuing 都不在 GSM 自己做、留給上層用 Cloud Function / Cloud Run 自組。跟 <a href="/blog/backend/07-security-data-protection/vendors/aws-secrets-manager/" data-link-title="AWS Secrets Manager" data-link-desc="AWS 原生 secret store &#43; 內建 RDS / Redshift rotation Lambda、Resource Policy 跨帳號共享、KMS 加密">AWS Secrets Manager</a> 最大的差異是 <em>沒有 built-in rotation Lambda</em> — rotation logic 要自己寫、GSM 只提供 <em>Rotation Schedule + Pub/Sub event</em> 當觸發點。</p>
<h2 id="服務定位">服務定位</h2>
<p>GSM 的定位是 <em>GCP-native 的 secret 集中點</em>、解決三件事：把 secret 從 environment variable / Cloud Build substitution / GitHub secret 收回單一受控位置；用 <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google Cloud IAM</a> 的 <em>role binding on secret resource</em> 控制誰能讀；走 <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Workload Identity Federation</a> 讓 GKE / Cloud Run / 外部 workload（GitHub Actions / AWS / Azure）安全取用、避免長期 service account key 散落。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a> 比、GSM 沒有 dynamic credential engine、沒有 transit / PKI engine、沒有跨雲統一介面 — 但運維成本接近於零、跟 GCP IAM / KMS / Cloud Logging 的整合是 first-class。跟 <a href="/blog/backend/07-security-data-protection/vendors/aws-secrets-manager/" data-link-title="AWS Secrets Manager" data-link-desc="AWS 原生 secret store &#43; 內建 RDS / Redshift rotation Lambda、Resource Policy 跨帳號共享、KMS 加密">AWS Secrets Manager</a> 比、GSM 把 rotation orchestration 推給應用層、自由度高但代價是 <em>rotation 流程要自己設計</em>；跟 <a href="/blog/backend/07-security-data-protection/vendors/azure-key-vault/" data-link-title="Azure Key Vault" data-link-desc="Azure 三合一 service（Secret &#43; Key &#43; Certificate）、整合 Managed Identity &#43; Entra ID RBAC、Premium tier 走 HSM">Azure Key Vault</a> 比、兩者 mindset 相近（單雲、IAM-driven、CMEK 整合）、各自綁雲。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>哪些 secret 適合 GSM（GCP-only、static、靠 IAM 授權即可）、哪些該走 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a> 或其他雲端 native</li>
<li>GSM 最低安全設定（CMEK、Data Access audit、Workload Identity Federation、IAM Conditions）</li>
<li>自寫 rotation Cloud Function 時必須處理的 <em>版本切換窗口</em> 跟 <em>fallback 邏輯</em></li>
<li>何時 GSM 不夠用、要往 Vault / Berglas / Cloud HSM 走</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判讀一個 GSM deployment 是否健康、最少看四件事：</p>
<ul>
<li><strong>誰能讀 secret</strong>：secret resource 上的 IAM binding 是不是用最小單位授權（per-secret、不是 project-level <code>roles/secretmanager.secretAccessor</code>）、有沒有上 IAM Conditions 限定時間 / IP / resource tag</li>
<li><strong>Key custody 分離</strong>：encryption key 是 Google-managed default key、還是 <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-kms/" data-link-title="Google Cloud KMS" data-link-desc="GCP 原生 key management service、KeyRing / CryptoKey Version 設計、CMEK 整合 &#43; Cloud HSM &#43; External Key Manager">Cloud KMS</a> CMEK？CMEK 的 key 持有 admin 跟 secret access admin 是不是分人</li>
<li><strong>取用路徑</strong>：workload 取 secret 是走 <em>service account key</em>（壞模式、長期憑證散落）還是 <em>Workload Identity Federation</em>（GKE WIF / 外部 OIDC token exchange）</li>
<li><strong>證據是否可回查</strong>：Admin Activity audit 預設開、Data Access audit（<code>AccessSecretVersion</code> 誰呼叫）預設 <em>關</em>、production 要手動 enable + 接 <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Cloud Logging sink</a> 推到 SIEM</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">Audit Log</a> 與 <a href="/blog/backend/knowledge-cards/secret-management/" data-link-title="Secret Management" data-link-desc="說明 token、key、password 與憑證如何保存、輪替與撤銷">Secret Management</a> 邊界的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>IAM Conditions 收 scope</strong>：GSM 的 secretAccessor role 預設綁到 secret resource、但組織常見錯配是給整個 project 上 <code>roles/secretmanager.secretAccessor</code> — 等於整個 project 所有 secret 都能讀。應該用 <em>per-secret binding</em>、再加 IAM Conditions（<code>resource.name.endsWith('prod-db-password')</code>、<code>request.time &lt; timestamp('...')</code>）限縮時間窗口。對應 <a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/okta-cloudflare-2023-support-supply-chain/" data-link-title="7.R7.1.2 Okta &#43; Cloudflare 2023：支援流程與身分供應鏈" data-link-desc="支援工單與第三方身份供應商路徑如何變成入侵鏈的一部分">Okta Cloudflare 2023 supply chain</a> 的對照啟示：第三方 token scope 過寬時、上游事件直接傳導下游、IAM Conditions 是收 scope 的工具。</p>
<p><strong>Secret Version + Alias 模型</strong>：每個 secret 有 monotonic version（v1、v2、v3…）、預設 alias <code>latest</code> 指向最新 enabled version。rotation 不是「更新現有 secret」、是 <em>建立新 version + 把舊 version disable</em>。應用端要支援 <em>讀新 version 失敗時 fallback 舊 version</em>、或在 rotation Cloud Function 內實作 <em>雙軌驗證窗口</em>（新版本上線後一段時間舊版還能讀、確認所有 consumer 切過去再 destroy 舊版）。沒這層設計、一次 rotation 就會打掉沒及時更新的 consumer。</p>
<p><strong>CMEK（Customer-Managed Encryption Key）</strong>：GSM 預設用 Google-managed key、production 應該指向 <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-kms/" data-link-title="Google Cloud KMS" data-link-desc="GCP 原生 key management service、KeyRing / CryptoKey Version 設計、CMEK 整合 &#43; Cloud HSM &#43; External Key Manager">Cloud KMS</a> CMEK。意義是 <em>把 key 持有跟 secret 取用分離</em> — 即使 secret admin 被攻破、沒有 CMEK 的 <code>decrypt</code> 權限拿不到明文。代價是 CMEK key region 跟 secret replication 要對齊（key 在 <code>us-central1</code> 但 secret 設 automatic replication = key 進不去其他 region、secret access 會失敗）。</p>
<p><strong>Replication 策略</strong>：automatic 是 GCP 自動跨 region replicate（高可用、不需要管 region 一致性、但 data residency 受 GCP 全球策略支配）；user-managed 是手動指定 region list（精細控制資料駐留、適合有 GDPR / 跨境合規需求的場景、但 region 加減要自己管 + CMEK key 要在每個指定 region 都存在）。一個常見錯配：選 user-managed 但只設一個 region — 等於沒有跨 region 冗餘、該 region 出事 secret 完全讀不到。</p>
<p><strong>Rotation 是自管 schedule</strong>：GSM 提供的不是 rotation logic、是 <em>Rotation Schedule</em>（cron 或固定間隔）、到期會發 <em>Pub/Sub message</em> 到指定 topic、由 <em>自己寫的 Cloud Function / Cloud Run</em> 訂閱該 topic 執行實際 rotation（呼叫上游系統 API 生新 credential、寫成新 secret version、disable 舊 version）。對應 <a href="/blog/backend/07-security-data-protection/cases/failure-credential-rotation-without-scope/" data-link-title="7.C9 反例：憑證輪替未分 Scope" data-link-desc="憑證輪替若未分域分批，容易造成跨系統連鎖中斷。">Failure: Credential Rotation Without Scope</a>：rotation Cloud Function 必須自己處理 <em>scope map</em>（哪些 consumer 用了同一把 secret）跟 <em>雙軌驗證窗口</em>（confirm 所有 consumer 切到新版本才 disable 舊版）、不像 AWS Secrets Manager 有 built-in 四階段 flow（<code>createSecret</code> → <code>setSecret</code> → <code>testSecret</code> → <code>finishSecret</code>）。</p>
<p><strong>Workload Identity Federation 取用</strong>：external workload（GitHub Actions / AWS workload / Azure workload / on-prem K8s）用 WIF 拿 GSM secret 是現代預設模式 — workload 用自己的 OIDC token（GitHub OIDC、AWS STS）跟 GCP STS 交換 short-lived access token、再用 token 呼叫 GSM。避開了「長期 service account JSON key 散落 CI / 第三方環境」的問題。GKE 內 workload 走 <em>GKE Workload Identity</em>（pod ServiceAccount → GCP service account 綁定）取 secret、也是同 mindset。</p>
<p><strong>Audit log 治理</strong>：GSM 的 audit 分兩層 — Admin Activity（create / delete / IAM 變更、預設開、免費）、Data Access（<code>AccessSecretVersion</code>、預設 <em>關</em>、開啟有 log 量跟 BigQuery export cost）。production 不開 Data Access = 事故時 <em>連 secret 被誰取過都查不到</em>、必須在 project IAM Audit Config 開、Cloud Logging sink 推到 SIEM 或 BigQuery（見 <a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">7.13 偵測覆蓋率與訊號治理</a>）。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Google Secret Manager</th>
          <th>HashiCorp Vault</th>
          <th>AWS Secrets Manager</th>
          <th>Azure Key Vault</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>部署模型</td>
          <td>GCP managed</td>
          <td>自管 cluster（HA + replication）</td>
          <td>AWS managed</td>
          <td>Azure managed</td>
      </tr>
      <tr>
          <td>跨雲</td>
          <td>弱 — 綁 GCP</td>
          <td>強 — 同一介面跨 AWS / GCP / Azure / on-prem</td>
          <td>弱 — 綁 AWS</td>
          <td>弱 — 綁 Azure</td>
      </tr>
      <tr>
          <td>Rotation 模型</td>
          <td>自寫 Cloud Function（Pub/Sub trigger）</td>
          <td>dynamic engine 自動 lease</td>
          <td>built-in Lambda 四階段 flow</td>
          <td>自寫 Function App（Event Grid trigger）</td>
      </tr>
      <tr>
          <td>Dynamic credential</td>
          <td>無（靠 IAM impersonation 替代）</td>
          <td>DB / cloud / SSH engine 完整</td>
          <td>RDS rotation 有、cloud STS 較弱</td>
          <td>較弱（依靠 Managed Identity）</td>
      </tr>
      <tr>
          <td>Encryption key</td>
          <td>Google-managed default / <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-kms/" data-link-title="Google Cloud KMS" data-link-desc="GCP 原生 key management service、KeyRing / CryptoKey Version 設計、CMEK 整合 &#43; Cloud HSM &#43; External Key Manager">Cloud KMS</a> CMEK</td>
          <td>自管 / KMS auto-unseal</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/aws-kms/" data-link-title="AWS KMS" data-link-desc="AWS 原生 key management service、envelope encryption / digital signing / Multi-Region Key、Key Policy &#43; Grant 雙軌授權">AWS KMS</a> CMK</td>
          <td>Azure Key Vault key</td>
      </tr>
      <tr>
          <td>External workload</td>
          <td>Workload Identity Federation（成熟）</td>
          <td>AppRole / Kubernetes / OIDC auth</td>
          <td>IAM Roles Anywhere（較新）</td>
          <td>Managed Identity / Workload Identity</td>
      </tr>
      <tr>
          <td>運維成本</td>
          <td>低</td>
          <td>高 — HA、upgrade、replication 自己顧</td>
          <td>低</td>
          <td>低</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>GCP-heavy + WIF 已主導 + static secret 為主</td>
          <td>跨雲、dynamic credential、內部 PKI</td>
          <td>AWS-heavy + 需要 built-in rotation 收斂</td>
          <td>Azure-heavy + Managed Identity 已主導</td>
      </tr>
      <tr>
          <td>退場成本</td>
          <td>低</td>
          <td>中 — dynamic engine 接線多</td>
          <td>低</td>
          <td>低</td>
      </tr>
  </tbody>
</table>
<p>選 GSM 的核心訴求：workload 主要跑在 GCP（GKE / Cloud Run / Cloud Build）、已經用 Workload Identity Federation 收 service account key、secret 形態以 static 為主（DB password、third-party API key、private key）、rotation 邏輯願意用 Cloud Function 自寫。要跨雲、要 dynamic credential、要內建 rotation flow、需要 transit encryption — 走 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a>。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>CMEK + Cloud KMS 雙軌權限分離</strong>：production 應該 <em>至少</em> 把 prod secret 的 CMEK key 跟 secret IAM 分到不同 admin group — secret admin 可以建 / 改 secret 但不能 decrypt（沒 KMS <code>cloudkms.cryptoKeyDecrypter</code>），KMS admin 可以管 key 但不能讀 secret 內容。對應 <a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/microsoft-storm-0558-2023-signing-key-chain/" data-link-title="7.R7.1.5 Microsoft Storm-0558 2023：簽章金鑰鏈與郵件存取" data-link-desc="從簽章金鑰保護失效到雲端郵件存取，拆解身分信任鏈的關鍵控制點">Microsoft Storm-0558 signing key chain</a> 的對照啟示：key 不離 KMS 邊界、跟 HSM-bound 同 mindset；CMEK 是把這個原則內建到 secret 路徑。</p>
<p><strong>Berglas（OSS pattern）</strong>：<a href="https://github.com/GoogleCloudPlatform/berglas">Berglas</a> 是 Google 開源的 GSM client library + CLI、在 Cloud Run / Cloud Function / GKE 啟動時把 <code>sm://...</code> 參考自動 resolve 成實際 secret value、注進環境變數或檔案。比起應用端寫 SDK 取 secret 的好處：<em>secret 不進 container image / build manifest</em>、只有 runtime 取得；缺點是多一層 dependency、且 Berglas 自己有 IAM 需求要管。</p>
<p><strong>GKE Workload Identity 取用</strong>：GKE pod 用 ServiceAccount → IAM service account 綁定（透過 <code>iam.gke.io/gcp-service-account</code> annotation）、pod 內呼叫 GSM API 自動帶 GCP service account 身份、metadata server 簽 token。比起把 service account JSON key mount 進 pod、Workload Identity 沒有長期 credential 在 pod 內、credential rotation 由 GCP metadata 自動處理。</p>
<p><strong>Secret rotation Cloud Function 樣板</strong>：訂閱 secret 的 rotation topic（Pub/Sub）、message 帶 secret name 跟 trigger reason；Function 內呼叫上游系統 API（DB / SaaS）生新 credential、用 <code>secretmanager.AddSecretVersion</code> 寫新 version、等一段時間（雙軌驗證窗口）後 <code>DisableSecretVersion</code> 舊 version、最後 <code>DestroySecretVersion</code> 完成 rotation。<strong>雙軌窗口的長度必須大於 consumer 的最長 cache TTL</strong>、否則沒及時 refresh 的 consumer 會在 disable 後失敗。</p>
<p><strong>Pub/Sub event subscription（new in 2023+）</strong>：除了 rotation schedule 自動發 event、GSM 也支援對 secret 任意變更（new version、IAM change）發 Pub/Sub message、可接 SOAR / SIEM 做 <em>secret 異常變更告警</em>（例：非 CI service account 在週末新增 secret version）。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>取 secret 拿到 PERMISSION_DENIED</strong>：通常是 IAM binding 在 project 層但 secret 在某 sub-resource、或 IAM Conditions 把當前 caller 排除 — 用 <code>gcloud secrets get-iam-policy</code> 直接看 binding、確認 condition 表達式</li>
<li><strong>CMEK 設定後突然讀不到 secret</strong>：CMEK key region 跟 secret replication region 不對齊、或 caller 沒有 KMS decrypt 權限 — 確認 key 在所有 replication region 都有版本、secret accessor service account 有 <code>cloudkms.cryptoKeyDecrypter</code></li>
<li><strong>Rotation Cloud Function 跑了但 consumer 認證失敗</strong>：雙軌窗口太短或 consumer 沒實作 <em>latest version 失敗 fallback</em>、舊版 disable 後孤兒 consumer 直接斷 — 把雙軌窗口拉到 cache TTL × 2、補 fallback 邏輯</li>
<li><strong>Data Access audit 沒紀錄</strong>：預設關、要在 project IAM Audit Config 明確開 <code>secretmanager.googleapis.com</code> 的 DATA_READ — 不開等於沒辦法回答「事故當下誰讀了 secret」</li>
<li><strong>External workload 拿不到 secret</strong>：Workload Identity Federation 的 provider attribute mapping 沒對齊（GitHub OIDC token 的 <code>repository</code> claim 沒被 map 到 attribute condition）— 走 <code>gcloud iam workload-identity-pools providers describe</code> 看 mapping、用 token introspection 驗實際 claim</li>
<li><strong>Secret version 累積過多</strong>：rotation 只 disable 不 destroy、版本無限長 — 加 lifecycle policy（手動 / Cloud Function 排程）destroy 超過 N 個版本以前的舊版</li>
<li><strong>GKE pod 用 Workload Identity 但拿不到 secret</strong>：通常是 GKE 沒 enable Workload Identity feature、或 <code>iam.gke.io/gcp-service-account</code> annotation 拼錯、或 GCP service account 沒給 K8s ServiceAccount <code>iam.workloadIdentityUser</code> — 三層都要對才能通</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>跨雲 secret 統一介面</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a></td>
      </tr>
      <tr>
          <td>需要 dynamic database / cloud credential</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a> dynamic engine</td>
      </tr>
      <tr>
          <td>需要 built-in 四階段 rotation flow</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/aws-secrets-manager/" data-link-title="AWS Secrets Manager" data-link-desc="AWS 原生 secret store &#43; 內建 RDS / Redshift rotation Lambda、Resource Policy 跨帳號共享、KMS 加密">AWS Secrets Manager</a>（若可遷 AWS）</td>
      </tr>
      <tr>
          <td>Encryption-as-a-service / 內部 PKI</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a> transit / PKI engine</td>
      </tr>
      <tr>
          <td>FIPS 140-2 Level 3 HSM 需求</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/google-cloud-kms/" data-link-title="Google Cloud KMS" data-link-desc="GCP 原生 key management service、KeyRing / CryptoKey Version 設計、CMEK 整合 &#43; Cloud HSM &#43; External Key Manager">Cloud HSM</a>（KMS 後端可改 HSM）</td>
      </tr>
      <tr>
          <td>公開憑證 PKI</td>
          <td>Google Certificate Authority Service / <a href="/blog/backend/07-security-data-protection/vendors/letsencrypt/" data-link-title="Let&#39;s Encrypt" data-link-desc="免費 &#43; 自動化的公共 ACME CA、90 天 TTL 強制自動化、跨雲跨平台 public TLS cert 的事實基礎">Let&rsquo;s Encrypt</a></td>
      </tr>
      <tr>
          <td>K8s workload cert 自動化</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/cert-manager/" data-link-title="cert-manager" data-link-desc="K8s 原生 certificate lifecycle automation、支援 Let&#39;s Encrypt / Vault PKI / Venafi 等多 issuer、auto-renewal &#43; Challenge solver">cert-manager</a></td>
      </tr>
      <tr>
          <td>Secret rotation 證據鏈</td>
          <td><a href="/blog/backend/07-security-data-protection/credential-rotation-scoped-evidence/" data-link-title="7.27 Credential Rotation with Scoped Evidence 實作示範" data-link-desc="以 webhook/API credential 輪替示範 scope map、證據欄位與回退窗口如何一起設計。">7.5 Credential Rotation Scoped Evidence</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>GSM 完整 REST API 跟 <code>gcloud secrets</code> 詳盡子命令</li>
<li>Cloud KMS key lifecycle 跟 rotation 細節（看 <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-kms/" data-link-title="Google Cloud KMS" data-link-desc="GCP 原生 key management service、KeyRing / CryptoKey Version 設計、CMEK 整合 &#43; Cloud HSM &#43; External Key Manager">Google Cloud KMS</a> 章）</li>
<li>Workload Identity Federation 完整設定步驟（attribute mapping、condition expression、provider 設定看 <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google Cloud IAM</a> 章）</li>
<li>Berglas 完整 CLI 用法</li>
<li>Cloud Function / Cloud Run 部署細節</li>
<li>GCP Organization Policy 跟 secret 跨 project 共享的進階場景</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>GSM 在 07 案例庫沒有直接 vendor-level 事件、以下案例採對照引用：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 GSM 的關係（對照）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/cases/failure-credential-rotation-without-scope/" data-link-title="7.C9 反例：憑證輪替未分 Scope" data-link-desc="憑證輪替若未分域分批，容易造成跨系統連鎖中斷。">Failure: Credential Rotation Without Scope</a></td>
          <td>GSM rotation 是自寫 Cloud Function、scope map 跟雙軌驗證窗口都要自己設計、不像 AWS Secrets Manager 有 built-in 四階段 flow — 設計時就要把 consumer scope 跟 cache TTL 算進 rotation 排程</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/microsoft-storm-0558-2023-signing-key-chain/" data-link-title="7.R7.1.5 Microsoft Storm-0558 2023：簽章金鑰鏈與郵件存取" data-link-desc="從簽章金鑰保護失效到雲端郵件存取，拆解身分信任鏈的關鍵控制點">Microsoft Storm-0558 Signing Key Chain (red-team)</a></td>
          <td>對照啟示 — GSM CMEK 把 encryption key 放 <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-kms/" data-link-title="Google Cloud KMS" data-link-desc="GCP 原生 key management service、KeyRing / CryptoKey Version 設計、CMEK 整合 &#43; Cloud HSM &#43; External Key Manager">Cloud KMS</a>、key 不離 KMS 邊界、跟 HSM-bound 同 mindset；secret admin 跟 KMS admin 分人是減 blast radius 的關鍵</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/okta-cloudflare-2023-support-supply-chain/" data-link-title="7.R7.1.2 Okta &#43; Cloudflare 2023：支援流程與身分供應鏈" data-link-desc="支援工單與第三方身份供應商路徑如何變成入侵鏈的一部分">Okta Cloudflare 2023 Support Supply Chain (red-team)</a></td>
          <td>對照啟示 — GSM 管的第三方 token（GitHub PAT / Slack token / SaaS API key）scope 過寬時、上游事件直接傳導下游、要走 IAM Conditions 收 caller scope 跟過期時間</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/secrets-and-machine-credential-governance/" data-link-title="7.6 秘密管理與機器憑證治理" data-link-desc="以問題驅動方式整理 secret、token、key 與機器身份治理">7.6 秘密管理與機器憑證治理</a>、<a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">7.13 偵測覆蓋率與訊號治理</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a>、<a href="/blog/backend/07-security-data-protection/vendors/aws-secrets-manager/" data-link-title="AWS Secrets Manager" data-link-desc="AWS 原生 secret store &#43; 內建 RDS / Redshift rotation Lambda、Resource Policy 跨帳號共享、KMS 加密">AWS Secrets Manager</a>、<a href="/blog/backend/07-security-data-protection/vendors/azure-key-vault/" data-link-title="Azure Key Vault" data-link-desc="Azure 三合一 service（Secret &#43; Key &#43; Certificate）、整合 Managed Identity &#43; Entra ID RBAC、Premium tier 走 HSM">Azure Key Vault</a></li>
<li>下游：<a href="/blog/backend/07-security-data-protection/vendors/google-cloud-kms/" data-link-title="Google Cloud KMS" data-link-desc="GCP 原生 key management service、KeyRing / CryptoKey Version 設計、CMEK 整合 &#43; Cloud HSM &#43; External Key Manager">Google Cloud KMS</a>（GSM CMEK 後端、key custody 分離）</li>
<li>下游：<a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google Cloud IAM</a>（secret IAM binding、Workload Identity Federation 設定）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（GSM 事件如何 routing 進 IR 流程）</li>
<li>官方：<a href="https://cloud.google.com/secret-manager/docs">Secret Manager Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>Keycloak</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/keycloak/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/keycloak/</guid><description>&lt;p>Keycloak 是 open source 自管 Identity Provider、Red Hat 主導維護（商業支援版本為 Red Hat build of Keycloak、前身 Red Hat SSO）。它承擔的責任跟 SaaS IdP 相同 — SSO、MFA、federation、user lifecycle — 但 &lt;em>整個控制面留在組織自己手上&lt;/em>：issuer signing key、support tooling、底層 PostgreSQL、HA cluster、CVE patch cadence 全部自管。決定上 Keycloak 不是技術偏好、是組織決定把 SaaS IdP 的「第三方信任成本」換成「自家 SRE 運維成本 + 安全責任」。在 &lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/capability-buy-vs-build/" data-link-title="0.22 能力級買 vs 建：feature-as-a-service 與 BaaS bundle 選型" data-link-desc="在交付形態決定整個系統要不要自建之後、逐能力判斷該外包還是自建：辨識 managed 基礎設施、feature SaaS 與 BaaS bundle 三種外包深度、no-code 到 dev-tool 的服務光譜、買 vs 建判準與權重浮動、整合接縫與遷出代價">0.22 能力級買 vs 建&lt;/a> 的光譜上、Keycloak 是認證能力「建」側的 canonical 例子 — 把 feature SaaS（Auth0 / Okta）的第三方信任成本、換成自管控制面的運維成本；什麼訊號該翻到這一側、見 0.22 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/capability-outsourcing-depth/" data-link-title="Capability Outsourcing Depth（外包深度）" data-link-desc="說明外包一塊後端能力有三種深度（managed 基礎設施、feature SaaS、BaaS bundle）、深度決定保留多少控制權與遷出代價">外包深度&lt;/a> 卡。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Keycloak 是 &lt;em>自管控制面&lt;/em> 的 human identity 與 federation engine、不是 cloud resource permission engine。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/auth0/" data-link-title="Auth0" data-link-desc="B2C / B2B Customer Identity Provider、Universal Login、Action / Rule hook、屬 Okta 旗下 Customer Identity Cloud">Auth0&lt;/a> 的本質差異在於信任邊界落點：SaaS IdP 把 signing key、tenant 隔離、support workflow 都託管出去、客戶承擔「供應商出事我也跟著被打」的風險；Keycloak 把整條控制面收回自家機房或自家 VPC、客戶承擔「signing key 過期 / DB 崩 / Java app CVE 沒跟上」的運維風險。&lt;/p>
&lt;p>跟 cloud-native SSO（&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-iam-identity-center/" data-link-title="AWS IAM Identity Center" data-link-desc="AWS 原生 workforce SSO、前 AWS SSO、Permission Set 跨帳號 access、可串外部 IdP federation">AWS IAM Identity Center&lt;/a>）相比、Keycloak 的核心優勢是 &lt;em>不綁雲廠 + 可深度客製 authentication flow + 資料不出境&lt;/em>。適合垂直：金融、政府、醫療某些不接受 SaaS IdP 的場景；以及預算敏感、員工數中等、SRE 量能足以接 24/7 on-call 的組織。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本頁、讀者能判斷：&lt;/p>
&lt;ol>
&lt;li>Keycloak 該承擔哪一段 identity 控制（SSO / MFA / federation / brokering）、哪一段該交給雲端 IAM 或下游應用&lt;/li>
&lt;li>自管 IdP 的最低運維基線（HA、DB DR、cert / signing key rotation、CVE cadence、SIEM 接點）&lt;/li>
&lt;li>Realm / Client / User Federation / Identity Broker / Authentication Flow / SPI 各自的決策時機與陷阱&lt;/li>
&lt;li>何時用 Keycloak、何時改走 SaaS（Okta / Auth0）或其他 OSS（Authentik / Zitadel）&lt;/li>
&lt;/ol>
&lt;h2 id="最短判讀路徑">最短判讀路徑&lt;/h2>
&lt;p>判斷 Keycloak 部署是否健康、最少看 SaaS IdP 的四件事加上自管特有的四個維度：&lt;/p></description><content:encoded><![CDATA[<p>Keycloak 是 open source 自管 Identity Provider、Red Hat 主導維護（商業支援版本為 Red Hat build of Keycloak、前身 Red Hat SSO）。它承擔的責任跟 SaaS IdP 相同 — SSO、MFA、federation、user lifecycle — 但 <em>整個控制面留在組織自己手上</em>：issuer signing key、support tooling、底層 PostgreSQL、HA cluster、CVE patch cadence 全部自管。決定上 Keycloak 不是技術偏好、是組織決定把 SaaS IdP 的「第三方信任成本」換成「自家 SRE 運維成本 + 安全責任」。在 <a href="/blog/backend/00-service-selection/capability-buy-vs-build/" data-link-title="0.22 能力級買 vs 建：feature-as-a-service 與 BaaS bundle 選型" data-link-desc="在交付形態決定整個系統要不要自建之後、逐能力判斷該外包還是自建：辨識 managed 基礎設施、feature SaaS 與 BaaS bundle 三種外包深度、no-code 到 dev-tool 的服務光譜、買 vs 建判準與權重浮動、整合接縫與遷出代價">0.22 能力級買 vs 建</a> 的光譜上、Keycloak 是認證能力「建」側的 canonical 例子 — 把 feature SaaS（Auth0 / Okta）的第三方信任成本、換成自管控制面的運維成本；什麼訊號該翻到這一側、見 0.22 與 <a href="/blog/backend/knowledge-cards/capability-outsourcing-depth/" data-link-title="Capability Outsourcing Depth（外包深度）" data-link-desc="說明外包一塊後端能力有三種深度（managed 基礎設施、feature SaaS、BaaS bundle）、深度決定保留多少控制權與遷出代價">外包深度</a> 卡。</p>
<h2 id="服務定位">服務定位</h2>
<p>Keycloak 是 <em>自管控制面</em> 的 human identity 與 federation engine、不是 cloud resource permission engine。跟 <a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a> / <a href="/blog/backend/07-security-data-protection/vendors/auth0/" data-link-title="Auth0" data-link-desc="B2C / B2B Customer Identity Provider、Universal Login、Action / Rule hook、屬 Okta 旗下 Customer Identity Cloud">Auth0</a> 的本質差異在於信任邊界落點：SaaS IdP 把 signing key、tenant 隔離、support workflow 都託管出去、客戶承擔「供應商出事我也跟著被打」的風險；Keycloak 把整條控制面收回自家機房或自家 VPC、客戶承擔「signing key 過期 / DB 崩 / Java app CVE 沒跟上」的運維風險。</p>
<p>跟 cloud-native SSO（<a href="/blog/backend/07-security-data-protection/vendors/aws-iam-identity-center/" data-link-title="AWS IAM Identity Center" data-link-desc="AWS 原生 workforce SSO、前 AWS SSO、Permission Set 跨帳號 access、可串外部 IdP federation">AWS IAM Identity Center</a>）相比、Keycloak 的核心優勢是 <em>不綁雲廠 + 可深度客製 authentication flow + 資料不出境</em>。適合垂直：金融、政府、醫療某些不接受 SaaS IdP 的場景；以及預算敏感、員工數中等、SRE 量能足以接 24/7 on-call 的組織。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>Keycloak 該承擔哪一段 identity 控制（SSO / MFA / federation / brokering）、哪一段該交給雲端 IAM 或下游應用</li>
<li>自管 IdP 的最低運維基線（HA、DB DR、cert / signing key rotation、CVE cadence、SIEM 接點）</li>
<li>Realm / Client / User Federation / Identity Broker / Authentication Flow / SPI 各自的決策時機與陷阱</li>
<li>何時用 Keycloak、何時改走 SaaS（Okta / Auth0）或其他 OSS（Authentik / Zitadel）</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Keycloak 部署是否健康、最少看 SaaS IdP 的四件事加上自管特有的四個維度：</p>
<ul>
<li><strong>誰能做什麼</strong>：master realm admin 的人數、是否走 access request workflow、admin console 是否限 IP / device trust、是否強制 <a href="/blog/backend/knowledge-cards/authentication/" data-link-title="Authentication" data-link-desc="說明系統如何確認呼叫者身份">phishing-resistant 認證</a></li>
<li><strong>憑證在哪裡</strong>：client secret 是否走 <a href="/blog/backend/knowledge-cards/secret-management/" data-link-title="Secret Management" data-link-desc="說明 token、key、password 與憑證如何保存、輪替與撤銷">secret management</a>、realm signing key 的 rotation 排程、admin token 的 TTL</li>
<li><strong>入口如何暴露</strong>：哪些 realm 對外、reverse proxy / Ingress 是否做 rate limit、admin console（/auth/admin）是否限內網或 zero trust</li>
<li><strong>證據是否可回查</strong>：Event Listener SPI 是否接 SIEM、admin event 跟 login event 是否分流、保留期是否符合稽核</li>
<li><strong>DB 健康</strong>：PostgreSQL / MySQL 是否跨 AZ、是否有 PITR、是否做過 restore 演練（不是只有備份成功訊息）</li>
<li><strong>Cert lifecycle</strong>：TLS cert 與 realm signing key 各自的 rotation 排程、是否走 <a href="/blog/backend/knowledge-cards/website-certificate-lifecycle/" data-link-title="Website Certificate Lifecycle" data-link-desc="說明網站 TLS 憑證從簽發到續期與撤銷的全流程責任">Website Certificate Lifecycle</a> 自動化</li>
<li><strong>HA topology</strong>：Keycloak cluster 是否多節點、Infinispan cache 是否跨 AZ、單節點重啟是否會踢掉所有 session</li>
<li><strong>Upgrade cadence</strong>：Keycloak 每年 major release、CVE patch 是否能在 SLA 內上、是否有 staging 跑 DB migration</li>
</ul>
<p>八個維度任一缺失、都是自管 IdP 常見事故的入口。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>Realm 設計</strong>：Realm 是 Keycloak 的隔離邊界、每個 realm 有獨立的 user store、client、role、signing key。multi-tenancy 走 realm 是正確選擇、但 <em>master realm 能管所有 realm</em>、master realm 的 admin compromise = 全公司 IdP compromise。把 master realm 鎖在內網、operational realm 才對外、是基本姿勢。</p>
<p><strong>Client 註冊與 secret</strong>：每個應用是一個 client、confidential client 有 secret、public client（SPA / mobile）走 PKCE 不存 secret。client secret 不存 source code、走 <a href="/blog/backend/knowledge-cards/secret-management/" data-link-title="Secret Management" data-link-desc="說明 token、key、password 與憑證如何保存、輪替與撤銷">secret management</a> 注入。client 數量爆炸時要設 naming convention 跟 ownership 標記、不然 stale client 會堆積。</p>
<p><strong>User Federation</strong>：把既有 LDAP / Active Directory 接進 Keycloak、user 還是住在原 directory、Keycloak 做 protocol 翻譯（LDAP → OIDC / SAML）。這是 Keycloak 強項之一 — 不需要 user migration、漸進接入。陷阱是 LDAP 連線健康 = IdP 健康、LDAP 慢 = 全公司 login 慢。</p>
<p><strong>Identity Brokering</strong>：把外部 IdP（Google、Microsoft、其他 SAML / OIDC provider）federate 進來、Keycloak 當中介。B2B 合作常見模式 — partner 用自己的 IdP、不在我的 user store 開帳號。決策點是 <em>trust mapping</em>：外部 claim 怎麼對應到內部 role、外部 IdP 的 MFA 狀態怎麼信任。</p>
<p><strong>Authentication Flow</strong>：Keycloak 把 login / registration / reset password 做成可編輯的 flow DAG、可以插入自訂 step。這是 Keycloak 跟 SaaS IdP 最大差異點之一 — 想要 step-up MFA、device fingerprint、risk-based 判斷都可以自己接。雙面刃是 <em>自訂 flow 容易留漏洞</em>：跳過必要步驟、condition 寫錯讓 MFA 變可選、custom Authenticator SPI 沒處理 race condition。</p>
<p><strong>Theme / 客製 UI</strong>：Keycloak 支援 theme override、可以改 login page HTML / CSS / JS。custom JS 在 login page = 自己注入 XSS 風險 — theme 寫進去之後就是 IdP 本體的攻擊面、不是普通網頁。CSP 跟 input sanitization 要當成 IdP 安全規範看待。</p>
<p><strong>Event Listener / Audit</strong>：Keycloak 預設只把 event 寫進 DB、UI 上能查、但 <em>不會自動推到外部 SIEM</em>。生產環境必須接 Event Listener SPI（內建 jboss-logging、或自寫 Kafka / file listener）把 admin event 跟 login event 推進 SIEM。沒接的話 audit trail 只在 IdP 本機、IdP 出事就拿不到 evidence。</p>
<p><strong>Exception / break-glass</strong>：master realm 留至少 2 個 break-glass admin、credential 離線存、走獨立 MFA（hardware key）。Keycloak cluster 整個失聯時、用 break-glass 直連 DB / 直連單一節點救回。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Keycloak（自管 OSS）</th>
          <th>Okta（SaaS）</th>
          <th>Auth0（SaaS / B2C）</th>
          <th>Authentik / Zitadel（其他 OSS）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>控制面責任</td>
          <td>自己跑 issuer / signing / HA / DB / upgrade</td>
          <td>Okta 託管</td>
          <td>Auth0 託管</td>
          <td>自己跑、但社群規模小於 Keycloak</td>
      </tr>
      <tr>
          <td>客製化深度</td>
          <td>高 — Authenticator SPI / theme / event listener</td>
          <td>中 — Workflows / Hooks、限定範圍</td>
          <td>高 — Actions（JS hook）</td>
          <td>中 — Authentik flow 視覺化、彈性中等</td>
      </tr>
      <tr>
          <td>第三方信任成本</td>
          <td>低 — 自管、自己承擔運維</td>
          <td>高 — 供應商事件直接波及</td>
          <td>高 — 同 Okta（同集團）</td>
          <td>低 — 自管</td>
      </tr>
      <tr>
          <td>運維成本</td>
          <td>高 — HA、DR、cert、DB、CVE 都自管</td>
          <td>低 — SaaS</td>
          <td>低 — SaaS</td>
          <td>高 — 同 Keycloak、生態系更小</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>資料主權、預算敏感、需深度客製、有 SRE 量能</td>
          <td>多雲、大量 SaaS、lifecycle 自動化</td>
          <td>B2C、消費者 identity、developer-centric</td>
          <td>規模小、Keycloak 太重、想要更現代 UI</td>
      </tr>
      <tr>
          <td>退場成本</td>
          <td>中 — 自己掌握資料、protocol 標準可遷移</td>
          <td>高 — SAML / SCIM 接線散在數百 app</td>
          <td>高 — Actions / Rules 客製綁定深</td>
          <td>中 — 同 Keycloak</td>
      </tr>
  </tbody>
</table>
<p>選 Keycloak 的核心訴求：<em>資料主權 + 預算控制 + 客製 flow 需求</em>、且有 SRE 團隊能 24/7 on-call、能接受自管的運維重量。團隊小於 50 人沒 SRE 量能、應用主要在 SaaS（pre-built integration 用不上 Keycloak 強項）、需要快速接 7000+ SaaS app — 都該回頭看 Okta / Auth0。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>User Federation 跟 LDAP 整合</strong>：企業環境常見「Active Directory 是 user source of truth、Keycloak 做 protocol 層」。注意 LDAP 同步策略（read-only / writable / import）、LDAP 健康直接影響 IdP 可用性、LDAP timeout 要設嚴格避免 login 卡住整個 cluster。</p>
<p><strong>Identity Brokering 跟外部 IdP</strong>：把 Google / Microsoft / 其他 SAML IdP federate 進來、外部 user 進來時 Keycloak 自動建 link。trust mapping 是關鍵 — 外部 IdP 宣稱「這個 user 已 MFA」、要不要信？外部 group claim 怎麼對應到內部 role？沒有預設答案、要用 <a href="/blog/backend/knowledge-cards/authorization/" data-link-title="Authorization" data-link-desc="說明授權如何判斷誰能對哪些資源執行哪些操作">authorization</a> 邊界決定。</p>
<p><strong>Fine-Grained Authorization（UMA / Authorization Services）</strong>：Keycloak 內建 policy engine、可以做 resource-level 授權（不只是 role-based）。適合需要中央化 policy decision 的場景、但會把應用的授權邏輯綁進 Keycloak、退場成本變高。多數場景應該把 authorization 留在應用內、Keycloak 只做 authentication + role token 發行。</p>
<p><strong>Custom Authenticator SPI</strong>：用 Java 寫自訂 authenticator、插進 Authentication Flow。能做 step-up MFA、device posture、risk score 判斷。陷阱是 SPI 程式碼就是 IdP 本體的一部分、bug = IdP 漏洞、必須走完整 code review + 安全測試流程、不能當普通 feature 開發。</p>
<p><strong>Realm signing key rotation</strong>：每個 realm 有自己的 RSA / EC signing key、用來簽 ID token / SAML assertion。rotation 必須跟下游 client 協調（key rollover 期間 client 要能接受新舊 key）、否則 rotation 當天全公司 login 失敗。分域分批是必做的、參考 <a href="/blog/backend/07-security-data-protection/cases/failure-credential-rotation-without-scope/" data-link-title="7.C9 反例：憑證輪替未分 Scope" data-link-desc="憑證輪替若未分域分批，容易造成跨系統連鎖中斷。">Failure: Credential Rotation Without Scope</a>。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>DB 是 SPOF</strong>：Keycloak 所有 state 在 PostgreSQL / MySQL、DB 出事 = IdP 停 = 全公司 SSO 停。跨 AZ replication + PITR + 季度 restore 演練、不是 nice-to-have</li>
<li><strong>Cert / signing key 過期</strong>：自管 IdP 最常見事故、TLS cert 過期擋對外 endpoint、realm signing key 過期讓所有 token 變無效。走 <a href="/blog/backend/knowledge-cards/certificate-rotation-renewal/" data-link-title="Certificate Rotation and Renewal" data-link-desc="說明網站憑證如何安全續期與輪替以避免停機">Certificate Rotation</a> 自動化、過期前 30 天 alert</li>
<li><strong>Cluster split-brain</strong>：Infinispan cache 跨節點同步、網路分區時 session 狀態不一致、user 看起來登入但下一個 request 又被踢出。HA topology 設計要考慮 cache mode（distributed vs replicated）、network 健康監控要 alert split-brain</li>
<li><strong>Major upgrade 卡 DB migration</strong>：每年 major release 帶 schema migration、staging 沒跑過就 production 升級 = 數小時 downtime。upgrade plan 包含 rollback DB snapshot + staging full rehearsal</li>
<li><strong>Custom theme / Authenticator 留漏洞</strong>：theme JS 引入 XSS、custom Authenticator 跳過 MFA、SPI 沒處理 race condition。把 IdP 客製當成 <a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">supply chain</a> 看待、走 code review + 安全測試</li>
<li><strong>Event 沒進 SIEM</strong>：預設只在 Keycloak DB、IdP 出事就拿不到 evidence。Event Listener SPI 接 Kafka / file / SIEM、admin event 跟 login event 各自接 <a href="/blog/backend/knowledge-cards/alert-runbook/" data-link-title="Alert Runbook" data-link-desc="說明告警如何連到可執行的排障與恢復流程">alert runbook</a></li>
<li><strong>Master realm admin 過多</strong>：日常工作不該用 master realm admin、應該在 operational realm 開有限權限 admin。master realm 是 single point of compromise</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>不想自管、要 SaaS IdP</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a> / <a href="/blog/backend/07-security-data-protection/vendors/auth0/" data-link-title="Auth0" data-link-desc="B2C / B2B Customer Identity Provider、Universal Login、Action / Rule hook、屬 Okta 旗下 Customer Identity Cloud">Auth0</a></td>
      </tr>
      <tr>
          <td>AWS-only 員工 SSO</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/aws-iam-identity-center/" data-link-title="AWS IAM Identity Center" data-link-desc="AWS 原生 workforce SSO、前 AWS SSO、Permission Set 跨帳號 access、可串外部 IdP federation">AWS IAM Identity Center</a></td>
      </tr>
      <tr>
          <td>Cloud resource 權限</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google IAM</a> / <a href="/blog/backend/07-security-data-protection/vendors/azure-rbac/" data-link-title="Azure RBAC &#43; Entra ID" data-link-desc="Azure 雙層身份/權限體系、Entra ID（IdP）&#43; Azure RBAC（resource permission）、Conditional Access、PIM、Managed Identity">Azure RBAC</a></td>
      </tr>
      <tr>
          <td>小團隊、Keycloak 太重</td>
          <td>Authentik / Zitadel / Ory Hydra（更輕量 OSS、生態系較小）</td>
      </tr>
      <tr>
          <td>事件偵測（不只 Keycloak event）</td>
          <td>04 SIEM / detection 工具（<a href="/blog/backend/04-observability/" data-link-title="模組四：可觀測性平台" data-link-desc="整理 log、metric、trace、dashboard 與 alert 的後端操作實務">04 observability</a> 跟 07 SIEM 章節）</td>
      </tr>
      <tr>
          <td>Secret / signing key 治理</td>
          <td><a href="/blog/backend/07-security-data-protection/secrets-and-machine-credential-governance/" data-link-title="7.6 秘密管理與機器憑證治理" data-link-desc="以問題驅動方式整理 secret、token、key 與機器身份治理">7.6 秘密管理與機器憑證治理</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Keycloak 完整 SAML / OIDC 規格細節、SPI Java API 文件</li>
<li>Red Hat build of Keycloak 商業支援的差異與授權細節</li>
<li>Keycloak Operator（Kubernetes deployment）的逐步部署教學</li>
<li>LDAP / Active Directory 各種 schema 對應規格</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>Keycloak 沒有直接的廠商級公開事件（OSS 沒有 vendor incident 的對應形態）、自管 IdP 的失效模式以下分兩類整理：跨 vendor 共通的 <em>同構失效</em> 用既有 case 對照、自管 IdP <em>特有</em> 的失效情境補敘事說明、避免案例表變成「同一個 frame 拼四個 case slug」。</p>
<p><strong>對照引用（跨 vendor 同構失效）</strong>：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 Keycloak 的關係</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/cases/azure-ad-identity-control-plane-2021/" data-link-title="7.C3 Azure AD：2021 Identity Control-plane 事件" data-link-desc="身分控制面事件如何影響多服務信任鏈與回復優先序。">Azure AD Identity Control Plane 2021</a></td>
          <td>對所有自管 IdP 的啟示：IdP 控制面故障會外溢到下游所有依賴 SSO 的服務、降級策略（local fallback、cached session）必須事先設計</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/cases/failure-credential-rotation-without-scope/" data-link-title="7.C9 反例：憑證輪替未分 Scope" data-link-desc="憑證輪替若未分域分批，容易造成跨系統連鎖中斷。">Failure: Credential Rotation Without Scope</a></td>
          <td>Keycloak realm signing key rotation 必須分域分批、一次 rotate 全部 realm = 全公司 login 同時失敗</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/uber-2022-mfa-fatigue/" data-link-title="7.R7.1.1 Uber 2022：MFA 疲勞與內部工具擴散" data-link-desc="從社交工程到內部工具存取，拆解身分流程與權限邊界的失效點">Uber 2022 MFA Fatigue</a></td>
          <td>純 push MFA 抗不過 fatigue、Keycloak 自訂 Authentication Flow 應該強制高風險操作走 phishing-resistant factor</td>
      </tr>
  </tbody>
</table>
<p><strong>自管 IdP 特有的失效情境</strong>（沒有對應公開 vendor case、來自自管運維常見事故樣態）：</p>
<ul>
<li><strong>Cert 過期讓全公司 SSO 卡死</strong>：Keycloak signing cert / TLS cert / 後端 DB cert 都自己管、任何一張過期 = login 全停。Okta / Auth0 客戶不會遇到這個失效面（vendor 自己 rotate）— 自管組織必須有 cert lifecycle monitoring（Prometheus exporter + alert）+ 季度 rotate rehearsal、不能等 Let&rsquo;s Encrypt / 公司 PKI 發過期通知才動</li>
<li><strong>Major upgrade 卡 DB migration 變數小時 downtime</strong>：Keycloak 每年 major release 帶 schema migration、若 staging 沒 full rehearsal 就 production 升級、可能遇到 migration 比預期慢 5-10 倍、整個維護視窗炸掉。對照 Okta / Auth0：vendor 自己升、客戶感知是 minutes-level、不是 hours-level</li>
<li><strong>Realm scope 在小規模時用法跟大規模衝突</strong>：<a href="/blog/backend/07-security-data-protection/cases/contrast-identity-governance-by-scale/" data-link-title="7.C10 對照：規模差異下的身份治理" data-link-desc="identity 控制面治理在不同規模服務下的失敗邊界差異。">Contrast: Identity Governance by Scale</a> 揭示不同規模治理模式差異 — 小團隊用單一 realm 順、團隊長大後該拆 realm 卻沒拆、最後 admin compromise blast radius 變整個組織。Keycloak 比 SaaS IdP 更容易踩到、因為 realm 拆分要自己決定時機、沒 vendor 推使用者升級 tier</li>
<li><strong>DB 是 SPOF、自管沒做好 = SSO 跟 DB 一起死</strong>：Keycloak 用 PostgreSQL / MySQL 存 user / session / signing key、DB 出事 = IdP 停。跨 AZ HA + 跨 region DR + 季度 failover 演練是硬性要求、不是 nice-to-have；SaaS IdP 客戶不會遇到這個層次的失效面</li>
</ul>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/identity-access-boundary/" data-link-title="7.2 身分與授權邊界" data-link-desc="以問題驅動方式整理身分、授權、會話與供應商身分鏈">7.2 身分與授權邊界</a>、<a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">7.13 偵測覆蓋率與訊號治理</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta vendor</a>、<a href="/blog/backend/07-security-data-protection/vendors/auth0/" data-link-title="Auth0" data-link-desc="B2C / B2B Customer Identity Provider、Universal Login、Action / Rule hook、屬 Okta 旗下 Customer Identity Cloud">Auth0 vendor</a>、<a href="/blog/backend/07-security-data-protection/vendors/aws-iam-identity-center/" data-link-title="AWS IAM Identity Center" data-link-desc="AWS 原生 workforce SSO、前 AWS SSO、Permission Set 跨帳號 access、可串外部 IdP federation">AWS IAM Identity Center</a></li>
<li>下游：<a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google Cloud IAM</a> / <a href="/blog/backend/07-security-data-protection/vendors/azure-rbac/" data-link-title="Azure RBAC &#43; Entra ID" data-link-desc="Azure 雙層身份/權限體系、Entra ID（IdP）&#43; Azure RBAC（resource permission）、Conditional Access、PIM、Managed Identity">Azure RBAC</a>（Keycloak 之後的 cloud resource permission 層）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（自管 IdP 事件如何 routing 進 IR 流程）</li>
<li>官方：<a href="https://www.keycloak.org/documentation">Keycloak Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>Gatling</title><link>https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/gatling/</link><pubDate>Fri, 15 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/gatling/</guid><description>&lt;p>Gatling 的核心責任是把複雜使用者流程寫成可維護的 JVM simulation。它適合 JVM 生態團隊、強型別 DSL、HTTP / WebSocket / JMS / MQTT 等 scenario，以及需要把 injection profile、assertion、report 與 CI pipeline 綁在一起的壓測流程。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Gatling 是 &lt;em>Scala-origin / 現以 Java DSL 為主流&lt;/em> 的 load testing 工具、跑在 JVM、async / non-blocking engine（基於 Akka / Netty）讓單一 injector node 就能驅動高 RPS。它跟 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/k6/" data-link-title="k6" data-link-desc="用 scriptable scenario 建立 API、protocol 與 CI 友善壓測的效能工程工具">k6&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/jmeter/" data-link-title="Apache JMeter" data-link-desc="用 GUI、plugin 與多 protocol sampler 承接企業壓測資產的效能工程工具">JMeter&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/locust/" data-link-title="Locust" data-link-desc="用 Python user behavior 與 distributed worker 表達高自訂負載模型的效能工程工具">Locust&lt;/a> 的核心差異在 &lt;em>語言生態 + engine efficiency + scenario 表達力&lt;/em>、壓出負載的能力都具備：&lt;/p>
&lt;ul>
&lt;li>vs k6 — k6 走 Go runtime + JavaScript scripting、CLI / Grafana 生態友善；Gatling 走 JVM + Java/Scala/Kotlin DSL、適合既有 JVM 工具鏈與強型別 review&lt;/li>
&lt;li>vs JMeter — JMeter 走 GUI / XML test plan、適合非工程角色協作；Gatling 走 code-first、適合 PR / build pipeline / refactor 工作流&lt;/li>
&lt;li>vs Locust — Locust 走 Python coroutine、scripting 自由度高；Gatling 走 DSL + injection profile、scenario 結構化程度更高&lt;/li>
&lt;li>engine efficiency — async / non-blocking model 讓 Gatling 在單機可推到數萬 RPS、JMeter thread-per-user 在同等資源下 throughput 較低&lt;/li>
&lt;/ul>
&lt;p>產品線分兩層：&lt;em>Gatling OSS&lt;/em>（開源 simulation runner + HTML report）與 &lt;em>Gatling Enterprise&lt;/em>（前身 FrontLine、加上 distributed injector、cluster orchestration、live monitoring、long-term result storage、role-based access）。OSS 適合單機 baseline / CI smoke、Enterprise 適合 cross-region distributed / 大型活動前壓測 / 結果長期治理。&lt;/p>
&lt;h2 id="最短判讀路徑">最短判讀路徑&lt;/h2>
&lt;p>判斷 Gatling 在壓測流程裡是否健康、最少看四件事：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Scala DSL vs Java DSL 版本&lt;/strong>：Gatling 3.7+（2022）正式加 Java DSL、2024 後新專案多走 Java DSL；舊 Scala simulation 仍可跑、但團隊要決定 &lt;em>維持 Scala 還是漸進改寫 Java&lt;/em>、避免雙語言治理&lt;/li>
&lt;li>&lt;strong>Injection profile 設計&lt;/strong>：simulation 是否明確區分 &lt;em>open model&lt;/em>（&lt;code>rampUsersPerSec&lt;/code> / &lt;code>constantUsersPerSec&lt;/code>、模擬真實 arrival）vs &lt;em>closed model&lt;/em>（&lt;code>atOnceUsers&lt;/code> / &lt;code>rampUsers&lt;/code>、模擬 fixed user pool），對應 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/workload-modeling/" data-link-title="9.2 Workload Modeling" data-link-desc="把 production traffic shape 翻成可重播的壓測模型">9.2 Workload Modeling&lt;/a> 的 traffic shape&lt;/li>
&lt;li>&lt;strong>Assertion gate&lt;/strong>：simulation 是否有 &lt;code>assertions { global.responseTime.percentile3.lt(500) }&lt;/code> 這類 hard gate、CI 跑完直接 fail build；沒 assertion 的 simulation 只是壓測、不是 release gate&lt;/li>
&lt;li>&lt;strong>Enterprise vs OSS 邊界&lt;/strong>：是否清楚知道哪些能力只 Enterprise 有（distributed injector / multi-region / long-term result storage / live dashboard）、避免用 OSS 拼湊 Enterprise 級需求&lt;/li>
&lt;/ul>
&lt;h2 id="定位">定位&lt;/h2>
&lt;p>Gatling 適合 code-first 且 JVM 能力強的團隊。當 workload model 需要多步驟 flow、資料 feeder、條件分支、session state 與明確 injection profile，Gatling 能用 simulation 把這些行為寫成工程 artifact。&lt;/p></description><content:encoded><![CDATA[<p>Gatling 的核心責任是把複雜使用者流程寫成可維護的 JVM simulation。它適合 JVM 生態團隊、強型別 DSL、HTTP / WebSocket / JMS / MQTT 等 scenario，以及需要把 injection profile、assertion、report 與 CI pipeline 綁在一起的壓測流程。</p>
<h2 id="服務定位">服務定位</h2>
<p>Gatling 是 <em>Scala-origin / 現以 Java DSL 為主流</em> 的 load testing 工具、跑在 JVM、async / non-blocking engine（基於 Akka / Netty）讓單一 injector node 就能驅動高 RPS。它跟 <a href="/blog/backend/09-performance-capacity/vendors/k6/" data-link-title="k6" data-link-desc="用 scriptable scenario 建立 API、protocol 與 CI 友善壓測的效能工程工具">k6</a> / <a href="/blog/backend/09-performance-capacity/vendors/jmeter/" data-link-title="Apache JMeter" data-link-desc="用 GUI、plugin 與多 protocol sampler 承接企業壓測資產的效能工程工具">JMeter</a> / <a href="/blog/backend/09-performance-capacity/vendors/locust/" data-link-title="Locust" data-link-desc="用 Python user behavior 與 distributed worker 表達高自訂負載模型的效能工程工具">Locust</a> 的核心差異在 <em>語言生態 + engine efficiency + scenario 表達力</em>、壓出負載的能力都具備：</p>
<ul>
<li>vs k6 — k6 走 Go runtime + JavaScript scripting、CLI / Grafana 生態友善；Gatling 走 JVM + Java/Scala/Kotlin DSL、適合既有 JVM 工具鏈與強型別 review</li>
<li>vs JMeter — JMeter 走 GUI / XML test plan、適合非工程角色協作；Gatling 走 code-first、適合 PR / build pipeline / refactor 工作流</li>
<li>vs Locust — Locust 走 Python coroutine、scripting 自由度高；Gatling 走 DSL + injection profile、scenario 結構化程度更高</li>
<li>engine efficiency — async / non-blocking model 讓 Gatling 在單機可推到數萬 RPS、JMeter thread-per-user 在同等資源下 throughput 較低</li>
</ul>
<p>產品線分兩層：<em>Gatling OSS</em>（開源 simulation runner + HTML report）與 <em>Gatling Enterprise</em>（前身 FrontLine、加上 distributed injector、cluster orchestration、live monitoring、long-term result storage、role-based access）。OSS 適合單機 baseline / CI smoke、Enterprise 適合 cross-region distributed / 大型活動前壓測 / 結果長期治理。</p>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Gatling 在壓測流程裡是否健康、最少看四件事：</p>
<ul>
<li><strong>Scala DSL vs Java DSL 版本</strong>：Gatling 3.7+（2022）正式加 Java DSL、2024 後新專案多走 Java DSL；舊 Scala simulation 仍可跑、但團隊要決定 <em>維持 Scala 還是漸進改寫 Java</em>、避免雙語言治理</li>
<li><strong>Injection profile 設計</strong>：simulation 是否明確區分 <em>open model</em>（<code>rampUsersPerSec</code> / <code>constantUsersPerSec</code>、模擬真實 arrival）vs <em>closed model</em>（<code>atOnceUsers</code> / <code>rampUsers</code>、模擬 fixed user pool），對應 <a href="/blog/backend/09-performance-capacity/workload-modeling/" data-link-title="9.2 Workload Modeling" data-link-desc="把 production traffic shape 翻成可重播的壓測模型">9.2 Workload Modeling</a> 的 traffic shape</li>
<li><strong>Assertion gate</strong>：simulation 是否有 <code>assertions { global.responseTime.percentile3.lt(500) }</code> 這類 hard gate、CI 跑完直接 fail build；沒 assertion 的 simulation 只是壓測、不是 release gate</li>
<li><strong>Enterprise vs OSS 邊界</strong>：是否清楚知道哪些能力只 Enterprise 有（distributed injector / multi-region / long-term result storage / live dashboard）、避免用 OSS 拼湊 Enterprise 級需求</li>
</ul>
<h2 id="定位">定位</h2>
<p>Gatling 適合 code-first 且 JVM 能力強的團隊。當 workload model 需要多步驟 flow、資料 feeder、條件分支、session state 與明確 injection profile，Gatling 能用 simulation 把這些行為寫成工程 artifact。</p>
<p>這個定位讓 Gatling 接到 <a href="/blog/backend/09-performance-capacity/workload-modeling/" data-link-title="9.2 Workload Modeling" data-link-desc="把 production traffic shape 翻成可重播的壓測模型">9.2 Workload Modeling</a> 與 <a href="/blog/backend/09-performance-capacity/saturation-discovery/" data-link-title="9.4 Saturation Discovery" data-link-desc="找出 throughput plateau 與 latency knee 的方法">9.4 Saturation Discovery</a>。它的價值在於把 traffic shape 寫進 injection profile，讓 ramp-up、constant users、stress peak 與 soak test 都能被版本化。</p>
<h2 id="適用場景">適用場景</h2>
<p>JVM 團隊適合用 Gatling 承接壓測。Java、Scala 或 Kotlin 團隊能把 simulation 當成一般程式碼 review，並用既有 build、dependency、CI 與 artifact 流程維護。</p>
<p>複雜 scenario 適合用 Gatling 表達。登入、搜尋、加入購物車、checkout、payment mock、order query 這類 multi-step flow 可以用 session 與 feeder 管理資料。</p>
<p>高品質 report 適合 release review。Gatling 的 report 能幫 reviewer 看到 response time distribution、request group、error 與 injection profile，適合在 release gate 中保留可讀證據。</p>
<h2 id="選型判準">選型判準</h2>
<table>
  <thead>
      <tr>
          <th>判準</th>
          <th>Gatling 的價值</th>
          <th>需要補的能力</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>JVM DSL</td>
          <td>simulation 可 code review</td>
          <td>Scala / Java / Kotlin 維護能力</td>
      </tr>
      <tr>
          <td>Injection profile</td>
          <td>負載階段可精準表達</td>
          <td>production traffic shape 校正</td>
      </tr>
      <tr>
          <td>Session / feeder</td>
          <td>多步驟資料與狀態容易管理</td>
          <td>測試資料治理與敏感資料遮罩</td>
      </tr>
      <tr>
          <td>Report</td>
          <td>release review 可讀性高</td>
          <td>長期趨勢儲存與 cross-run comparison</td>
      </tr>
  </tbody>
</table>
<p>JVM DSL 價值來自可維護性。壓測 scenario 如果需要被長期 review、重構、抽 helper 或接 build pipeline，Gatling 的 code-first workflow 會比 GUI test plan 更適合工程團隊。</p>
<p>Injection profile 價值來自負載形狀精準。團隊可以把 steady load、spike、ramp、open model 與 closed model 放到 simulation 中，讓 <a href="/blog/backend/09-performance-capacity/saturation-discovery/" data-link-title="9.4 Saturation Discovery" data-link-desc="找出 throughput plateau 與 latency knee 的方法">9.4 Saturation Discovery</a> 的 knee point 判讀更可重現。</p>
<h2 id="跟其他工具的取捨">跟其他工具的取捨</h2>
<p>Gatling 和 k6 的主要差異是語言與生態。Gatling 適合 JVM 團隊與強型別 simulation；k6 適合 JavaScript-style scripting、CLI workflow 與 Grafana 生態。</p>
<p>Gatling 和 JMeter 的主要差異是維護模式。Gatling 偏 code review、build pipeline 與 simulation abstraction；JMeter 偏 GUI、plugin 與跨角色測試資產。</p>
<p>Gatling 和 Locust 的主要差異是自訂語言。Locust 適合 Python 團隊與任意 Python client；Gatling 適合 JVM 團隊與 report / injection profile 的結構化壓測。</p>
<p>Gatling 和 Vegeta 的主要差異是 scenario 深度。Vegeta 適合快速 HTTP pressure test；Gatling 適合需要 session、feeder、assertion 與多 request group 的長期測試。</p>
<h2 id="操作成本">操作成本</h2>
<p>Gatling 的主要成本是 JVM 團隊能力。非 JVM 團隊要承擔語言、build tool、dependency 與 simulation pattern 的學習成本；這個成本只有在 scenario 複雜度夠高時才划算。</p>
<p>測試資料成本來自 feeder 與 session。多步驟 flow 需要 account、cart、order、token、region 與 tenant 資料，資料過期或分布偏差會讓壓測結果失真。</p>
<p>Enterprise / distributed 成本要提前評估。單機 Gatling 適合中小型 baseline；跨 region、大型活動前驗證或長時間 soak test 需要 runner topology、結果集中與雲端成本治理。</p>
<h2 id="evidence-package">Evidence Package</h2>
<p>Gatling 結果應回寫到 evidence package。最小欄位包括 simulation version、injection profile、feeder source、target environment、assertion、response time distribution、error rate、throughput、target service saturation metric、known gap 與 owner。</p>
<table>
  <thead>
      <tr>
          <th>欄位</th>
          <th>Gatling 證據來源</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Source</td>
          <td>simulation code、HTML report、dashboard link</td>
      </tr>
      <tr>
          <td>Time range</td>
          <td>test start / end</td>
      </tr>
      <tr>
          <td>Query link</td>
          <td>APM / metrics / logs 查詢連結</td>
      </tr>
      <tr>
          <td>Data quality</td>
          <td>feeder freshness、scenario coverage</td>
      </tr>
      <tr>
          <td>Confidence</td>
          <td>production similarity、runner capacity</td>
      </tr>
      <tr>
          <td>Known gap</td>
          <td>未覆蓋 flow、資料偏差、下游 mock 限制</td>
      </tr>
  </tbody>
</table>
<p>Evidence package 的核心用途是讓 simulation 可回放。Reviewer 要能從 report 回到 injection profile、scenario code、feeder 與目標環境，才有辦法判斷一次壓測是容量訊號還是測試設計偏差。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Gatling</th>
          <th>k6</th>
          <th>JMeter</th>
          <th>Locust</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>語言 / DSL</td>
          <td>Java / Kotlin / Scala DSL（JVM）</td>
          <td>JavaScript（Go runtime）</td>
          <td>GUI / XML test plan（JVM）</td>
          <td>Python（coroutine / gevent）</td>
      </tr>
      <tr>
          <td>Engine model</td>
          <td>Async / non-blocking（Akka + Netty）</td>
          <td>Async（Go goroutine）</td>
          <td>Thread-per-user（同步）</td>
          <td>Async coroutine</td>
      </tr>
      <tr>
          <td>單機 RPS 上限</td>
          <td>高（數萬 RPS）</td>
          <td>高（數萬 RPS）</td>
          <td>中（thread overhead）</td>
          <td>中（GIL + coroutine）</td>
      </tr>
      <tr>
          <td>Scenario 表達力</td>
          <td>強（session / feeder / 條件分支內建）</td>
          <td>中（JS function 自寫）</td>
          <td>中（GUI 拖拉 + listener）</td>
          <td>中（Python class + task）</td>
      </tr>
      <tr>
          <td>Report quality</td>
          <td>高（HTML report 內建、distribution / group 詳細）</td>
          <td>中（CLI 摘要 + Grafana 串接）</td>
          <td>中（GUI listener、不適合 headless）</td>
          <td>中（web UI 即時、無 historical）</td>
      </tr>
      <tr>
          <td>CI integration</td>
          <td>強（Maven / Gradle / sbt + assertion gate）</td>
          <td>強（CLI + JSON output）</td>
          <td>中（CLI mode 可、但 GUI-first）</td>
          <td>強（CLI + Python ecosystem）</td>
      </tr>
      <tr>
          <td>Distributed</td>
          <td>OSS 自建 / Enterprise 內建</td>
          <td>k6 Cloud / OSS 自建</td>
          <td>自建（master-slave）</td>
          <td>自建（master-worker）</td>
      </tr>
      <tr>
          <td>商業版本</td>
          <td>Gatling Enterprise（前 FrontLine）</td>
          <td>Grafana Cloud k6</td>
          <td>無（純 OSS）</td>
          <td>無（純 OSS）</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>JVM 團隊、複雜 scenario、release gate、高 RPS efficiency</td>
          <td>全棧團隊、CLI workflow、Grafana 生態</td>
          <td>跨角色團隊、legacy test plan、protocol 多樣</td>
          <td>Python 團隊、自訂 client、輕量 setup</td>
      </tr>
  </tbody>
</table>
<p>選 Gatling 的核心訴求：<em>JVM 團隊 + 複雜 scenario（session / feeder / 多 group）+ 高 RPS 單機效率 + HTML report 作為 release gate 證據</em>。Java DSL 在 2024 後降低了 Scala 學習門檻、讓 Java/Kotlin 後端團隊不必再為了壓測導入 Scala。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Gatling Enterprise（前 FrontLine）</strong>：商業版加 <em>distributed injector cluster</em>（跨 region / 跨 cloud 推大型負載）、<em>live monitoring dashboard</em>（real-time RPS / response time 趨勢、不用等 simulation 結束看 HTML）、<em>long-term result storage</em>（cross-run comparison、retention policy）、<em>role-based access</em>（QA / dev / SRE 不同權限）。對只跑單機 baseline 的團隊 OSS 已夠；要跑黑五 / 春晚級活動前壓測或多 region 同時施壓、需要 Enterprise 或自建 distributed topology。</p>
<p><strong>Java DSL 取代 Scala 成主流（2022-2024）</strong>：Gatling 3.7（2022）正式釋出 Java DSL、3.9+ 文件 Java / Kotlin / Scala 三語並列、2024 後新教學多以 Java 為主。對 Java 後端團隊降低 onboarding 成本、但要注意 <em>Gatling 2.x → 3.x</em> 的 Scala syntax 不向後相容（<code>scenario</code> builder、<code>http</code> config、<code>feed</code> 用法都改寫）— 舊 simulation 升級時等於改寫一遍。</p>
<p><strong>Distributed execution（OSS）</strong>：OSS 沒有內建 cluster orchestration、要靠 <em>multiple injector + result aggregation</em>：每台 injector 跑同一份 simulation（按 user count 切割）、結束後把 <code>simulation.log</code> 蒐集到一處用 <code>gatling.sh</code> 重跑 report stage。常見補位是用 Kubernetes Job + 共享 PVC、或直接走 Gatling Enterprise。</p>
<p><strong>HTML report 與 release gate</strong>：simulation 跑完自動產 HTML report、含 <em>response time percentile distribution</em>（mean / p50 / p95 / p99 / max）、<em>per-request-group breakdown</em>、<em>active users over time</em>、<em>error log</em>。release gate 的標準做法是：CI job 跑 simulation → assertion gate fail 直接 break build → HTML report 存成 build artifact 供 reviewer 翻查、配合 <a href="/blog/backend/04-observability/observability-evidence-package/" data-link-title="4.20 Observability Evidence Package" data-link-desc="把 log、metric、trace、audit 與資料品質限制包成可交接證據">Evidence Package</a> 治理。</p>
<p><strong>CI integration 模式</strong>：Jenkins / GitLab CI / GitHub Actions 都靠 <code>mvn gatling:test</code> / <code>gradle gatlingRun</code> / <code>sbt gatling:test</code> 入口、CI 設定 <em>baseline simulation</em>（每 PR 跑、catch regression）+ <em>release simulation</em>（release branch / nightly 跑、長時間 soak）。staging environment 跑壓測時要隔離噪音來源（其他 QA 流量 / cron job）、否則 RPS 數字會被污染。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Scala learning curve 拖累進度</strong>：團隊沒人會 Scala、被 implicit / case class / pattern match 卡住 — 改用 Java DSL（3.7+）或 Kotlin DSL、保留 Gatling 表達力但去除 Scala 學習成本</li>
<li><strong>Gatling 2.x → 3.x 升級 simulation 全紅</strong>：<code>bootstrap</code> import path / <code>scenario</code> builder API / <code>feed</code> 語法都變了 — 走 <em>新專案直接 3.x、舊專案維持 2.x</em> 雙軌、或安排專門 sprint 改寫、避免邊跑邊踩雷</li>
<li><strong>JVM heap OOM / GC pause 拖慢 RPS</strong>：高 RPS 下 default heap 不夠、Young Gen GC 頻繁 — 調 <code>-Xmx4G -Xms4G</code>、用 G1GC / ZGC、監控 injector 的 GC log 跟 CPU、不是只看 target service</li>
<li><strong>Injection profile 設計錯導致誤判 saturation</strong>：用 <code>atOnceUsers(1000)</code> 壓 closed model 但實際 traffic 是 open arrival、結果 knee point 找錯 — 看 production traffic shape、open model 用 <code>constantUsersPerSec</code> / <code>rampUsersPerSec</code>、closed model 才用 <code>atOnceUsers</code></li>
<li><strong>Single injector node 撞 client-side bottleneck</strong>：injector CPU / network / file descriptor / source port 用滿、看起來 target saturate 其實是 injector saturate — 監控 injector resource、scale out 成 distributed 或走 Enterprise</li>
<li><strong>Feeder data 過期 / 分布偏差</strong>：用同一份 <code>users.csv</code> 反覆壓、cache hit rate 失真、production 看不到的 cache miss 路徑沒被測 — feeder 走 <code>random</code> / <code>shuffle</code>、定期 regenerate、覆蓋 long-tail key</li>
<li><strong>HTML report 看起來綠但 production 出事</strong>：assertion gate 只設 average response time、p99 / error rate 沒設、release 後尖峰時段才爆 — assertion 要明確設 p95 / p99 + error rate threshold、不只看 mean</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>Gatling 適合回寫多步驟與多負載模型案例。它可接 <a href="/blog/backend/09-performance-capacity/cases/fanduel-dual-peak-betting-streaming/" data-link-title="9.C28 FanDuel：體育直播 &#43; 投注的雙重峰值" data-link-desc="FanDuel 3.5M MAU、Super Bowl 期間擴容 5-10 倍、用 AWS Local Zones &#43; Wavelength &#43; Outposts 處理 20&#43; 州的雙重峰值">9.C28 FanDuel 雙峰 workload</a> 的直播與投注雙模型、<a href="/blog/backend/09-performance-capacity/cases/seatgeek-virtual-waiting-room/" data-link-title="9.C16 SeatGeek：DynamoDB &#43; Lambda 打造的虛擬等候室" data-link-desc="SeatGeek 用 DynamoDB 4 張表 &#43; Lambda Bouncer 實作 flash-sale 限流排隊機制、取代第三方 waiting room 服務">9.C16 SeatGeek waiting room</a> 的 token / admission flow、<a href="/blog/backend/09-performance-capacity/cases/bookmyshow-indian-ticketing-platform/" data-link-title="9.C17 BookMyShow：印度年售 2 億張票的資料架構現代化" data-link-desc="BookMyShow 從 15 年自建 analytics 遷移到 AWS modern data architecture、4 個月完成、分析成本下降 80%">9.C17 BookMyShow ticketing</a> 的售票流程壓力、<a href="/blog/backend/09-performance-capacity/cases/draftkings-aurora-financial-ledger/" data-link-title="9.C4 DraftKings：Aurora 撐 100 萬 ops/min 的體育博彩金融帳本" data-link-desc="DraftKings 用 Aurora MySQL 跑體育博彩金融帳本、Super Bowl 流量 &#43;50% 不影響延遲">9.C4 DraftKings Aurora 金融帳本</a> 的「比賽期讀爆量 + payout 時寫爆量」雙峰錯位，以及 <a href="/blog/backend/09-performance-capacity/cases/gr8-tech-ai-predicted-betting-peak/" data-link-title="9.C2 GR8 Tech：AI 預測式自動擴容下的體育博彩高峰" data-link-desc="AI 預測 &#43; EKS 自動擴容怎麼在 25ms p95 下承載 54000 TPS 體育博彩峰值流量">9.C2 GR8 Tech</a> 的「投注 / 結算 / 賠率更新」三類請求 group 的 injection profile。</p>
<p>這些案例的重點是 scenario 與 injection profile。Gatling 頁引用案例時，要把業務流程拆成 request group、session state、feeder、assertion 與 stop condition — 例如 DraftKings 雙峰錯位要寫成兩個 scenario 平行注入、各自有獨立 assertion budget。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/09-performance-capacity/workload-modeling/" data-link-title="9.2 Workload Modeling" data-link-desc="把 production traffic shape 翻成可重播的壓測模型">9.2 Workload Modeling</a></li>
<li>上游：<a href="/blog/backend/09-performance-capacity/load-test-tooling/" data-link-title="9.3 壓測工具選型" data-link-desc="k6 / JMeter / Gatling / Locust / Vegeta / Production Replay 的工程選型">9.3 壓測工具選型</a></li>
<li>上游：<a href="/blog/backend/09-performance-capacity/saturation-discovery/" data-link-title="9.4 Saturation Discovery" data-link-desc="找出 throughput plateau 與 latency knee 的方法">9.4 Saturation Discovery</a></li>
<li>平行：<a href="/blog/backend/09-performance-capacity/vendors/k6/" data-link-title="k6" data-link-desc="用 scriptable scenario 建立 API、protocol 與 CI 友善壓測的效能工程工具">k6</a>、<a href="/blog/backend/09-performance-capacity/vendors/jmeter/" data-link-title="Apache JMeter" data-link-desc="用 GUI、plugin 與多 protocol sampler 承接企業壓測資產的效能工程工具">JMeter</a>、<a href="/blog/backend/09-performance-capacity/vendors/locust/" data-link-title="Locust" data-link-desc="用 Python user behavior 與 distributed worker 表達高自訂負載模型的效能工程工具">Locust</a></li>
<li>官方：<a href="https://docs.gatling.io/">Gatling documentation</a></li>
</ul>
]]></content:encoded></item><item><title>MongoDB</title><link>https://tarrragon.github.io/blog/backend/01-database/vendors/mongodb/</link><pubDate>Wed, 13 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/01-database/vendors/mongodb/</guid><description>&lt;p>MongoDB 是 document database 的事實標準。schema flexibility、aggregation pipeline、跨雲 managed（Atlas）讓它成為許多 startup 的 default 選擇。Microsoft 365、Disney+ 早期、Uber 等大規模平台都從 MongoDB 起家，後來依 workload 壓力把部分路徑遷移到 KV / 雲商專屬服務（Cosmos DB、DynamoDB）。&lt;/p>
&lt;h2 id="教學路線document-shape-與-schema-governance">教學路線：Document shape 與 schema governance&lt;/h2>
&lt;p>MongoDB 服務頁的教學目標是把 document model、schema flexibility、index、aggregation pipeline 與 sharding 放回資料形狀治理。讀者讀完後要能判斷資料是否適合 aggregate root，並知道 schema governance 如何影響長期維護成本。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>學習段&lt;/th>
 &lt;th>核心問題&lt;/th>
 &lt;th>對應段落&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Document shape&lt;/td>
 &lt;td>哪些資料適合 aggregate root 與 nested document&lt;/td>
 &lt;td>定位、適用場景&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Schema governance&lt;/td>
 &lt;td>schema flexibility 如何搭配 validation、版本與 migration&lt;/td>
 &lt;td>容量規劃要點、預計實作話題&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Query / index&lt;/td>
 &lt;td>index、aggregation pipeline、ad-hoc query 如何影響成本&lt;/td>
 &lt;td>容量特性、常見陷阱&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Sharding&lt;/td>
 &lt;td>shard key、chunk、balancer 如何把資料形狀變容量問題&lt;/td>
 &lt;td>容量規劃要點、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">Database Sharding&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>替代路由&lt;/td>
 &lt;td>何時轉 PostgreSQL、DynamoDB、Cosmos DB 或 search&lt;/td>
 &lt;td>不適用場景、跟其他 vendor 的取捨&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="定位json-document--跨雲彈性">定位：JSON document + 跨雲彈性&lt;/h2>
&lt;p>MongoDB 是以 document model 為主體的 DB。PostgreSQL JSONB 適合「SQL 為主、少量半結構化欄位」；MongoDB 則把 BSON document、aggregation pipeline、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">database sharding&lt;/a> 與 schema governance 放在核心設計裡。近年版本加入 time series、change streams、queryable encryption、CSFLE 等能力。&lt;/p>
&lt;p>選 MongoDB 的核心訴求：document model 是主要 use case、需要跨雲 managed（Atlas）、想避免 vendor lock-in（也可自管）。&lt;/p>
&lt;h2 id="容量特性">容量特性&lt;/h2>
&lt;p>&lt;strong>單一 instance 吞吐&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>一般 m5.4xlarge：5K-15K WPS（依 doc size、index）&lt;/li>
&lt;li>高階 instance + tuning：30K-50K WPS&lt;/li>
&lt;li>超過此級別 → sharding&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Sharding&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>MongoDB 原生支援 sharded cluster&lt;/li>
&lt;li>mongos router + config servers + shard&lt;/li>
&lt;li>MongoDB sharding 要主動設計 shard key，並和 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/hot-partition/" data-link-title="Hot Partition" data-link-desc="說明分散式 KV / OLTP 中、單一 partition 流量遠超其他的容量問題">Hot Partition&lt;/a> 風險一起看&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Replication&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>Replica set（primary + secondary、async）&lt;/li>
&lt;li>跨 region 通常 async&lt;/li>
&lt;li>自動 failover &amp;lt; 30 秒（mongod 內建）&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Storage&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>單一 collection 沒有官方上限、但 shard key resharding 過去版本是大手術（4.4+ 支援 reshardCollection）&lt;/li>
&lt;/ul>
&lt;h2 id="適用場景">適用場景&lt;/h2>
&lt;p>&lt;strong>1. Document model 主要 workload&lt;/strong>：&lt;/p></description><content:encoded><![CDATA[<p>MongoDB 是 document database 的事實標準。schema flexibility、aggregation pipeline、跨雲 managed（Atlas）讓它成為許多 startup 的 default 選擇。Microsoft 365、Disney+ 早期、Uber 等大規模平台都從 MongoDB 起家，後來依 workload 壓力把部分路徑遷移到 KV / 雲商專屬服務（Cosmos DB、DynamoDB）。</p>
<h2 id="教學路線document-shape-與-schema-governance">教學路線：Document shape 與 schema governance</h2>
<p>MongoDB 服務頁的教學目標是把 document model、schema flexibility、index、aggregation pipeline 與 sharding 放回資料形狀治理。讀者讀完後要能判斷資料是否適合 aggregate root，並知道 schema governance 如何影響長期維護成本。</p>
<table>
  <thead>
      <tr>
          <th>學習段</th>
          <th>核心問題</th>
          <th>對應段落</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Document shape</td>
          <td>哪些資料適合 aggregate root 與 nested document</td>
          <td>定位、適用場景</td>
      </tr>
      <tr>
          <td>Schema governance</td>
          <td>schema flexibility 如何搭配 validation、版本與 migration</td>
          <td>容量規劃要點、預計實作話題</td>
      </tr>
      <tr>
          <td>Query / index</td>
          <td>index、aggregation pipeline、ad-hoc query 如何影響成本</td>
          <td>容量特性、常見陷阱</td>
      </tr>
      <tr>
          <td>Sharding</td>
          <td>shard key、chunk、balancer 如何把資料形狀變容量問題</td>
          <td>容量規劃要點、<a href="/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">Database Sharding</a></td>
      </tr>
      <tr>
          <td>替代路由</td>
          <td>何時轉 PostgreSQL、DynamoDB、Cosmos DB 或 search</td>
          <td>不適用場景、跟其他 vendor 的取捨</td>
      </tr>
  </tbody>
</table>
<h2 id="定位json-document--跨雲彈性">定位：JSON document + 跨雲彈性</h2>
<p>MongoDB 是以 document model 為主體的 DB。PostgreSQL JSONB 適合「SQL 為主、少量半結構化欄位」；MongoDB 則把 BSON document、aggregation pipeline、<a href="/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">database sharding</a> 與 schema governance 放在核心設計裡。近年版本加入 time series、change streams、queryable encryption、CSFLE 等能力。</p>
<p>選 MongoDB 的核心訴求：document model 是主要 use case、需要跨雲 managed（Atlas）、想避免 vendor lock-in（也可自管）。</p>
<h2 id="容量特性">容量特性</h2>
<p><strong>單一 instance 吞吐</strong>：</p>
<ul>
<li>一般 m5.4xlarge：5K-15K WPS（依 doc size、index）</li>
<li>高階 instance + tuning：30K-50K WPS</li>
<li>超過此級別 → sharding</li>
</ul>
<p><strong>Sharding</strong>：</p>
<ul>
<li>MongoDB 原生支援 sharded cluster</li>
<li>mongos router + config servers + shard</li>
<li>MongoDB sharding 要主動設計 shard key，並和 <a href="/blog/backend/knowledge-cards/hot-partition/" data-link-title="Hot Partition" data-link-desc="說明分散式 KV / OLTP 中、單一 partition 流量遠超其他的容量問題">Hot Partition</a> 風險一起看</li>
</ul>
<p><strong>Replication</strong>：</p>
<ul>
<li>Replica set（primary + secondary、async）</li>
<li>跨 region 通常 async</li>
<li>自動 failover &lt; 30 秒（mongod 內建）</li>
</ul>
<p><strong>Storage</strong>：</p>
<ul>
<li>單一 collection 沒有官方上限、但 shard key resharding 過去版本是大手術（4.4+ 支援 reshardCollection）</li>
</ul>
<h2 id="適用場景">適用場景</h2>
<p><strong>1. Document model 主要 workload</strong>：</p>
<ul>
<li>schema 變化頻繁的早期產品</li>
<li>nested document 自然表達領域模型（訂單含多個 item、用戶含多個 preference）</li>
<li>對應案例：<a href="/blog/backend/09-performance-capacity/cases/microsoft-365-cosmos-db-analytics/" data-link-title="9.C30 Microsoft 365：從 MongoDB 遷移到 Cosmos DB 的分析平台" data-link-desc="Microsoft 365 把使用分析平台從 MongoDB 遷移到 Cosmos DB、planet-scale 全球分散式分析">9.C30 Microsoft 365</a> — 從 MongoDB 遷移到 Cosmos DB MongoDB API、保留 document model</li>
</ul>
<p><strong>2. Aggregation pipeline 重 workload</strong>：</p>
<ul>
<li>複雜的 $group / $match / $project chain</li>
<li>報表、analytics、ETL prep</li>
<li>比 RDBMS 寫複雜 query 更直觀（對某些 team）</li>
</ul>
<p><strong>3. 跨雲 managed（Atlas）</strong>：</p>
<ul>
<li>MongoDB Atlas 跨 AWS / GCP / Azure</li>
<li>跟 DynamoDB（AWS only）、Cosmos DB（Azure only）、Spanner（GCP only）相反</li>
<li>適合多雲策略、避免單一 vendor lock-in</li>
</ul>
<p><strong>4. Time series workload（6.0+）</strong>：</p>
<ul>
<li>time series collection 專屬優化</li>
<li>不過 InfluxDB / TimescaleDB 仍是更專業選擇</li>
</ul>
<p><strong>5. 已有 MongoDB 生態 + 想轉移操作責任</strong>：</p>
<ul>
<li>Atlas 提供 backup、failover、monitoring、auto-scale</li>
<li>想把 MongoDB DBA / SRE 操作責任交給 Atlas</li>
</ul>
<h2 id="不適用場景">不適用場景</h2>
<p><strong>1. 強 ACID multi-document transaction</strong>：</p>
<ul>
<li>MongoDB Transaction 支援多 document、但跨 shard 有性能影響</li>
<li>高頻金融交易仍建議 SQL 系統</li>
<li>替代：PostgreSQL、Aurora、Spanner</li>
</ul>
<p><strong>2. 複雜 JOIN</strong>：</p>
<ul>
<li>MongoDB <code>$lookup</code> 適合少量相鄰資料，JOIN-heavy workload 應回 SQL 系統</li>
<li>schema design 階段要把常用讀取路徑 denormalize 成 document shape</li>
<li>替代：SQL 系統做 JOIN-heavy workload</li>
</ul>
<p><strong>3. 純 KV + sub-ms latency</strong>：</p>
<ul>
<li>MongoDB document model 比 KV 多一層 BSON parsing</li>
<li>替代：Redis、DynamoDB、Bigtable</li>
</ul>
<p><strong>4. 大規模 OLAP</strong>：</p>
<ul>
<li>aggregation 對中等資料量還行、TB 級不適合</li>
<li>替代：ClickHouse、BigQuery、Spark on Delta Lake</li>
</ul>
<p><strong>5. 嚴格資料模型 + schema enforcement</strong>：</p>
<ul>
<li>MongoDB schema flexibility 可能導致 production data inconsistency</li>
<li>替代：SQL DB（schema 強制）+ JSONB column 處理半結構化</li>
</ul>
<h2 id="跟其他-vendor-的取捨">跟其他 vendor 的取捨</h2>
<p><strong>vs Cosmos DB MongoDB API</strong>：</p>
<ul>
<li>MongoDB Atlas：跨雲、原生 MongoDB 行為</li>
<li>Cosmos DB MongoDB API：Azure-only、global distribution + 5 <a href="/blog/backend/knowledge-cards/consistency-level/" data-link-title="Consistency Level" data-link-desc="資料系統對讀寫一致性語意的可選擇層級">consistency level</a>s</li>
<li>選 MongoDB Atlas：跨雲、需要原生 MongoDB features</li>
<li>選 Cosmos DB：Azure 生態、需要更好 global distribution</li>
<li>對應案例：<a href="/blog/backend/09-performance-capacity/cases/microsoft-365-cosmos-db-analytics/" data-link-title="9.C30 Microsoft 365：從 MongoDB 遷移到 Cosmos DB 的分析平台" data-link-desc="Microsoft 365 把使用分析平台從 MongoDB 遷移到 Cosmos DB、planet-scale 全球分散式分析">9.C30 Microsoft 365</a> — 從 MongoDB 遷到 Cosmos DB MongoDB API，主要保留 document model</li>
</ul>
<p><strong>vs DynamoDB</strong>：</p>
<ul>
<li>MongoDB：document model、aggregation 強、跨雲</li>
<li>DynamoDB：KV / single-table design、AWS 整合、5 個 9 SLA</li>
<li>選 MongoDB：document 為主、跨雲</li>
<li>選 DynamoDB：KV 為主、AWS 生態</li>
<li>詳見 <a href="/blog/backend/01-database/vendors/dynamodb/" data-link-title="DynamoDB" data-link-desc="AWS managed key-value、partition-based scaling、9000 萬 RPS sustained 實戰證據">DynamoDB vendor page</a> 對比段</li>
</ul>
<p><strong>vs PostgreSQL JSONB</strong>：</p>
<ul>
<li>MongoDB：document 為主、schema-less</li>
<li>PostgreSQL：SQL 為主、JSONB 補充</li>
<li>選 MongoDB：document 占主要 schema</li>
<li>選 PostgreSQL JSONB：主要結構化、少量半結構化欄位</li>
</ul>
<p><strong>vs Couchbase / Couchdb / Firestore</strong>：</p>
<ul>
<li>Couchbase：MongoDB 替代、有 N1QL（SQL-like）</li>
<li>CouchDB：偏小規模、master-master replication</li>
<li>Firestore：GCP-only、realtime updates</li>
<li>MongoDB 在這群裡是生態最廣的</li>
</ul>
<p><strong>vs Elasticsearch 作為 search 替代</strong>：</p>
<ul>
<li>兩者分屬不同類別：MongoDB 是 OLTP / document、Elasticsearch 是 search + analytics</li>
<li>通常搭配用：MongoDB 主、Elasticsearch 處理 full-text search</li>
</ul>
<h2 id="容量規劃要點">容量規劃要點</h2>
<p><strong>1. Shard key 設計是命脈</strong>：</p>
<ul>
<li>跟 DynamoDB partition key 同樣關鍵</li>
<li>不均勻 → hot shard、實際容量達不到名義</li>
<li>4.4+ 可以 reshard、但仍是大手術</li>
</ul>
<p><strong>2. Replica set 是 HA 基礎</strong>：</p>
<ul>
<li>至少 3 個 member（1 primary + 2 secondary）</li>
<li>secondary 可 read（read preference）但要注意 lag</li>
<li>failover 通常 &lt; 30 秒</li>
</ul>
<p><strong>3. Atlas managed 服務</strong>：</p>
<ul>
<li>提供 auto-scaling、auto-backup、跨雲部署</li>
<li>Tier 從 M0（free）到 M700（高階）</li>
<li>Atlas Online Archive 自動把舊資料移到便宜 storage</li>
</ul>
<p><strong>4. Index 限制</strong>：</p>
<ul>
<li>單 collection 最多 64 個 index</li>
<li>compound index 有順序敏感（{a:1, b:1} 跟 {b:1, a:1} 不同）</li>
<li>TTL index 自動 expire 過期 document</li>
</ul>
<p><strong>5. Change streams（CDC）</strong>：</p>
<ul>
<li>4.0+ 提供原生 change streams</li>
<li>對接 Kafka / event bus 做 event sourcing</li>
</ul>
<h2 id="anti-recommendation-與升級路由">Anti-recommendation 與升級路由</h2>
<p>MongoDB 的 schema flexibility 會降低早期建模成本，也會把 schema governance 延後到 production。這一段先說何時維持 document model，再說何時升級 Atlas、sharding、Cosmos DB、DynamoDB 或 SQL。</p>
<table>
  <thead>
      <tr>
          <th>機制 / 路線</th>
          <th>維持簡單設計的條件</th>
          <th>升級訊號</th>
          <th>主要引用路徑</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>單一 replica set</td>
          <td>document size 穩定、working set 可控、primary 寫入足夠</td>
          <td>storage / write / working set 接近上限、failover 演練不足</td>
          <td><a href="/blog/backend/knowledge-cards/replication-lag/" data-link-title="Replication Lag" data-link-desc="說明資料副本落後正式來源多久，以及它如何影響讀取正確性">Replication Lag</a>、<a href="/blog/backend/knowledge-cards/rpo/" data-link-title="RPO" data-link-desc="說明恢復點目標如何定義可接受資料損失範圍">RPO</a></td>
      </tr>
      <tr>
          <td>Atlas managed</td>
          <td>團隊仍能管理 backup、upgrade、monitoring 與 scaling</td>
          <td>DBA / SRE 責任想轉交平台、跨雲部署與 backup 成為主要壓力</td>
          <td><a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">Audit Log</a>、<a href="/blog/backend/knowledge-cards/secret-management/" data-link-title="Secret Management" data-link-desc="說明 token、key、password 與憑證如何保存、輪替與撤銷">Secret Management</a></td>
      </tr>
      <tr>
          <td>Sharded cluster</td>
          <td>single replica set 還能承擔容量與維護窗口</td>
          <td>shard key 穩定、tenant / user / region 可分、hot shard 可觀測</td>
          <td><a href="/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">Database Sharding</a>、<a href="/blog/backend/knowledge-cards/hot-partition/" data-link-title="Hot Partition" data-link-desc="說明分散式 KV / OLTP 中、單一 partition 流量遠超其他的容量問題">Hot Partition</a></td>
      </tr>
      <tr>
          <td>Cosmos DB MongoDB API</td>
          <td>Azure 只是部署選項，原生 MongoDB 行為仍重要</td>
          <td>Azure global distribution、multi-region write 或 RU governance 成主題</td>
          <td><a href="/blog/backend/01-database/vendors/cosmosdb/" data-link-title="Azure Cosmos DB" data-link-desc="全球分散式 multi-model DB、5 個 consistency levels、Microsoft 自家 dogfood 證據">Cosmos DB vendor</a></td>
      </tr>
      <tr>
          <td>DynamoDB / KV</td>
          <td>query 仍需要 document traversal 與 aggregation</td>
          <td>access pattern 固定、sub-10ms p99、connection-free scaling 成主題</td>
          <td><a href="/blog/backend/01-database/vendors/dynamodb/" data-link-title="DynamoDB" data-link-desc="AWS managed key-value、partition-based scaling、9000 萬 RPS sustained 實戰證據">DynamoDB vendor</a></td>
      </tr>
      <tr>
          <td>PostgreSQL</td>
          <td>document 是主要資料形狀</td>
          <td>JOIN-heavy、transaction-heavy、schema 約束是主要價值</td>
          <td><a href="/blog/backend/01-database/vendors/postgresql/" data-link-title="PostgreSQL" data-link-desc="多用途 OLTP 主流關聯式資料庫、MVCC、豐富 SQL 特性、是 Aurora / Cosmos DB / Spanner / CockroachDB / Aurora DSQL 的相容目標">PostgreSQL vendor</a></td>
      </tr>
  </tbody>
</table>
<p>MongoDB 的簡單路徑是先把 document boundary 寫清楚。資料可以彈性演進，但 application 仍要知道哪些欄位是正式契約、哪些欄位只是相容期，並用 validation、migration 與 data quality check 管住版本漂移。</p>
<p>Sharding 的升級路徑要等 shard key 與 query shape 足夠穩定。過早切 shard 會把 aggregation、transaction 與 index 成本提前放大；過晚切 shard 則會讓 resharding、chunk migration 與 balancer 壓力進入 production 高峰期。</p>
<h2 id="deep-article已完成">Deep article（已完成）</h2>
<p>本批 6 篇 deep article 已完成、覆蓋 MongoDB 從 schema 設計到 production 跨層架構的核心 production 議題：</p>
<table>
  <thead>
      <tr>
          <th>主題</th>
          <th>文章</th>
          <th>對應 production 議題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Schema contract 該放 DB 層 validator 還是 app 層 abstraction</td>
          <td><a href="schema-design-pattern/">schema-design-pattern</a></td>
          <td>Toyota polymorphic governance、Forbes abstraction layer</td>
      </tr>
      <tr>
          <td>Shard key 選型 + 單 cluster vs 多 cluster blast radius</td>
          <td><a href="shard-key-selection/">shard-key-selection</a></td>
          <td>Toyota 20 DB blast radius、跟 DynamoDB 可逆性對比</td>
      </tr>
      <tr>
          <td>Read preference + causal session 跟 cache 層 freshness token</td>
          <td><a href="replica-set-read-preference/">replica-set-read-preference</a></td>
          <td>DB 層 + cache 層讀後一致性兩層合用</td>
      </tr>
      <tr>
          <td>Aggregation pipeline 順序 / index / memory boundary</td>
          <td><a href="aggregation-pipeline-optimization/">aggregation-pipeline-optimization</a></td>
          <td>report dashboard 跑爆 primary 的 anti-pattern 治理</td>
      </tr>
      <tr>
          <td>Change streams resume token + Kafka connector 治理</td>
          <td><a href="change-streams-kafka/">change-streams-kafka</a></td>
          <td>at-least-once 語義 + idempotency + resume token 過期防護</td>
      </tr>
      <tr>
          <td>Driver × deployment × cache × predictive scaling 三層協作</td>
          <td><a href="connection-management-and-cache-layer/">connection-management-and-cache-layer</a></td>
          <td>Coinbase mongobetween + freshness token + ML 預測擴容三件套</td>
      </tr>
  </tbody>
</table>
<p>跨 vendor entry：先看 <a href="../db3-vendor-selection/">DB3 vendor selection</a>（MongoDB / DynamoDB / Cosmos DB 三方選型 + workload shape 前置判讀），再進本 vendor 的 deep article。</p>
<h2 id="後續擴充仍待補">後續擴充（仍待補）</h2>
<ul>
<li>Index 設計跟覆蓋</li>
<li>從自管 MongoDB 遷到 Atlas</li>
<li>從 MongoDB 遷到 Cosmos DB MongoDB API（保留 document model）</li>
<li>從 MongoDB 遷到 DynamoDB（access pattern 需要重設計）</li>
<li>Queryable encryption（CSFLE）</li>
</ul>
<h2 id="案例對照">案例對照</h2>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 MongoDB 的關係</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/cases/microsoft-365-cosmos-db-analytics/" data-link-title="9.C30 Microsoft 365：從 MongoDB 遷移到 Cosmos DB 的分析平台" data-link-desc="Microsoft 365 把使用分析平台從 MongoDB 遷移到 Cosmos DB、planet-scale 全球分散式分析">9.C30 Microsoft 365</a></td>
          <td>從 MongoDB 遷到 Cosmos DB MongoDB API、planet-scale analytics</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/cases/coinbase-mongodb-document-platform/" data-link-title="9.C36 Coinbase：MongoDB 撐 Ruby 單體 &#43; 1.5M reads/sec identity 服務" data-link-desc="Coinbase 以 MongoDB 為主資料層、自建 mongobetween connection proxy、users 服務在加密貨幣 surge 時撐 1.5M reads/sec">9.C36 Coinbase</a></td>
          <td>MongoDB 為主資料層、自建 mongobetween 解決 Ruby 連線爆炸、users 服務 1.5M reads/sec</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/cases/forbes-mongodb-atlas-multi-cloud-migration/" data-link-title="9.C37 Forbes：自管 MongoDB → Atlas on GCP、build 時間 25 → 9 分鐘" data-link-desc="Forbes 把自管 MongoDB 遷到 Atlas on Google Cloud、6 個月完成、build 25 → 9 分鐘、120M 不重複訪客單月承接">9.C37 Forbes</a></td>
          <td>自管 MongoDB → Atlas on GCP、6 個月遷完、build 25→9 分鐘、120M MAU</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/cases/toyota-connected-mongodb-telematics-iot/" data-link-title="9.C38 Toyota Connected：MongoDB Atlas 撐 900 萬車輛 telematics、月 180 億 transaction" data-link-desc="Toyota Connected 用 MongoDB Atlas 撐 Safety Connect 900 萬車、月 180 億 transaction、緊急訊號 3 秒內到 agent">9.C38 Toyota Connected</a></td>
          <td>Atlas 撐 900 萬車 telematics、月 180 億 transaction、緊急訊號 3 秒內到 agent</td>
      </tr>
  </tbody>
</table>
<p>MongoDB case 的讀法分三組：</p>
<ul>
<li><strong>作為 production 主角持續演進</strong>（Coinbase、Toyota Connected）：document model 撐住核心 OLTP / IoT、配 connection proxy / cache / event-driven 處理擴展周邊。</li>
<li><strong>自管 → managed 遷移</strong>（Forbes）：同 document model、換託管模式、ROI 集中在 DBA 責任轉移跟跨雲彈性、不是性能改善。</li>
<li><strong>遷出 MongoDB 保留 API</strong>（Microsoft 365）：document model 保留、底層換到 Cosmos DB MongoDB API、換取 Azure global distribution。</li>
</ul>
<p>讀 case 時要區分 MongoDB 在「主角 / 遷入 / 遷出」三種位置的差異，三種位置揭露的工程議題完全不同。</p>
<h2 id="常見陷阱">常見陷阱</h2>
<ul>
<li><strong>schema 長期 schema-less</strong>：production 出現 data inconsistency、難 query</li>
<li><strong>shard key 用 _id（自增）</strong>：寫入全集中在最後一個 shard</li>
<li><strong>$lookup 過度使用</strong>：跨 collection JOIN-heavy workload 應在 schema design 時 denormalize 或回 SQL</li>
<li><strong>index 太多</strong>：寫吞吐被拖垮、定期 review 未用 index</li>
<li><strong>secondary read 不檢查 lag</strong>：用戶讀到 stale data</li>
<li><strong>不規劃 Atlas tier upgrade 路徑</strong>：流量上來才發現 tier 跟不上、緊急升級費用高</li>
</ul>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>完整 T1 對照：<a href="/blog/backend/01-database/vendors/" data-link-title="資料庫 Vendor 清單" data-link-desc="規劃 SQL、managed SQL、document、KV 與 distributed SQL 的服務頁撰寫順序與教學大綱">01-database vendors index</a></li>
<li>平行：<a href="/blog/backend/01-database/vendors/cosmosdb/" data-link-title="Azure Cosmos DB" data-link-desc="全球分散式 multi-model DB、5 個 consistency levels、Microsoft 自家 dogfood 證據">Cosmos DB vendor</a>（MongoDB API replacement）、<a href="/blog/backend/01-database/vendors/dynamodb/" data-link-title="DynamoDB" data-link-desc="AWS managed key-value、partition-based scaling、9000 萬 RPS sustained 實戰證據">DynamoDB vendor</a>（KV alternative）</li>
<li>上游：<a href="/blog/backend/01-database/schema-design/" data-link-title="1.2 Schema Design 與資料建模" data-link-desc="整理 table、index、key、partition、denormalization 與命名規則">1.2 schema design</a>、<a href="/blog/backend/01-database/kv-document-capacity-planning/" data-link-title="1.10 KV / Document DB 容量規劃" data-link-desc="DynamoDB / Cosmos DB / Bigtable / MongoDB 等 KV / Document DB 的容量設計、partition key 取捨、capacity mode 選擇">1.10 KV / Document DB 容量規劃</a></li>
<li>下游：<a href="/blog/backend/01-database/large-scale-db-migration/" data-link-title="1.12 大規模 DB 遷移實戰" data-link-desc="跨 DB 遷移的 dual-write、[shadow read](/backend/knowledge-cards/shadow-read/)、cutover、rollback 流程 — 從實戰案例提煉的工程做法">1.12 大規模 DB 遷移實戰</a>（MongoDB 遷出範例）</li>
<li>跨模組：<a href="/blog/backend/09-performance-capacity/capacity-planning/" data-link-title="9.6 容量規劃模型" data-link-desc="peak forecast、headroom budget、growth curve、autoscaling sizing">9.6 容量規劃模型</a>、<a href="/blog/backend/09-performance-capacity/saturation-discovery/" data-link-title="9.4 Saturation Discovery" data-link-desc="找出 throughput plateau 與 latency knee 的方法">9.4 Saturation Discovery</a>（shard key 跟 hot shard）</li>
<li>官方：<a href="https://www.mongodb.com/docs/manual/">MongoDB Manual</a>、<a href="https://www.mongodb.com/atlas">MongoDB Atlas</a></li>
</ul>
]]></content:encoded></item><item><title>Grafana OnCall</title><link>https://tarrragon.github.io/blog/backend/08-incident-response/vendors/grafana-oncall/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/08-incident-response/vendors/grafana-oncall/</guid><description>&lt;p>Grafana OnCall 是 Grafana Labs 維護的 &lt;em>OSS-friendly&lt;/em> on-call 平台、源自 2021 年收購的 Amixr.io、以 Apache 2.0 授權釋出。它承擔三段責任：&lt;em>alert routing + schedule + escalation&lt;/em>（PagerDuty 的 OSS 替代）、&lt;em>Grafana 生態 alert 收斂&lt;/em>（Grafana / Alertmanager / Mimir / Loki alert 進統一 routing）、&lt;em>phone / SMS notification&lt;/em> 透過 Twilio 等 provider。2024 年起 Grafana Labs 推出 &lt;em>Grafana IRM (Incident Response Management) bundle&lt;/em>、把 Grafana OnCall + Grafana Incident（前 Grafana Incident Response &amp;amp; Communications）綁成一個 alert-to-resolve workflow、定位明確對標 PagerDuty 跟 incident.io 的整合 IR 路線。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Grafana OnCall 的核心定位是 &lt;em>Grafana 生態內的 on-call layer&lt;/em>、不是獨立 IR platform。底層產品線：&lt;em>Grafana OnCall OSS&lt;/em>（self-hosted、Helm chart、Apache 2.0）、&lt;em>Grafana Cloud OnCall&lt;/em>（SaaS、含在 Grafana Cloud Pro/Advanced）、&lt;em>Grafana IRM bundle&lt;/em>（OnCall + Incident 整合、2024+ 主推路線）。對非 Grafana-heavy 環境也能單獨用、但跟 &lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/vendors/pagerduty/" data-link-title="PagerDuty" data-link-desc="On-call / alerting 主流 SaaS、IR 平台演化">PagerDuty&lt;/a> 比 ecosystem 廣度不及。&lt;/p>
&lt;p>跟 PagerDuty 比、Grafana OnCall 走 &lt;em>OSS-first + 預算敏感&lt;/em>、核心 schedule / escalation / phone-call 功能對齊、但 advanced workflow（global event orchestration、business service mapping、analytics depth）較弱。跟 &lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/vendors/opsgenie/" data-link-title="Opsgenie" data-link-desc="Atlassian on-call、跟 Jira / Statuspage 套件整合、JSM Premium migration 議題">Opsgenie&lt;/a> 比、Grafana OnCall 不綁 Atlassian 生態、適合已用 Grafana stack 的團隊。跟 &lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/vendors/incident-io/" data-link-title="incident.io" data-link-desc="Slack-native IR 平台、整合 paging / response / retro">incident.io&lt;/a> 比、Grafana IRM bundle 在 alert routing 強、但 Slack-native incident channel 體驗 incident.io 仍領先。&lt;/p>
&lt;p>關鍵張力：&lt;em>OSS 路徑的維運成本&lt;/em> ↔ &lt;em>商業 SaaS 的 SLA&lt;/em>。Self-hosted OSS 要自管 PostgreSQL / Redis / Celery worker / Twilio account、出事故時自家 on-call 平台不能掛（chicken-and-egg）；Grafana Cloud OnCall 解這層、但脫離了 OSS 自管的成本優勢。中型團隊通常走 Grafana Cloud、小型 OSS-first 團隊走自管 + Twilio。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本頁、讀者能判斷：&lt;/p></description><content:encoded><![CDATA[<p>Grafana OnCall 是 Grafana Labs 維護的 <em>OSS-friendly</em> on-call 平台、源自 2021 年收購的 Amixr.io、以 Apache 2.0 授權釋出。它承擔三段責任：<em>alert routing + schedule + escalation</em>（PagerDuty 的 OSS 替代）、<em>Grafana 生態 alert 收斂</em>（Grafana / Alertmanager / Mimir / Loki alert 進統一 routing）、<em>phone / SMS notification</em> 透過 Twilio 等 provider。2024 年起 Grafana Labs 推出 <em>Grafana IRM (Incident Response Management) bundle</em>、把 Grafana OnCall + Grafana Incident（前 Grafana Incident Response &amp; Communications）綁成一個 alert-to-resolve workflow、定位明確對標 PagerDuty 跟 incident.io 的整合 IR 路線。</p>
<h2 id="服務定位">服務定位</h2>
<p>Grafana OnCall 的核心定位是 <em>Grafana 生態內的 on-call layer</em>、不是獨立 IR platform。底層產品線：<em>Grafana OnCall OSS</em>（self-hosted、Helm chart、Apache 2.0）、<em>Grafana Cloud OnCall</em>（SaaS、含在 Grafana Cloud Pro/Advanced）、<em>Grafana IRM bundle</em>（OnCall + Incident 整合、2024+ 主推路線）。對非 Grafana-heavy 環境也能單獨用、但跟 <a href="/blog/backend/08-incident-response/vendors/pagerduty/" data-link-title="PagerDuty" data-link-desc="On-call / alerting 主流 SaaS、IR 平台演化">PagerDuty</a> 比 ecosystem 廣度不及。</p>
<p>跟 PagerDuty 比、Grafana OnCall 走 <em>OSS-first + 預算敏感</em>、核心 schedule / escalation / phone-call 功能對齊、但 advanced workflow（global event orchestration、business service mapping、analytics depth）較弱。跟 <a href="/blog/backend/08-incident-response/vendors/opsgenie/" data-link-title="Opsgenie" data-link-desc="Atlassian on-call、跟 Jira / Statuspage 套件整合、JSM Premium migration 議題">Opsgenie</a> 比、Grafana OnCall 不綁 Atlassian 生態、適合已用 Grafana stack 的團隊。跟 <a href="/blog/backend/08-incident-response/vendors/incident-io/" data-link-title="incident.io" data-link-desc="Slack-native IR 平台、整合 paging / response / retro">incident.io</a> 比、Grafana IRM bundle 在 alert routing 強、但 Slack-native incident channel 體驗 incident.io 仍領先。</p>
<p>關鍵張力：<em>OSS 路徑的維運成本</em> ↔ <em>商業 SaaS 的 SLA</em>。Self-hosted OSS 要自管 PostgreSQL / Redis / Celery worker / Twilio account、出事故時自家 on-call 平台不能掛（chicken-and-egg）；Grafana Cloud OnCall 解這層、但脫離了 OSS 自管的成本優勢。中型團隊通常走 Grafana Cloud、小型 OSS-first 團隊走自管 + Twilio。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>自管 Grafana OnCall（Helm chart）vs Grafana Cloud OnCall vs Grafana IRM bundle 的取捨</li>
<li>配置 schedule / escalation chain / Twilio phone-call 的最短路徑</li>
<li>Grafana / Alertmanager / 自家 webhook 進 OnCall 的 routing 設計</li>
<li>跟 SIEM（<a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / Elastic）webhook 整合的 alert 收斂模式</li>
<li>評估 Grafana OnCall vs <a href="/blog/backend/08-incident-response/vendors/pagerduty/" data-link-title="PagerDuty" data-link-desc="On-call / alerting 主流 SaaS、IR 平台演化">PagerDuty</a> / <a href="/blog/backend/08-incident-response/vendors/opsgenie/" data-link-title="Opsgenie" data-link-desc="Atlassian on-call、跟 Jira / Statuspage 套件整合、JSM Premium migration 議題">Opsgenie</a> / <a href="/blog/backend/08-incident-response/vendors/incident-io/" data-link-title="incident.io" data-link-desc="Slack-native IR 平台、整合 paging / response / retro">incident.io</a> 取捨</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Grafana OnCall deployment 是否健康、最少看四件事：</p>
<ul>
<li><strong>Slack / Teams integration</strong>：on-call notification 是否進團隊主 chat channel、ack / resolve 是否能直接在 Slack 操作不切換 UI、@here / @channel 跟 phone-call 是否分層（低風險 Slack only、高風險才打電話）</li>
<li><strong>Escalation chain</strong>：N step escalation 是否覆蓋 <em>primary → secondary → manager</em>、每階是否有 timeout（5min / 15min / 30min）、節假日 / 跨時區 schedule 是否走 <em>rotation</em> 而非單人值班、override 機制是否清楚</li>
<li><strong>Webhook integration to SIEM</strong>：<a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / Elastic Notable Event 進 OnCall 的 webhook 是否走 <em>correlation rule 過濾後</em> 才轉發、HMAC / token auth 是否正確、failed delivery 是否有 retry 跟 dead-letter queue</li>
<li><strong>Grafana dashboard alert routing</strong>：Grafana / Alertmanager alert 是否走 <em>severity-based routing</em>（critical / warning / info 分流到不同 escalation chain）、alert grouping / deduplication 是否啟用避免 alert storm、跟 <a href="/blog/backend/08-incident-response/observability-reliability-incident-loop/" data-link-title="8.11 Observability / Reliability / Incident Response 閉環" data-link-desc="把 04 / 06 / 08 三個模組的雙向反饋串成可判讀循環，定義閉環健康度判讀訊號">observability-reliability-incident-loop</a> 的 signal-to-incident 邊界是否定義</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/08-incident-response/drills-and-oncall-readiness/" data-link-title="8.6 演練與值班能力建設" data-link-desc="用演練與值班訓練提升事故反應品質">drills-and-oncall-readiness</a> 的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>Schedule + escalation chain</strong>：rotation 走 <em>weekly</em> / <em>daily</em> / <em>custom</em>、可掛 calendar import（iCal / Google Calendar）做休假 override。Escalation chain 是 <em>N step + timeout</em> 結構（例：notify primary → 5min no ack → notify secondary → 15min no ack → notify manager + phone-call）。反例是 <em>single-step chain</em> — 一個人 ack 不到整個 incident 卡住、production chain 至少要 3 step + 跨時區 fallback。</p>
<p><strong>Alert grouping + Notification</strong>：alert source 包含 <em>Alertmanager</em>（Prometheus / Mimir）、<em>Grafana alert</em>（unified alerting 推送）、<em>generic webhook</em>（自家 app / SIEM）、<em>Sentry / Datadog 等第三方</em>。Grouping 用 <em>integration template</em> 寫 Jinja2 抽欄位（service / severity / region）做 deduplication。Notification channel 分層：Slack / Teams 走低成本通知、Twilio phone-call / SMS 留給 P0 / P1、Mobile push 走 Grafana IRM mobile app。</p>
<p><strong>Grafana 生態整合</strong>：Grafana Cloud 帳號內 OnCall 直接啟用、不另外 deploy。Grafana unified alerting 推 alert 到 OnCall integration、Loki / Tempo 的 metric-from-log / trace-anomaly alert 一條 pipeline 進 OnCall。對應 <a href="/blog/backend/04-observability/vendors/grafana-stack/" data-link-title="Grafana Stack" data-link-desc="Grafana / Loki / Tempo / Mimir / Pyroscope 全棧">Grafana Stack</a> 的 alert 出口。Grafana SLO（Service Level Objective）違反 burn rate threshold 也可直接路由到 OnCall escalation。</p>
<p><strong>Grafana IRM bundle</strong>（2024+）：Grafana 把 OnCall（alert routing）+ Incident（incident lifecycle / war room / timeline）打包、目標是把 <em>alert paged → IC declared → channel created → timeline auto-recorded → post-incident review</em> 收進一個 console。對 Grafana-heavy 環境的吸引力是 <em>少一個 vendor seam</em>；對 Slack-native 團隊則跟 incident.io / FireHydrant 競爭、要看 Slack 體驗深度。</p>
<p><strong>OnCall webhook 整合 SIEM / 第三方</strong>：generic webhook integration 接 <a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> Notable Event、Elastic Security alert、Datadog monitor、自家 app exception。Webhook payload 走 <em>integration template</em> 轉成 OnCall alert 欄位、加 routing label 進對應 escalation chain。注意 <em>webhook auth</em> 走 token / HMAC、不要用 anonymous webhook 接外網 — 對應 <a href="/blog/backend/08-incident-response/incident-workflow-automation-boundary/" data-link-title="8.21 Incident Workflow Automation Boundary" data-link-desc="定義哪些事故流程適合自動化，哪些決策需要保留人工確認">incident-workflow-automation-boundary</a> 的入口治理。</p>
<p><strong>Maintenance mode</strong>：planned maintenance window 期間 suppress alert、避免 deploy / DB migration 觸發大量假 alert。設定 <em>integration-level mute</em> 或 <em>route-level mute</em>、附 reason 跟 expiry time、不要無限期 mute（容易遺忘變盲點）。</p>
<p><strong>Mobile app</strong>：Grafana IRM mobile app（iOS / Android）支援 push notification + ack / resolve / 加 note、replace 部分電話需求。但 phone-call 不可完全廢除 — 手機靜音 / 深夜值班 push 不一定醒、P0 仍需 Twilio 多次呼叫升級。</p>
<p><strong>自管部署</strong>：Helm chart 部署、依賴 <em>PostgreSQL</em>（state）+ <em>Redis</em>（cache / Celery broker）+ <em>Celery worker</em>（background job）+ <em>Twilio account</em>（phone / SMS）+ TLS domain。Production checklist：PostgreSQL 走 managed service（RDS / Cloud SQL）避免自管 DB on-call 平台兩層 chicken-and-egg、Redis 走 managed、Helm values 走 GitOps 版控、Twilio account 走獨立 sub-account 避免 quota 跟其他服務搶。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Grafana OnCall</th>
          <th>PagerDuty</th>
          <th>Opsgenie</th>
          <th>incident.io</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>計費模型</td>
          <td>OSS 自管免費 / Cloud 含在 Grafana Cloud 套餐</td>
          <td>Per-user / 月、advanced tier 加價</td>
          <td>Per-user / 月（Atlassian 套餐）</td>
          <td>Per-user / 月、Slack-native focus</td>
      </tr>
      <tr>
          <td>部署模型</td>
          <td>Self-hosted (Helm) / Grafana Cloud SaaS</td>
          <td>SaaS only</td>
          <td>SaaS only</td>
          <td>SaaS only</td>
      </tr>
      <tr>
          <td>授權</td>
          <td>Apache 2.0 OSS</td>
          <td>商業 SaaS</td>
          <td>商業 SaaS</td>
          <td>商業 SaaS</td>
      </tr>
      <tr>
          <td>Advanced workflow</td>
          <td>基本 schedule + escalation、analytics 較弱</td>
          <td>業界最強（global orchestration / RBA）</td>
          <td>中等（Atlassian Jira / Confluence 整合）</td>
          <td>Slack incident channel + post-incident</td>
      </tr>
      <tr>
          <td>Integration ecosystem</td>
          <td>Grafana / Alertmanager 強、第三方靠 webhook</td>
          <td>700+ 原生 integration</td>
          <td>Atlassian 生態深、Jira / Confluence 一線</td>
          <td>Slack-native、深度有限但體驗好</td>
      </tr>
      <tr>
          <td>Phone / SMS</td>
          <td>Twilio（自配 account / OSS 路徑要自管）</td>
          <td>內建、跨地區 carrier 覆蓋廣</td>
          <td>內建、Atlassian 計費</td>
          <td>內建、focus 在 Slack ack 多於電話</td>
      </tr>
      <tr>
          <td>Slack 體驗</td>
          <td>Slack integration 基本（notify / ack）</td>
          <td>Slack integration 完整</td>
          <td>Slack integration 中等</td>
          <td>Slack-native、incident channel 自動建</td>
      </tr>
      <tr>
          <td>跨平台 IR</td>
          <td>Grafana IRM bundle（OnCall + Incident）2024+</td>
          <td>PagerDuty Incident Workflows</td>
          <td>Jira Service Management incident</td>
          <td>incident.io Catalog + workflow</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>Grafana-heavy / OSS-first / 預算敏感</td>
          <td>Enterprise / 跨產品線 / 高 SLA</td>
          <td>已用 Atlassian / Jira Service Management</td>
          <td>Slack-first / startup-to-midsize</td>
      </tr>
      <tr>
          <td>退場成本</td>
          <td>低 — OSS 路徑可帶走 config、Cloud 也有 export</td>
          <td>中-高 — escalation policy / workflow 量多</td>
          <td>中 — Atlassian 套餐綁定</td>
          <td>中 — Slack workflow 客製化深度</td>
      </tr>
  </tbody>
</table>
<p>選 Grafana OnCall 的核心訴求：<em>OSS-friendly / 預算敏感 / Grafana 生態已是觀測平台主力</em>、能接受 advanced workflow 較弱（或預期不需要）、自管路徑能投入 PostgreSQL / Redis / Twilio account 維運。Enterprise + 高 SLA + 跨產品線 ecosystem 廣度需求仍走 PagerDuty。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Grafana IRM bundle 的整合決策</strong>：OnCall（alert routing）+ Incident（incident channel / timeline / post-mortem）打包後、IR workflow 收在一個 console。決策點是 <em>是否已用 Slack 做 incident channel</em>、若團隊 Slack incident workflow 成熟、IRM Incident 的 channel 自動建可能跟現有 <a href="/blog/backend/08-incident-response/incident-communication/" data-link-title="8.4 事故通訊與狀態更新" data-link-desc="建立內外部通報節奏與狀態更新格式">incident-communication</a> 模式衝突；若還沒成熟、IRM bundle 是最短路徑。</p>
<p><strong>OnCall webhook 整合 SIEM 的 alert 收斂模式</strong>：<a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> ES Notable Event / Elastic Security alert 不該直接打 OnCall — 噪音太大會造成 <a href="/blog/backend/07-security-data-protection/blue-team/alert-fatigue-and-signal-quality/" data-link-title="7.B10 Alert Fatigue and Signal Quality" data-link-desc="建立告警疲勞治理方法，讓訊號品質、分級一致性與處置效率同步提升">alert-fatigue-and-signal-quality</a> 問題。實務做法：SIEM 端先走 <em>correlation rule + risk-based threshold</em>、只有 high-confidence finding 才 webhook 到 OnCall、低風險走 Slack notification channel 給 SOC analyst triage。</p>
<p><strong>Maintenance mode 跟 deploy 流程的整合</strong>：deploy pipeline 在 production rollout 前 call OnCall API 開 maintenance window（mute 特定 integration / route）、deploy 完成或失敗 rollback 後關閉。避免 deploy 期間 false alert 把 on-call 叫醒、但要設 <em>max maintenance duration</em>（例 1hr 自動 expire）避免長 window 變盲點。</p>
<p><strong>OSS 自管的 chicken-and-egg</strong>：自管 OnCall 部署本身的 monitoring 不能依賴 OnCall — OnCall 掛了 alert 進不來、on-call 不知道 OnCall 掛了。實務做法：OnCall infra 的 monitoring 走另一條 <em>bootstrap alert</em>（直接 Twilio API call + email-to-pager fallback）、或保留小規模 <a href="/blog/backend/08-incident-response/vendors/pagerduty/" data-link-title="PagerDuty" data-link-desc="On-call / alerting 主流 SaaS、IR 平台演化">PagerDuty</a> free tier 做 backstop。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Webhook 沒觸發 / alert 沒進來</strong>：integration URL 錯（環境變數沒帶 base URL）、token / HMAC auth 設錯、source 端 webhook payload format 不對（沒走 integration template mapping）— 檢查 OnCall integration log + source webhook delivery log 對齊</li>
<li><strong>Slack notification stuck / 不出現</strong>：Slack OAuth token 過期、Slack workspace permission 變更、OnCall Slack bot 沒被 invite 進 channel — 重 OAuth + 確認 bot membership</li>
<li><strong>Twilio quota 用完 / phone-call 失敗</strong>：Twilio account balance 不足 / 沒升級 trial / 地區 carrier 限制 — 看 Twilio dashboard balance + delivery log、A2P 10DLC 註冊跟地區 toll-free 預先設定</li>
<li><strong>Schedule overlap / on-call 漏排班</strong>：rotation override 配錯、calendar import 沒同步、時區誤判（UTC vs local）— 用 OnCall schedule preview 跑 7-day forward 檢查</li>
<li><strong>Notification delay / 來得慢</strong>：provider latency（Twilio / Slack / FCM push）、Celery worker queue backlog（自管路徑）、escalation timeout 設太長 — 自管路徑檢查 Celery queue length + worker count</li>
<li><strong>Self-hosted upgrade gotcha</strong>：Helm chart major upgrade 帶 DB schema migration、跳版升級失敗、PostgreSQL extension 缺 — 走 staging environment 跑 migration + 備 rollback DB snapshot、不直接 production helm upgrade</li>
<li><strong>Maintenance mode 沒到期 / 變盲點</strong>：mute 沒設 expiry / reason、deploy 完成沒清 mute — maintenance window 強制設 max duration、weekly review mute 清單</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>進階 IR workflow / RBA</td>
          <td><a href="/blog/backend/08-incident-response/vendors/pagerduty/" data-link-title="PagerDuty" data-link-desc="On-call / alerting 主流 SaaS、IR 平台演化">PagerDuty</a></td>
      </tr>
      <tr>
          <td>Atlassian 生態 / Jira</td>
          <td><a href="/blog/backend/08-incident-response/vendors/opsgenie/" data-link-title="Opsgenie" data-link-desc="Atlassian on-call、跟 Jira / Statuspage 套件整合、JSM Premium migration 議題">Opsgenie</a></td>
      </tr>
      <tr>
          <td>Slack-native incident</td>
          <td><a href="/blog/backend/08-incident-response/vendors/incident-io/" data-link-title="incident.io" data-link-desc="Slack-native IR 平台、整合 paging / response / retro">incident.io</a></td>
      </tr>
      <tr>
          <td>商業 SLA / Enterprise</td>
          <td>PagerDuty / Opsgenie</td>
      </tr>
      <tr>
          <td>Post-incident learning</td>
          <td><a href="/blog/backend/08-incident-response/vendors/jeli/" data-link-title="Jeli" data-link-desc="Post-incident learning 平台、2023 被 PagerDuty 收購、強調 interview-driven narrative 而非 timeline-only retro">Jeli</a>（PagerDuty 收購）</td>
      </tr>
      <tr>
          <td>Status page (對外溝通)</td>
          <td><a href="/blog/backend/08-incident-response/vendors/atlassian-statuspage/" data-link-title="Atlassian Statuspage" data-link-desc="公開狀態頁 SaaS、Atlassian 出品、enterprise polish &#43; Atlassian 生態整合、subscriber notification &#43; component dependency 是核心責任">Atlassian Statuspage</a> / <a href="/blog/backend/08-incident-response/vendors/instatus/" data-link-title="Instatus" data-link-desc="輕量 status page SaaS、現代 UI、價格敏感替代">Instatus</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Twilio account 申請 / A2P 10DLC 註冊 / 地區 carrier 設定細節</li>
<li>Helm chart values 完整 reference（看官方 docs）</li>
<li>Grafana Cloud OnCall pricing tier 對照</li>
<li>Grafana unified alerting 規則語法（屬 observability 範圍、見 <a href="/blog/backend/04-observability/vendors/grafana-stack/" data-link-title="Grafana Stack" data-link-desc="Grafana / Loki / Tempo / Mimir / Pyroscope 全棧">Grafana Stack</a>）</li>
<li>Grafana Incident 的 channel / timeline 細節（屬 IRM bundle 另一半、本頁聚焦 OnCall）</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>Grafana OnCall 在 08 案例庫沒有直接 vendor-level 事件、本案例庫的多數事故主角是 Slack / GitHub / Cloudflare / AWS 等基礎設施。Grafana OnCall 的對照位置在 <em>OSS-first organization / Grafana-heavy 監控環境</em> 的 IR routing 設計、相關 case 的啟示如下：</p>
<table>
  <thead>
      <tr>
          <th>案例方向</th>
          <th>跟 Grafana OnCall 的關係（對照啟示）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>OSS-first / Grafana-heavy 觀測環境</td>
          <td>Alertmanager / Mimir / Loki alert 進 OnCall 是最短整合路徑、escalation chain 走 Grafana SLO burn rate trigger</td>
      </tr>
      <tr>
          <td>預算敏感的中型團隊</td>
          <td>Self-hosted OnCall + Twilio account 是 PagerDuty 的 OSS 替代、要算 PostgreSQL / Redis 維運成本是否真的省</td>
      </tr>
      <tr>
          <td>Slack-only IR workflow vs Grafana IRM</td>
          <td>Grafana IRM bundle 把 incident channel 收進 console、跟 incident.io / Slack-native workflow 二選一</td>
      </tr>
      <tr>
          <td>Vendor 依賴出事（<a href="/blog/backend/08-incident-response/vendor-dependency-incident/" data-link-title="8.15 Vendor / 第三方依賴事故處理" data-link-desc="依賴方掛掉、自己無 control 時的決策模型">vendor-dependency-incident</a>）</td>
          <td>OnCall 自身是 vendor、自管路徑要設 bootstrap alert、Cloud 路徑要評估 Grafana Labs SLA 跟 backup paging</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/08-incident-response/drills-and-oncall-readiness/" data-link-title="8.6 演練與值班能力建設" data-link-desc="用演練與值班訓練提升事故反應品質">Drills and On-call Readiness</a>、<a href="/blog/backend/08-incident-response/incident-workflow-automation-boundary/" data-link-title="8.21 Incident Workflow Automation Boundary" data-link-desc="定義哪些事故流程適合自動化，哪些決策需要保留人工確認">Incident Workflow Automation Boundary</a></li>
<li>平行：<a href="/blog/backend/08-incident-response/vendors/pagerduty/" data-link-title="PagerDuty" data-link-desc="On-call / alerting 主流 SaaS、IR 平台演化">PagerDuty</a>、<a href="/blog/backend/08-incident-response/vendors/opsgenie/" data-link-title="Opsgenie" data-link-desc="Atlassian on-call、跟 Jira / Statuspage 套件整合、JSM Premium migration 議題">Opsgenie</a>、<a href="/blog/backend/08-incident-response/vendors/incident-io/" data-link-title="incident.io" data-link-desc="Slack-native IR 平台、整合 paging / response / retro">incident.io</a>、<a href="/blog/backend/08-incident-response/vendors/firehydrant/" data-link-title="FireHydrant" data-link-desc="IR &#43; retrospective 平台、Slack / Teams 整合、service catalog &#43; runbook automation 為核心">FireHydrant</a>、<a href="/blog/backend/08-incident-response/vendors/rootly/" data-link-title="Rootly" data-link-desc="IR 自動化平台、no-code workflow &#43; AI investigation、Slack-native &#43; 200&#43; integration">Rootly</a></li>
<li>下游：<a href="/blog/backend/04-observability/vendors/grafana-stack/" data-link-title="Grafana Stack" data-link-desc="Grafana / Loki / Tempo / Mimir / Pyroscope 全棧">Grafana Stack</a>（alert source）、<a href="/blog/backend/08-incident-response/observability-reliability-incident-loop/" data-link-title="8.11 Observability / Reliability / Incident Response 閉環" data-link-desc="把 04 / 06 / 08 三個模組的雙向反饋串成可判讀循環，定義閉環健康度判讀訊號">Observability ↔ Reliability ↔ Incident Loop</a></li>
<li>跨模組：<a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a>（SIEM webhook → OnCall）、<a href="/blog/backend/08-incident-response/vendor-dependency-incident/" data-link-title="8.15 Vendor / 第三方依賴事故處理" data-link-desc="依賴方掛掉、自己無 control 時的決策模型">Vendor Dependency Incident</a>（OnCall 自身 vendor 風險）</li>
<li>官方：<a href="https://grafana.com/docs/oncall/">Grafana OnCall Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>Grafana Stack</title><link>https://tarrragon.github.io/blog/backend/04-observability/vendors/grafana-stack/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/04-observability/vendors/grafana-stack/</guid><description>&lt;p>Grafana Stack 是 Grafana Labs 提供的 OSS observability 全棧、承擔三個責任：跨 data source 統一視覺化（Grafana）、各訊號類型專屬 backend（Loki logs / Tempo traces / Mimir metrics / Pyroscope profiles）、可自管或用 Grafana Cloud（managed）。設計取捨偏向「OSS-first + signal-specific backend + 統一查詢介面」、是 Datadog 的 OSS 替代方案。&lt;/p>
&lt;p>對「需要 OSS / 自管 observability、跨 data source 統一儀表板、不想 vendor lock-in」這條路徑、Grafana Stack 是首選。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>部署 Grafana + Prometheus + Loki + Tempo 基本棧&lt;/li>
&lt;li>用 LogQL 查詢 Loki、用 TraceQL 查詢 Tempo&lt;/li>
&lt;li>設計 dashboard as code（Jsonnet / Terraform）&lt;/li>
&lt;li>評估 Mimir vs Thanos 的長期 metrics 儲存選擇&lt;/li>
&lt;li>評估 Grafana Cloud（managed）跟自管的取捨&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑5-分鐘把-grafana-stack-跑起來">最短路徑：5 分鐘把 Grafana Stack 跑起來&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 1. 用 docker-compose 跑起 Grafana + Prometheus + Loki&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: docker-compose.yml with grafana / prometheus / loki&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="c1"># 2. 在 Grafana 加 data source&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: Prometheus / Loki 各自的 datasource config&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">&lt;span class="c1"># 3. 建第一個 dashboard&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: 用 explorer 試 PromQL + LogQL&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>最短路徑驗證 Grafana 起來、可訪 metrics + logs。實際 production 要評估 Mimir / Tempo + Grafana Cloud 取捨。&lt;/p>
&lt;h2 id="日常操作與決策形狀">日常操作與決策形狀&lt;/h2>
&lt;h3 id="grafana-視覺化">Grafana 視覺化&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>Data source 配置（Prometheus / Loki / Tempo / Postgres / MySQL / Elasticsearch）&lt;/li>
&lt;li>Dashboard 設計：variable + template + panel&lt;/li>
&lt;li>Dashboard as code：Jsonnet (Grafonnet) / Terraform Grafana provider&lt;/li>
&lt;li>對應指令：HTTP API &lt;code>/api/dashboards&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="logqlloki-查詢">LogQL（Loki 查詢）&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>LogQL syntax：log stream selector + filter + parser + aggregation&lt;/li>
&lt;li>跟 PromQL 對齊的設計（同樣 label-based）&lt;/li>
&lt;li>範例：&lt;code>{job=&amp;quot;app&amp;quot;} |= &amp;quot;error&amp;quot; | json | line_format &amp;quot;...&amp;quot;&lt;/code>&lt;/li>
&lt;li>對應 metrics-from-logs（unwrap + rate）&lt;/li>
&lt;/ul>
&lt;h3 id="traceqltempo-查詢">TraceQL（Tempo 查詢）&lt;/h3>
&lt;p>子議題：&lt;/p></description><content:encoded><![CDATA[<p>Grafana Stack 是 Grafana Labs 提供的 OSS observability 全棧、承擔三個責任：跨 data source 統一視覺化（Grafana）、各訊號類型專屬 backend（Loki logs / Tempo traces / Mimir metrics / Pyroscope profiles）、可自管或用 Grafana Cloud（managed）。設計取捨偏向「OSS-first + signal-specific backend + 統一查詢介面」、是 Datadog 的 OSS 替代方案。</p>
<p>對「需要 OSS / 自管 observability、跨 data source 統一儀表板、不想 vendor lock-in」這條路徑、Grafana Stack 是首選。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>部署 Grafana + Prometheus + Loki + Tempo 基本棧</li>
<li>用 LogQL 查詢 Loki、用 TraceQL 查詢 Tempo</li>
<li>設計 dashboard as code（Jsonnet / Terraform）</li>
<li>評估 Mimir vs Thanos 的長期 metrics 儲存選擇</li>
<li>評估 Grafana Cloud（managed）跟自管的取捨</li>
</ol>
<h2 id="最短路徑5-分鐘把-grafana-stack-跑起來">最短路徑：5 分鐘把 Grafana Stack 跑起來</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 1. 用 docker-compose 跑起 Grafana + Prometheus + Loki</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># TODO: docker-compose.yml with grafana / prometheus / loki</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 2. 在 Grafana 加 data source</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="c1"># TODO: Prometheus / Loki 各自的 datasource config</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="c1"># 3. 建第一個 dashboard</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="c1"># TODO: 用 explorer 試 PromQL + LogQL</span></span></span></code></pre></div><p>最短路徑驗證 Grafana 起來、可訪 metrics + logs。實際 production 要評估 Mimir / Tempo + Grafana Cloud 取捨。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="grafana-視覺化">Grafana 視覺化</h3>
<p>子議題：</p>
<ul>
<li>Data source 配置（Prometheus / Loki / Tempo / Postgres / MySQL / Elasticsearch）</li>
<li>Dashboard 設計：variable + template + panel</li>
<li>Dashboard as code：Jsonnet (Grafonnet) / Terraform Grafana provider</li>
<li>對應指令：HTTP API <code>/api/dashboards</code></li>
</ul>
<h3 id="logqlloki-查詢">LogQL（Loki 查詢）</h3>
<p>子議題：</p>
<ul>
<li>LogQL syntax：log stream selector + filter + parser + aggregation</li>
<li>跟 PromQL 對齊的設計（同樣 label-based）</li>
<li>範例：<code>{job=&quot;app&quot;} |= &quot;error&quot; | json | line_format &quot;...&quot;</code></li>
<li>對應 metrics-from-logs（unwrap + rate）</li>
</ul>
<h3 id="traceqltempo-查詢">TraceQL（Tempo 查詢）</h3>
<p>子議題：</p>
<ul>
<li>TraceQL syntax：span selector + attribute + aggregation</li>
<li>範例：<code>{ span.http.status_code = 500 &amp;&amp; duration &gt; 1s }</code></li>
<li>Service graph：跨服務依賴自動分析</li>
<li>對應 trace-to-logs / trace-to-metrics 關聯查詢</li>
</ul>
<h2 id="deep-article">Deep Article</h2>
<ul>
<li><a href="lgtm-stack-operations/">LGTM Stack 組合運維</a>：四個元件的責任分工、部署模式、常見故障與 dashboard provisioning</li>
<li><a href="loki-design-operational-limits/">Loki 設計與操作限制</a>：label-based index 設計、LogQL 查詢模式、cardinality 治理與 Elasticsearch 差異</li>
</ul>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<h3 id="loki-設計與限制">Loki 設計與限制</h3>
<p>子議題：</p>
<ul>
<li>Storage：S3 / GCS / 本地、按 stream 切 chunks</li>
<li>Label cardinality 跟 Prometheus 一樣敏感（不是 stream content）</li>
<li>LogQL 不適合 high-cardinality content search（用 Elastic）</li>
<li>對應 <a href="/blog/backend/04-observability/cases/healthcare-access-traceability-and-retention/" data-link-title="Healthcare：存取可追溯性與保留邊界" data-link-desc="在資料主權限制下，建立可追溯存取證據與分層保留策略。">4.C3 Healthcare retention</a></li>
</ul>
<h3 id="tempo-trace-採集">Tempo trace 採集</h3>
<p>子議題：</p>
<ul>
<li>接受 OTLP / Jaeger / Zipkin protocol</li>
<li>Storage：S3 / GCS、cheap object storage</li>
<li>Trace ID lookup 為主、no full-text search（用 traces metrics 反向查）</li>
<li>對應 <a href="/blog/backend/04-observability/cases/xray-to-opentelemetry-migration/" data-link-title="4.C4 AWS：X-Ray 到 OpenTelemetry 轉換" data-link-desc="觀測儀表從 vendor-specific SDK 轉向 OpenTelemetry 的治理重點。">4.C4 X-Ray to OTel</a></li>
</ul>
<h3 id="mimir-長期-metrics-儲存">Mimir 長期 metrics 儲存</h3>
<p>子議題：</p>
<ul>
<li>Prometheus remote write 接收 metric</li>
<li>Horizontally scalable（multi-tenant）</li>
<li>跟 Thanos / Cortex 的對照（Mimir 是 Cortex fork + improvements）</li>
<li>對應 <a href="/blog/backend/04-observability/cases/airbnb-observability-k8s-scale-signals/" data-link-title="4.C8 Airbnb：Kubernetes 規模化下的觀測訊號治理" data-link-desc="叢集擴縮與工作負載變動如何回寫觀測模型。">4.C8 Airbnb K8s scale</a></li>
</ul>
<h3 id="pyroscope-continuous-profiling">Pyroscope continuous profiling</h3>
<p>子議題：</p>
<ul>
<li>CPU / memory / mutex / goroutine profiling</li>
<li>Flame graph 視覺化</li>
<li>跟 Tempo trace 關聯（trace-to-profile）</li>
<li>OSS（Grafana 收購）vs Pyroscope OG</li>
</ul>
<h3 id="grafana-cloudmanaged">Grafana Cloud（managed）</h3>
<p>子議題：</p>
<ul>
<li>Free tier 額度 + paid tier</li>
<li>含所有 stack（Metrics / Logs / Traces / Profiles）</li>
<li>Grafana Cloud vs Datadog cost 對照</li>
<li>Hybrid 模式：self-host backend + Grafana Cloud Grafana</li>
</ul>
<h3 id="unified-alerting">Unified Alerting</h3>
<p>子議題：</p>
<ul>
<li>Grafana 9+ 統一 alerting（取代 dashboard alert + Prometheus alertmanager 分裂）</li>
<li>跨 data source 寫 alert rule</li>
<li>Multi-dimensional alert（per-label）</li>
<li>對應 Alertmanager 兼容</li>
</ul>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<h3 id="dashboard-載入慢">Dashboard 載入慢</h3>
<p>操作原則：先看 query 範圍跟 panel 數、用 query inspector 看 query 時間分布。</p>
<h3 id="loki-query-過慢--失敗">Loki query 過慢 / 失敗</h3>
<p>操作原則：Loki query 需要 label filter 先縮範圍、再 content match。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># TODO: LogQL: {namespace=&#34;prod&#34;, app=&#34;api&#34;} |= &#34;error&#34;（先 label 後 filter）</span></span></span></code></pre></div><h3 id="tempo-span-gap">Tempo span gap</h3>
<p>操作原則：trace 不完整、看 sampling 設定 + Collector buffer 是否 drop。</p>
<h3 id="mimir-ingestion-失敗">Mimir ingestion 失敗</h3>
<p>操作原則：remote_write rate / size limit 撞到 Mimir quota。判讀：Mimir HTTP 429 / 413。</p>
<h3 id="grafana-跟-prometheus-disconnected">Grafana 跟 Prometheus disconnected</h3>
<p>操作原則：data source 連不上、看 Grafana log + network。</p>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Pure metrics</td>
          <td><a href="/blog/backend/04-observability/vendors/prometheus/" data-link-title="Prometheus" data-link-desc="Pull-based metrics 主流 OSS、PromQL 與 alerting">Prometheus</a> 單獨用</td>
      </tr>
      <tr>
          <td>SaaS turnkey APM</td>
          <td><a href="/blog/backend/04-observability/vendors/datadog/" data-link-title="Datadog" data-link-desc="All-in-one SaaS 觀測平台、APM / Logs / Metrics / RUM / Security">Datadog</a></td>
      </tr>
      <tr>
          <td>Log full-text search 為主</td>
          <td><a href="/blog/backend/04-observability/vendors/elastic-stack/" data-link-title="Elastic Stack" data-link-desc="ELK：Elasticsearch / Logstash / Kibana &#43; Beats / APM">Elastic Stack</a></td>
      </tr>
      <tr>
          <td>High-cardinality debug</td>
          <td><a href="/blog/backend/04-observability/vendors/honeycomb/" data-link-title="Honeycomb" data-link-desc="High-cardinality observability 平台、events-based 模型">Honeycomb</a></td>
      </tr>
      <tr>
          <td>AWS / GCP native</td>
          <td><a href="/blog/backend/04-observability/vendors/aws-cloudwatch/" data-link-title="AWS CloudWatch" data-link-desc="AWS 原生觀測性服務、Logs / Metrics / Traces (X-Ray)">CloudWatch</a> / <a href="/blog/backend/04-observability/vendors/gcp-cloud-operations/" data-link-title="GCP Cloud Operations" data-link-desc="GCP 原生觀測性套件（前 Stackdriver）：Logging / Monitoring / Trace / Profiler">Cloud Ops</a></td>
      </tr>
      <tr>
          <td>Error tracking</td>
          <td><a href="/blog/backend/04-observability/vendors/sentry/" data-link-title="Sentry" data-link-desc="Error tracking 主流、APM / Profiling / Session Replay 擴展">Sentry</a></td>
      </tr>
      <tr>
          <td>Profile only</td>
          <td>Pyroscope OSS / Polar Signals</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>各 Grafana plugin 細節</li>
<li>Dashboard 美術 / UX 建議</li>
<li>Grafana / Loki / Tempo / Mimir 各自完整 admin 手冊</li>
<li>Grafana 商業版 (Enterprise) 功能</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<h3 id="直接相關案例">直接相關案例</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>主討論議題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/gaming-peak-signal-freshness-and-cardinality/" data-link-title="Gaming：高峰流量下的訊號新鮮度與 Cardinality" data-link-desc="在高峰事件中控制訊號延遲與維度爆炸，維持告警與定位可信度。">4.C2 Gaming peak cardinality</a></td>
          <td>Loki / Mimir 高峰下的 ingestion lag 與標籤治理</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/healthcare-access-traceability-and-retention/" data-link-title="Healthcare：存取可追溯性與保留邊界" data-link-desc="在資料主權限制下，建立可追溯存取證據與分層保留策略。">4.C3 Healthcare retention</a></td>
          <td>Loki retention / compliance</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/airbnb-observability-k8s-scale-signals/" data-link-title="4.C8 Airbnb：Kubernetes 規模化下的觀測訊號治理" data-link-desc="叢集擴縮與工作負載變動如何回寫觀測模型。">4.C8 Airbnb K8s scale</a></td>
          <td>Mimir scale / Prometheus 長期儲存</td>
      </tr>
  </tbody>
</table>
<h3 id="跨-vendor-對照">跨 vendor 對照</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>對 Grafana Stack 的對應</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/xray-to-opentelemetry-migration/" data-link-title="4.C4 AWS：X-Ray 到 OpenTelemetry 轉換" data-link-desc="觀測儀表從 vendor-specific SDK 轉向 OpenTelemetry 的治理重點。">4.C4 X-Ray to OTel</a></td>
          <td>從 X-Ray 遷出後 Tempo 是 OSS trace backend 候選</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/datadog-otel-migration-practice/" data-link-title="4.C7 Datadog：OTel 相容遷移實務" data-link-desc="APM 採集從專有代理轉向 OTel 相容模式的治理案例。">4.C7 Datadog OTel migration</a></td>
          <td>從 Datadog 遷出可去 Grafana Cloud</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/contrast-observability-rollout-by-scale/" data-link-title="4.C10 對照：規模差異下的觀測遷移" data-link-desc="觀測遷移在不同規模團隊下的流程與風險差異。">4.C10 規模對照</a></td>
          <td>小型 single Grafana / 中型加 Loki+Tempo / 大型 Grafana Cloud 或 Mimir</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游概念：<a href="/blog/backend/04-observability/metrics-basics/" data-link-title="4.2 metrics 與 SLI/SLO" data-link-desc="整理 counter、gauge、histogram 與服務健康指標">Metrics Basics</a></li>
<li>平行 vendor：<a href="/blog/backend/04-observability/vendors/prometheus/" data-link-title="Prometheus" data-link-desc="Pull-based metrics 主流 OSS、PromQL 與 alerting">Prometheus</a>、<a href="/blog/backend/04-observability/vendors/opentelemetry/" data-link-title="OpenTelemetry" data-link-desc="可觀測性開放標準、SDK 與 Collector">OpenTelemetry</a></li>
<li>下游能力：<a href="/blog/backend/04-observability/observability-evidence-package/" data-link-title="4.20 Observability Evidence Package" data-link-desc="把 log、metric、trace、audit 與資料品質限制包成可交接證據">4.20 Observability Evidence Package</a></li>
</ul>
]]></content:encoded></item><item><title>k6</title><link>https://tarrragon.github.io/blog/backend/06-reliability/vendors/k6/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/06-reliability/vendors/k6/</guid><description>&lt;p>k6 是 Grafana Labs 出品的 load test 工具、承擔三個責任：CLI-first load test（Go 寫成、JS 寫測試 script）、threshold-based CI gate（pass/fail 直接接 CI）、Grafana Cloud k6 / k6 Operator on K8s 分散式。設計取捨偏向「CI-first + JS DX + 整合 Grafana 生態」、是現代 load test 主流選擇。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>寫 k6 test script（VU / iteration / stages）&lt;/li>
&lt;li>設計 threshold + CI gate（pass/fail）&lt;/li>
&lt;li>用 xk6 extension 擴展（gRPC / Kafka / SQL）&lt;/li>
&lt;li>部署 k6 Operator 做 distributed load&lt;/li>
&lt;li>評估 k6 vs Gatling / Locust / JMeter 的選用&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑5-分鐘把-k6-跑起來">最短路徑：5 分鐘把 k6 跑起來&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 1. 安裝&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: brew install k6 / docker run grafana/k6&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="c1"># 2. 寫 test.js&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: import http from &amp;#39;k6/http&amp;#39;; export default function(){ http.get(...) }&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">&lt;span class="c1"># 3. 跑&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: k6 run --vus 10 --duration 30s test.js&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="日常操作與決策形狀">日常操作與決策形狀&lt;/h2>
&lt;h3 id="test-script-結構">Test script 結構&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>export default function（per-VU iteration）&lt;/li>
&lt;li>export const options（VU / duration / stages / thresholds）&lt;/li>
&lt;li>Setup / teardown&lt;/li>
&lt;li>對應指令範例：&lt;code>k6 run --vus 100 --duration 10m&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="threshold--ci-gate">Threshold + CI gate&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>thresholds: &lt;code>http_req_duration: ['p(95)&amp;lt;500']&lt;/code>&lt;/li>
&lt;li>Exit code 非 0 → CI fail&lt;/li>
&lt;li>Custom metric thresholds&lt;/li>
&lt;li>對應 &lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/performance-regression-gate/" data-link-title="6.13 Performance Regression Gate" data-link-desc="把效能 baseline 從一次性壓測變成持續對齊的 release gate，涵蓋 baseline 設定、判讀方法、variance 控制與退化定位">6.13 Performance Regression Gate&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="test-pattern">Test pattern&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>Smoke / Load / Stress / Spike / Soak / Breakpoint&lt;/li>
&lt;li>Stages（ramp-up / steady / ramp-down）&lt;/li>
&lt;li>VU vs iteration vs RPS-based&lt;/li>
&lt;/ul>
&lt;h2 id="進階主題按需閱讀">進階主題（按需閱讀）&lt;/h2>
&lt;h3 id="xk6-extensions">xk6 extensions&lt;/h3>
&lt;p>子議題：&lt;/p></description><content:encoded><![CDATA[<p>k6 是 Grafana Labs 出品的 load test 工具、承擔三個責任：CLI-first load test（Go 寫成、JS 寫測試 script）、threshold-based CI gate（pass/fail 直接接 CI）、Grafana Cloud k6 / k6 Operator on K8s 分散式。設計取捨偏向「CI-first + JS DX + 整合 Grafana 生態」、是現代 load test 主流選擇。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>寫 k6 test script（VU / iteration / stages）</li>
<li>設計 threshold + CI gate（pass/fail）</li>
<li>用 xk6 extension 擴展（gRPC / Kafka / SQL）</li>
<li>部署 k6 Operator 做 distributed load</li>
<li>評估 k6 vs Gatling / Locust / JMeter 的選用</li>
</ol>
<h2 id="最短路徑5-分鐘把-k6-跑起來">最短路徑：5 分鐘把 k6 跑起來</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 1. 安裝</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># TODO: brew install k6 / docker run grafana/k6</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 2. 寫 test.js</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="c1"># TODO: import http from &#39;k6/http&#39;; export default function(){ http.get(...) }</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="c1"># 3. 跑</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="c1"># TODO: k6 run --vus 10 --duration 30s test.js</span></span></span></code></pre></div><h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="test-script-結構">Test script 結構</h3>
<p>子議題：</p>
<ul>
<li>export default function（per-VU iteration）</li>
<li>export const options（VU / duration / stages / thresholds）</li>
<li>Setup / teardown</li>
<li>對應指令範例：<code>k6 run --vus 100 --duration 10m</code></li>
</ul>
<h3 id="threshold--ci-gate">Threshold + CI gate</h3>
<p>子議題：</p>
<ul>
<li>thresholds: <code>http_req_duration: ['p(95)&lt;500']</code></li>
<li>Exit code 非 0 → CI fail</li>
<li>Custom metric thresholds</li>
<li>對應 <a href="/blog/backend/06-reliability/performance-regression-gate/" data-link-title="6.13 Performance Regression Gate" data-link-desc="把效能 baseline 從一次性壓測變成持續對齊的 release gate，涵蓋 baseline 設定、判讀方法、variance 控制與退化定位">6.13 Performance Regression Gate</a></li>
</ul>
<h3 id="test-pattern">Test pattern</h3>
<p>子議題：</p>
<ul>
<li>Smoke / Load / Stress / Spike / Soak / Breakpoint</li>
<li>Stages（ramp-up / steady / ramp-down）</li>
<li>VU vs iteration vs RPS-based</li>
</ul>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<h3 id="xk6-extensions">xk6 extensions</h3>
<p>子議題：</p>
<ul>
<li>自訂 binary：xk6 build + import extension</li>
<li>內建：HTTP / WebSocket / gRPC</li>
<li>社群：Kafka / SQL / Redis / browser</li>
<li>對應 cross-protocol load test</li>
</ul>
<h3 id="k6-operator-on-k8s">k6 Operator on K8s</h3>
<p>子議題：</p>
<ul>
<li>TestRun CRD</li>
<li>Distributed load（多 pod 模擬高 VU）</li>
<li>Result aggregation</li>
<li>對應 <a href="/blog/backend/05-deployment-platform/vendors/kubernetes/" data-link-title="Kubernetes" data-link-desc="Container orchestration 主流、GKE / EKS / AKS / 自管">Kubernetes vendor 頁</a></li>
</ul>
<h3 id="grafana-cloud-k6">Grafana Cloud k6</h3>
<p>子議題：</p>
<ul>
<li>Managed runner（多 region load source）</li>
<li>跟 Grafana dashboard 整合</li>
<li>跟 Loki / Tempo trace 關聯（test → APM trace）</li>
</ul>
<h3 id="browser-testing">Browser testing</h3>
<p>子議題：</p>
<ul>
<li>k6 browser：Chromium-based browser testing</li>
<li>跟 Playwright 重疊但更聚焦 load</li>
<li>適合 frontend regression load test</li>
</ul>
<h3 id="ci-integration">CI integration</h3>
<p>子議題：</p>
<ul>
<li>GitHub Actions / GitLab CI / Jenkins 整合</li>
<li>Artifact + report upload</li>
<li>對應 <a href="/blog/backend/06-reliability/release-gate/" data-link-title="6.8 Release Gate 與變更節奏" data-link-desc="把驗證、migration、相容性納入放行判準">6.8 Release Gate</a></li>
</ul>
<h3 id="k6-vs-xk6-vs-cloud">k6 vs xk6 vs Cloud</h3>
<p>子議題：</p>
<ul>
<li>k6 OSS：CLI + local script</li>
<li>xk6：build custom binary with extensions</li>
<li>k6 Cloud / Grafana Cloud k6：managed + UI</li>
</ul>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<h3 id="test-結果差異大">Test 結果差異大</h3>
<p>操作原則：local network / VU saturation / target 處理能力。</p>
<h3 id="threshold-太鬆--太嚴">Threshold 太鬆 / 太嚴</h3>
<p>操作原則：baseline 不準 / production traffic pattern 沒模擬。</p>
<h3 id="distributed-load-不均勻">Distributed load 不均勻</h3>
<p>操作原則：k6 Operator 分配 VU 不均 / pod 規格差異。</p>
<h3 id="browser-testing-慢--不穩">Browser testing 慢 / 不穩</h3>
<p>操作原則：Chromium 啟動成本 / network condition / target 反應時間。</p>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>JVM 生態</td>
          <td><a href="/blog/backend/06-reliability/vendors/gatling/" data-link-title="Gatling" data-link-desc="JVM-based load test、Scala / Java / Kotlin DSL、強型別 scenario、HAR-driven recording">Gatling</a></td>
      </tr>
      <tr>
          <td>GUI / 老牌</td>
          <td><a href="/blog/backend/06-reliability/vendors/jmeter/" data-link-title="Apache JMeter" data-link-desc="老牌 load test 工具、GUI &#43; plugins">JMeter</a></td>
      </tr>
      <tr>
          <td>Python</td>
          <td><a href="/blog/backend/06-reliability/vendors/locust/" data-link-title="Locust" data-link-desc="Python-based load test、distributed、易擴展">Locust</a></td>
      </tr>
      <tr>
          <td>純 browser flow</td>
          <td>Playwright / Cypress</td>
      </tr>
      <tr>
          <td>Cloud managed</td>
          <td>Grafana Cloud k6 / BlazeMeter / k6 Cloud</td>
      </tr>
      <tr>
          <td>Capacity planning（非 CI）</td>
          <td><a href="/blog/backend/09-performance-capacity/" data-link-title="模組九：效能工程與容量規劃" data-link-desc="把『目前配置能撐多少、要加多少機器』變成可量化、可驗證、可改進的工程流程">09 performance capacity 模組</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>JS 語言基礎</li>
<li>k6 完整 API</li>
<li>Grafana Cloud k6 pricing</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<table>
  <thead>
      <tr>
          <th>案例方向</th>
          <th>對應主題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/06-reliability/cases/shopify/bfcm-capacity-and-game-day/" data-link-title="Shopify：BFCM 容量治理與 Game Day 驗證節奏" data-link-desc="把季節性流量峰值轉成年度可靠性流程，透過容量模型、演練與隔離策略提前吸收風險。">Shopify：BFCM 容量治理與 Game Day</a></td>
          <td>峰值前 load test 對齊 capacity model + CI gate</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/06-reliability/cases/linkedin/capacity-headroom-and-oncall-tiering/" data-link-title="LinkedIn：Capacity Headroom 與 On-call 分層" data-link-desc="把容量預測與值班分層綁在一起，降低高峰時段的升級混亂與恢復延遲。">LinkedIn：Capacity 與 On-call 分層</a></td>
          <td>automated load testing 變成日常流程的工程化做法</td>
      </tr>
  </tbody>
</table>
<p><strong>待補 k6 customer case</strong>：Grafana Labs / k6 customer engineering blog、企業遷移 JMeter → k6 案例。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游概念：<a href="/blog/backend/06-reliability/performance-regression-gate/" data-link-title="6.13 Performance Regression Gate" data-link-desc="把效能 baseline 從一次性壓測變成持續對齊的 release gate，涵蓋 baseline 設定、判讀方法、variance 控制與退化定位">6.13 Performance Regression Gate</a></li>
<li>平行 vendor：<a href="/blog/backend/06-reliability/vendors/gatling/" data-link-title="Gatling" data-link-desc="JVM-based load test、Scala / Java / Kotlin DSL、強型別 scenario、HAR-driven recording">Gatling</a>、<a href="/blog/backend/06-reliability/vendors/locust/" data-link-title="Locust" data-link-desc="Python-based load test、distributed、易擴展">Locust</a>、<a href="/blog/backend/06-reliability/vendors/jmeter/" data-link-title="Apache JMeter" data-link-desc="老牌 load test 工具、GUI &#43; plugins">JMeter</a></li>
<li>下游能力：<a href="/blog/backend/09-performance-capacity/" data-link-title="模組九：效能工程與容量規劃" data-link-desc="把『目前配置能撐多少、要加多少機器』變成可量化、可驗證、可改進的工程流程">09 performance capacity</a> load test 模組</li>
</ul>
]]></content:encoded></item><item><title>Memcached</title><link>https://tarrragon.github.io/blog/backend/02-cache-redis/vendors/memcached/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/02-cache-redis/vendors/memcached/</guid><description>&lt;p>Memcached 是純粹的 in-memory key-value cache、承擔三個責任：簡單 string KV cache、多執行緒高吞吐、嚴格的 cache 邊界（無持久化 / 無 data types / 無 lock）。設計取捨偏向「越簡單越好」— 沒有 Redis 的 data types / Streams / Pub/Sub、也沒有持久化 / 複製 / cluster mode。極輕量、運維成本低、適合 strict cache 場景。&lt;/p>
&lt;p>對「純 cache、避免誤用為 source-of-truth、需要多執行緒高 throughput、極簡運維」這條路徑、Memcached 是首選。從 LiveJournal 2003 年開源至今、是業界最久經考驗的 cache。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>跑起 Memcached、用 telnet 或 memcached-tool 驗證&lt;/li>
&lt;li>用 SET / GET / DELETE / INCR / DECR 操作、區分 Memcached 跟 Redis 的場景界限&lt;/li>
&lt;li>設計 client-side consistent hashing 做 sharding&lt;/li>
&lt;li>看懂 hit rate / slab fragmentation / eviction 訊號&lt;/li>
&lt;li>評估 Memcached vs Redis 的選用判讀（何時純粹勝過豐富）&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑5-分鐘把-memcached-跑起來">最短路徑：5 分鐘把 Memcached 跑起來&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 1. 啟動 Memcached（-t 4 開 4 條 worker thread、-m 64 給 64MB）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">docker run -d --name memcached -p 11211:11211 memcached:1.6 memcached -t &lt;span class="m">4&lt;/span> -m &lt;span class="m">64&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="c1"># 2. 用 text protocol 驗證讀寫（沒有 redis-cli 這種專屬 CLI、直接走 TCP）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">&lt;span class="c1"># set &amp;lt;key&amp;gt; &amp;lt;flags&amp;gt; &amp;lt;ttl&amp;gt; &amp;lt;bytes&amp;gt;，下一行是 value&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="nb">printf&lt;/span> &lt;span class="s1">&amp;#39;set foo 0 60 3\r\nbar\r\nget foo\r\nquit\r\n&amp;#39;&lt;/span> &lt;span class="p">|&lt;/span> nc localhost &lt;span class="m">11211&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="c1"># STORED&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="c1"># VALUE foo 0 3&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="c1"># bar&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="c1"># END&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">&lt;span class="c1"># 3. 確認多執行緒與記憶體上限&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">&lt;span class="nb">printf&lt;/span> &lt;span class="s1">&amp;#39;stats settings\r\nquit\r\n&amp;#39;&lt;/span> &lt;span class="p">|&lt;/span> nc localhost &lt;span class="m">11211&lt;/span> &lt;span class="p">|&lt;/span> grep -E &lt;span class="s2">&amp;#34;num_threads|maxbytes&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">&lt;span class="c1"># STAT maxbytes 67108864 ← 64MB&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl">&lt;span class="c1"># STAT num_threads 4 ← -t 4 生效&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>最短路徑驗證「Memcached 起來、能讀寫、多執行緒生效」。Memcached 沒有 redis-cli 這類專屬 CLI、實際 ops 走 client library（python-memcached / pylibmc / go memcache）+ &lt;code>stats&lt;/code> 系列命令。實機驗證於 memcached:1.6（VERSION 1.6.42）、最後檢查日 2026-06-16。&lt;/p></description><content:encoded><![CDATA[<p>Memcached 是純粹的 in-memory key-value cache、承擔三個責任：簡單 string KV cache、多執行緒高吞吐、嚴格的 cache 邊界（無持久化 / 無 data types / 無 lock）。設計取捨偏向「越簡單越好」— 沒有 Redis 的 data types / Streams / Pub/Sub、也沒有持久化 / 複製 / cluster mode。極輕量、運維成本低、適合 strict cache 場景。</p>
<p>對「純 cache、避免誤用為 source-of-truth、需要多執行緒高 throughput、極簡運維」這條路徑、Memcached 是首選。從 LiveJournal 2003 年開源至今、是業界最久經考驗的 cache。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>跑起 Memcached、用 telnet 或 memcached-tool 驗證</li>
<li>用 SET / GET / DELETE / INCR / DECR 操作、區分 Memcached 跟 Redis 的場景界限</li>
<li>設計 client-side consistent hashing 做 sharding</li>
<li>看懂 hit rate / slab fragmentation / eviction 訊號</li>
<li>評估 Memcached vs Redis 的選用判讀（何時純粹勝過豐富）</li>
</ol>
<h2 id="最短路徑5-分鐘把-memcached-跑起來">最短路徑：5 分鐘把 Memcached 跑起來</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># 1. 啟動 Memcached（-t 4 開 4 條 worker thread、-m 64 給 64MB）</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">docker run -d --name memcached -p 11211:11211 memcached:1.6 memcached -t <span class="m">4</span> -m <span class="m">64</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c1"># 2. 用 text protocol 驗證讀寫（沒有 redis-cli 這種專屬 CLI、直接走 TCP）</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="c1">#    set &lt;key&gt; &lt;flags&gt; &lt;ttl&gt; &lt;bytes&gt;，下一行是 value</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="nb">printf</span> <span class="s1">&#39;set foo 0 60 3\r\nbar\r\nget foo\r\nquit\r\n&#39;</span> <span class="p">|</span> nc localhost <span class="m">11211</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="c1"># STORED</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="c1"># VALUE foo 0 3</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="c1"># bar</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="c1"># END</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="c1"># 3. 確認多執行緒與記憶體上限</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="nb">printf</span> <span class="s1">&#39;stats settings\r\nquit\r\n&#39;</span> <span class="p">|</span> nc localhost <span class="m">11211</span> <span class="p">|</span> grep -E <span class="s2">&#34;num_threads|maxbytes&#34;</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="c1"># STAT maxbytes 67108864      ← 64MB</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="c1"># STAT num_threads 4          ← -t 4 生效</span></span></span></code></pre></div><p>最短路徑驗證「Memcached 起來、能讀寫、多執行緒生效」。Memcached 沒有 redis-cli 這類專屬 CLI、實際 ops 走 client library（python-memcached / pylibmc / go memcache）+ <code>stats</code> 系列命令。實機驗證於 memcached:1.6（VERSION 1.6.42）、最後檢查日 2026-06-16。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="協議與-client-library">協議與 client library</h3>
<p>子議題：</p>
<ul>
<li>ASCII protocol vs binary protocol（兩種都支援、binary 較有效率）</li>
<li>Client library：python-memcached、pylibmc（libmemcached 綁定）、go memcache、Java spymemcached</li>
<li>Connection management：connection pool / persistent connection</li>
</ul>
<h3 id="指令對照">指令對照</h3>
<p>子議題：</p>
<ul>
<li>基本：SET / GET / ADD / REPLACE / DELETE / FLUSH_ALL</li>
<li>Counter：INCR / DECR（不能 &lt; 0）</li>
<li>條件：CAS（compare-and-swap）做 optimistic lock</li>
<li>批次：GETS（批次 + CAS token）</li>
</ul>
<h3 id="client-side-sharding">Client-side sharding</h3>
<p>Memcached server 本身無 cluster mode、靠 client library 做 sharding。子議題：</p>
<ul>
<li>Consistent hashing（ketama）— 加減 node 時 minimum key 移動</li>
<li>Hash 演算法：md5 / SHA1 / ketama</li>
<li>對應 <a href="/blog/backend/02-cache-redis/cache-data-shape-access-pattern/" data-link-title="2.8 Cache Data Shape 與 Access Pattern" data-link-desc="說明 cache value、key space、資料結構與存取型態如何反映服務語意。">2.4 cache data shape</a></li>
</ul>
<h3 id="memory-modelslab-allocator">Memory model（slab allocator）</h3>
<p>子議題：</p>
<ul>
<li>Memcached 用 slab allocator 預分配記憶體 chunk</li>
<li>不同 size class（slab class）對應不同 chunk size</li>
<li>Fragmentation：當 value size 跟 slab 不對齊、memory 浪費</li>
<li>對應指令：<code>stats slabs</code> / <code>stats items</code></li>
</ul>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<h3 id="slab-allocator-與-memory-fragmentation">Slab allocator 與 memory fragmentation</h3>
<p>子議題：</p>
<ul>
<li>Slab class 自動分配機制</li>
<li>Slab reassignment（Memcached 1.4.25+）— 把記憶體在 slab class 間搬移</li>
<li>監控 <code>STAT total_malloced</code> vs <code>STAT bytes_read</code></li>
<li>對應指令：<code>stats slabs</code>、<code>slabs reassign &lt;src&gt; &lt;dst&gt;</code></li>
</ul>
<h3 id="multi-threaded-scaling">Multi-threaded scaling</h3>
<p>子議題：</p>
<ul>
<li>Memcached 從早期就 multi-threaded（vs Redis 早期 single-thread）</li>
<li><code>-t</code> 設 thread 數、預設 4、依 CPU core 調</li>
<li>Lock contention：高 thread 數可能 hit per-bucket lock</li>
<li>對比 Redis：Redis 6+ 加 I/O threads、但 main thread 仍單線</li>
</ul>
<h3 id="aws-elasticache-for-memcached">AWS ElastiCache for Memcached</h3>
<p>子議題：</p>
<ul>
<li>ElastiCache 提供 managed Memcached cluster</li>
<li>Auto Discovery：客戶端自動發現 cluster node 變化</li>
<li>ElastiCache config endpoint 取代 client-side sharding 配置</li>
<li>跟 Redis ElastiCache 的成本對照</li>
</ul>
<h3 id="cascompare-and-swap">CAS（compare-and-swap）</h3>
<p>子議題：</p>
<ul>
<li>GETS 拿 value + token、SET 帶 token 做 conditional update</li>
<li>適合做 optimistic lock（vs Redis SETNX + lua）</li>
<li>CAS 失敗時的 retry 策略</li>
</ul>
<h3 id="memcached-vs-redis-的場景區分">Memcached vs Redis 的場景區分</h3>
<p>子議題：</p>
<ul>
<li>純 cache 不需 data types → Memcached 更輕量</li>
<li>Session store / counter / hot key 兩者都行</li>
<li>Leaderboard / sorted set / Streams / Pub/Sub → 只 Redis</li>
<li>Distributed lock → Redis（Memcached CAS 不夠強）</li>
<li>持久化（cache warmup 後不想全失）→ Redis（RDB / AOF）</li>
</ul>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<h3 id="hit-rate-下降">Hit rate 下降</h3>
<p>操作原則：先看 eviction 是否提高、再看 key naming 是否變動。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="nb">printf</span> <span class="s1">&#39;stats\r\nquit\r\n&#39;</span> <span class="p">|</span> nc localhost <span class="m">11211</span> <span class="p">|</span> grep -E <span class="s2">&#34;get_hits|get_misses|evictions&#34;</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># get_hits / get_misses 算 hit rate、evictions 持續增加代表 memory 壓力</span></span></span></code></pre></div><h3 id="eviction-增加memory-pressure">Eviction 增加（memory pressure）</h3>
<p>操作原則：超過 <code>-m</code> 設定的 memory limit、Memcached 用 LRU evict 老 key。看 <code>stats slabs</code> 哪些 slab class 最常 evict、可能要 slab reassign。</p>
<h3 id="slab-fragmentation">Slab fragmentation</h3>
<p>操作原則：value size 跟 slab class 不對齊造成 wasted memory。判讀：<code>stats slabs</code> 看每個 slab class 的 used vs total chunks。</p>
<h3 id="client-side-sharding-不平衡">Client-side sharding 不平衡</h3>
<p>操作原則：node 加減後、ketama 應 minimum 移動、但實際分布可能因 key 集中而偏斜。判讀：每個 node 的 <code>stats</code> 看 key count + memory usage 是否均衡。</p>
<h3 id="connection-耗盡">Connection 耗盡</h3>
<p>操作原則：每個 client 開太多 connection、Memcached 預設 max 1024 connection。看 <code>stats curr_connections</code>。</p>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>需要 data types（hash / list / set）</td>
          <td><a href="/blog/backend/02-cache-redis/vendors/redis/" data-link-title="Redis" data-link-desc="OSS in-memory data structure store、cache 主流">Redis</a> / <a href="/blog/backend/02-cache-redis/vendors/valkey/" data-link-title="Valkey" data-link-desc="Redis fork、Linux Foundation 託管、BSD 授權">Valkey</a></td>
      </tr>
      <tr>
          <td>需要持久化 / 半持久化</td>
          <td>Redis with AOF / RDB</td>
      </tr>
      <tr>
          <td>需要 distributed lock</td>
          <td>Redis（Redlock 或 SETNX）</td>
      </tr>
      <tr>
          <td>需要 Pub/Sub / Streams</td>
          <td>Redis / Kafka / NATS</td>
      </tr>
      <tr>
          <td>多核高 throughput</td>
          <td><a href="/blog/backend/02-cache-redis/vendors/dragonflydb/" data-link-title="DragonflyDB" data-link-desc="高效能 Redis / Memcached 相容替代、多核架構">DragonflyDB</a></td>
      </tr>
      <tr>
          <td>AWS managed</td>
          <td><a href="/blog/backend/02-cache-redis/vendors/aws-elasticache/" data-link-title="AWS ElastiCache" data-link-desc="AWS managed Redis / Valkey / Memcached">AWS ElastiCache for Memcached</a></td>
      </tr>
      <tr>
          <td>Process-local cache</td>
          <td><a href="/blog/backend/02-cache-redis/vendors/caffeine/" data-link-title="Caffeine" data-link-desc="JVM process-local cache、Window TinyLFU、Guava Cache 後繼">Caffeine</a> / Guava Cache（JVM 內、無網路）</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>各語言 Memcached client 完整 API</li>
<li>Memcached internal data structure 細節</li>
<li>Custom binary protocol 實作</li>
<li>ASCII vs binary protocol 完整對照</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<h3 id="直接相關案例">直接相關案例</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>對 Memcached 的對應</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/meta-mcrouter-global-cache-routing/" data-link-title="2.C2 Meta：mcrouter 與跨區快取路由" data-link-desc="快取從單點最佳化演進到分散式路由層的案例。">2.C2 Meta mcrouter</a></td>
          <td>mcrouter 是 Memcached 專屬 protocol-aware routing proxy、處理跨叢集 / 跨區流量收斂與失效隔離</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/netflix-evcache-global-cache-layer/" data-link-title="2.C6 Netflix：EVCache 全域快取層" data-link-desc="快取從本地層演進為跨區分散式能力的案例。">2.C6 Netflix EVCache</a></td>
          <td>EVCache 基於 Memcached、Netflix 加上跨 AZ replication + client-side smart routing</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/meta-tao-social-graph-cache-evolution/" data-link-title="2.C8 Meta：TAO 社交圖快取演進" data-link-desc="社交圖查詢在規模化下如何把快取做成資料層能力。">2.C8 Meta TAO</a></td>
          <td>TAO 底層用 Memcached 作為 graph 資料的快取層、上層加一致性 / 關聯查詢能力</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/meta-cache-consistency-upgrade/" data-link-title="2.C1 Meta：Cache Consistency 升級" data-link-desc="快取 invalidation 一致性如何從常見錯誤演進到高可信治理。">2.C1 Meta cache consistency</a></td>
          <td>Meta 大規模 Memcached 部署的 invalidation / shard move 一致性治理</td>
      </tr>
  </tbody>
</table>
<h3 id="跨-vendor-對照">跨 vendor 對照</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>對 Memcached 的對應</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/failure-cache-stampede-rollout-regression/" data-link-title="2.C9 反例：快取切換引發 Stampede 回歸" data-link-desc="快取策略切換若缺乏保護，會導致回源壓力與錯誤率連鎖上升。">2.C9 Cache Stampede</a></td>
          <td>通用、Memcached 也需 TTL jitter / lease / probabilistic early expiration</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/contrast-cache-strategy-by-scale/" data-link-title="2.C10 對照：規模差異下的快取策略" data-link-desc="同一快取策略在小中大型服務下會產生不同風險。">2.C10 規模對照</a></td>
          <td>小型 single instance / 中型 client-side ketama / 大型 mcrouter 路由 + 跨區 pool</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/meta-cachelib-kangaroo-tiered-cache/" data-link-title="2.C4 Meta：CacheLib / Kangaroo 分層快取" data-link-desc="快取從 DRAM-only 轉向分層快取架構的實務案例。">2.C4 Meta CacheLib + Kangaroo</a></td>
          <td>CacheLib 是 Memcached 之後 Meta 的分層 cache library、處理 DRAM 經濟極限後的議題</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/shopify-cache-serialization-migration/" data-link-title="2.C3 Shopify：快取序列化格式遷移" data-link-desc="快取 payload 從 Marshal 轉 MessagePack 的遷移策略。">2.C3 Shopify serialization</a></td>
          <td>Payload 編碼遷移在 Memcached 上一樣適用、雙軌策略不依賴 vendor</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/shopify-write-through-cache-at-scale/" data-link-title="2.C5 Shopify：Write-through Cache 在高讀流量的實作" data-link-desc="read-heavy 服務如何轉向 write-through 快取模型。">2.C5 Shopify write-through</a></td>
          <td>Write-through 模式 Memcached 用 SET + CAS 實作、不像 Redis 有 Lua / transaction 可組合</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游概念：<a href="/blog/backend/02-cache-redis/cache-aside/" data-link-title="2.2 cache aside 與失效策略" data-link-desc="整理 read-through 思路、cache miss 與 invalidation">2.2 Cache Aside</a>、<a href="/blog/backend/02-cache-redis/ttl-eviction/" data-link-title="2.3 TTL 與 eviction" data-link-desc="整理過期策略、容量控制與熱點資料">2.3 TTL eviction</a></li>
<li>平行 vendor：<a href="/blog/backend/02-cache-redis/vendors/redis/" data-link-title="Redis" data-link-desc="OSS in-memory data structure store、cache 主流">Redis</a>、<a href="/blog/backend/02-cache-redis/vendors/aws-elasticache/" data-link-title="AWS ElastiCache" data-link-desc="AWS managed Redis / Valkey / Memcached">AWS ElastiCache</a></li>
<li>下游能力：<a href="/blog/backend/02-cache-redis/cache-data-shape-access-pattern/" data-link-title="2.8 Cache Data Shape 與 Access Pattern" data-link-desc="說明 cache value、key space、資料結構與存取型態如何反映服務語意。">2.4 cache data shape</a></li>
</ul>
]]></content:encoded></item><item><title>NATS</title><link>https://tarrragon.github.io/blog/backend/03-message-queue/vendors/nats/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/03-message-queue/vendors/nats/</guid><description>&lt;p>NATS 是 lightweight high-performance messaging system、承擔三個責任：subject-based routing（hierarchical wildcards）、low-latency messaging（Core NATS、fire-and-forget）、選擇性持久化（JetStream、streams + KV + Object Store）。設計取捨偏向「協議極簡、運維輕、必要時才開持久化」、適合微服務通訊跟 edge 場景。&lt;/p>
&lt;p>對「微服務 messaging、IoT/edge、Request/Reply、需要 messaging + KV 一體」這條路徑、NATS 是輕量首選。本頁先給最短路徑、再展開日常 publish / subscribe 與 subject 設計、最後進階治理（JetStream、supercluster、leaf node）跟排錯。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>用 nats-server 跑起 NATS（含 JetStream）、驗證 broker 健康&lt;/li>
&lt;li>用 nats CLI publish / subscribe、看 subject hierarchy 匹配&lt;/li>
&lt;li>區分 Core NATS（fire-and-forget）vs JetStream（durable）的選用判讀&lt;/li>
&lt;li>看懂 stream 配置、consumer 配置、pending 訊號&lt;/li>
&lt;li>評估 supercluster、leaf node、KV / Object Store 等延伸場景&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑5-分鐘把-nats-跑起來">最短路徑：5 分鐘把 NATS 跑起來&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 1. 啟動 NATS server（-js 開 JetStream、-m 8222 開監控埠）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">docker run -d --name nats -p 4222:4222 -p 8222:8222 nats:latest -js -m &lt;span class="m">8222&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="c1"># 2. 用 nats CLI publish / subscribe（CLI 可用 natsio/nats-box 容器）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">&lt;span class="c1"># docker run --rm --network host natsio/nats-box nats &amp;lt;subcommand&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">nats --server nats://localhost:4222 pub demo.hello &lt;span class="s2">&amp;#34;world&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">nats --server nats://localhost:4222 sub &lt;span class="s2">&amp;#34;demo.&amp;gt;&amp;#34;&lt;/span> &lt;span class="c1"># 另開一個 shell 持續訂閱&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="c1"># 3. 建 JetStream stream + pull consumer（持久化 + ack）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">nats --server nats://localhost:4222 stream add demo --subjects &lt;span class="s1">&amp;#39;demo.&amp;gt;&amp;#39;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> --storage file --retention limits --discard old --defaults
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">nats --server nats://localhost:4222 consumer add demo worker &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> --pull --deliver all --ack explicit --filter &lt;span class="s1">&amp;#39;demo.&amp;gt;&amp;#39;&lt;/span> --defaults&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>最短路徑驗證「Core NATS + JetStream 都可用」。實際寫程式用 nats client library、見&lt;a href="#%e6%97%a5%e5%b8%b8%e6%93%8d%e4%bd%9c%e8%88%87%e6%b1%ba%e7%ad%96%e5%bd%a2%e7%8b%80">日常操作&lt;/a>。&lt;/p>
&lt;h2 id="日常操作與決策形狀">日常操作與決策形狀&lt;/h2>
&lt;h3 id="cli-與-client-api">CLI 與 client API&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>nats CLI 指令對照表（pub / sub / stream / consumer / kv）&lt;/li>
&lt;li>監控 endpoint（&lt;code>/varz&lt;/code> / &lt;code>/connz&lt;/code> / &lt;code>/jsz&lt;/code> HTTP）&lt;/li>
&lt;li>Client library 配置：connection / reconnect / timeout / async / sync subscribe&lt;/li>
&lt;li>對應指令範例：&lt;code>nats stream info &amp;lt;name&amp;gt;&lt;/code>、&lt;code>nats consumer info &amp;lt;stream&amp;gt; &amp;lt;consumer&amp;gt;&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="subject-hierarchy-與-wildcard">Subject hierarchy 與 wildcard&lt;/h3>
&lt;p>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/topic/" data-link-title="Topic" data-link-desc="說明 topic 如何把事件依主題分流給不同訂閱者">Subject&lt;/a> 是 NATS 路由的核心、層級式設計：&lt;/p></description><content:encoded><![CDATA[<p>NATS 是 lightweight high-performance messaging system、承擔三個責任：subject-based routing（hierarchical wildcards）、low-latency messaging（Core NATS、fire-and-forget）、選擇性持久化（JetStream、streams + KV + Object Store）。設計取捨偏向「協議極簡、運維輕、必要時才開持久化」、適合微服務通訊跟 edge 場景。</p>
<p>對「微服務 messaging、IoT/edge、Request/Reply、需要 messaging + KV 一體」這條路徑、NATS 是輕量首選。本頁先給最短路徑、再展開日常 publish / subscribe 與 subject 設計、最後進階治理（JetStream、supercluster、leaf node）跟排錯。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>用 nats-server 跑起 NATS（含 JetStream）、驗證 broker 健康</li>
<li>用 nats CLI publish / subscribe、看 subject hierarchy 匹配</li>
<li>區分 Core NATS（fire-and-forget）vs JetStream（durable）的選用判讀</li>
<li>看懂 stream 配置、consumer 配置、pending 訊號</li>
<li>評估 supercluster、leaf node、KV / Object Store 等延伸場景</li>
</ol>
<h2 id="最短路徑5-分鐘把-nats-跑起來">最短路徑：5 分鐘把 NATS 跑起來</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># 1. 啟動 NATS server（-js 開 JetStream、-m 8222 開監控埠）</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">docker run -d --name nats -p 4222:4222 -p 8222:8222 nats:latest -js -m <span class="m">8222</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c1"># 2. 用 nats CLI publish / subscribe（CLI 可用 natsio/nats-box 容器）</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="c1">#    docker run --rm --network host natsio/nats-box nats &lt;subcommand&gt;</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">nats --server nats://localhost:4222 pub demo.hello <span class="s2">&#34;world&#34;</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">nats --server nats://localhost:4222 sub <span class="s2">&#34;demo.&gt;&#34;</span>   <span class="c1"># 另開一個 shell 持續訂閱</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="c1"># 3. 建 JetStream stream + pull consumer（持久化 + ack）</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">nats --server nats://localhost:4222 stream add demo --subjects <span class="s1">&#39;demo.&gt;&#39;</span> <span class="se">\
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="se"></span>  --storage file --retention limits --discard old --defaults
</span></span><span class="line"><span class="ln">12</span><span class="cl">nats --server nats://localhost:4222 consumer add demo worker <span class="se">\
</span></span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="se"></span>  --pull --deliver all --ack explicit --filter <span class="s1">&#39;demo.&gt;&#39;</span> --defaults</span></span></code></pre></div><p>最短路徑驗證「Core NATS + JetStream 都可用」。實際寫程式用 nats client library、見<a href="#%e6%97%a5%e5%b8%b8%e6%93%8d%e4%bd%9c%e8%88%87%e6%b1%ba%e7%ad%96%e5%bd%a2%e7%8b%80">日常操作</a>。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="cli-與-client-api">CLI 與 client API</h3>
<p>子議題：</p>
<ul>
<li>nats CLI 指令對照表（pub / sub / stream / consumer / kv）</li>
<li>監控 endpoint（<code>/varz</code> / <code>/connz</code> / <code>/jsz</code> HTTP）</li>
<li>Client library 配置：connection / reconnect / timeout / async / sync subscribe</li>
<li>對應指令範例：<code>nats stream info &lt;name&gt;</code>、<code>nats consumer info &lt;stream&gt; &lt;consumer&gt;</code></li>
</ul>
<h3 id="subject-hierarchy-與-wildcard">Subject hierarchy 與 wildcard</h3>
<p><a href="/blog/backend/knowledge-cards/topic/" data-link-title="Topic" data-link-desc="說明 topic 如何把事件依主題分流給不同訂閱者">Subject</a> 是 NATS 路由的核心、層級式設計：</p>
<ul>
<li>層級用 <code>.</code> 分隔（例：<code>orders.created.us-west</code>）</li>
<li>單層 wildcard <code>*</code>（匹配一層）</li>
<li>多層 wildcard <code>&gt;</code>（匹配剩餘所有層）</li>
<li>Subject 命名規範與 ownership</li>
</ul>
<h3 id="core-nats-vs-jetstream">Core NATS vs JetStream</h3>
<p>子議題：</p>
<ul>
<li>Core NATS：fire-and-forget、無持久化、極低延遲、適合即時通知 / 控制信號</li>
<li>JetStream：append-only stream + durable consumer、適合需要 replay / 持久化的事件流</li>
<li>兩者並存設計（同一 NATS server 同時跑）</li>
</ul>
<h3 id="requestreply-與-queue-groups">Request/Reply 與 Queue groups</h3>
<p>子議題：</p>
<ul>
<li>Request/Reply pattern（RPC over messaging）</li>
<li>Queue groups（load balancing、多 subscriber 分擔同 subject）</li>
<li>Pub/Sub vs Queue groups 的差異</li>
</ul>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<p>JetStream 已展開為兩篇 deep article：<a href="jetstream-durability-consumer/">core 到 JetStream 邊界</a>（採用決策入口）、<a href="jetstream-supercluster-design/">JetStream 設計與 supercluster/leaf node</a>（stream / consumer / 跨區拓樸 / 多租戶完整實作）。下列子議題段保留選題判讀入口。</p>
<h3 id="jetstream-stream-設計">JetStream stream 設計</h3>
<p>子議題：</p>
<ul>
<li>Stream 配置（subjects、retention policy、storage type）</li>
<li>File-based vs Memory-based storage</li>
<li>MaxMsgs / MaxBytes / MaxAge（保留策略）</li>
<li>Replicas（JetStream raft、跨節點一致性）</li>
</ul>
<h3 id="jetstream-consumer-設計">JetStream consumer 設計</h3>
<p>子議題：</p>
<ul>
<li>Durable vs ephemeral consumer</li>
<li>Push vs pull consumer</li>
<li>Ack 策略（explicit ack / all / none）</li>
<li>AckWait + MaxDeliver + DeliverPolicy（重試控制）</li>
</ul>
<h3 id="cluster--supercluster--leaf-node">Cluster / Supercluster / Leaf node</h3>
<p>子議題：</p>
<ul>
<li>Cluster：單一 region 多 broker、JetStream raft 同步</li>
<li>Supercluster：跨 cluster gateway、跨區延展</li>
<li>Leaf node：邊緣節點、subject mapping、適合 IoT / edge 場景</li>
<li>對應 <a href="/blog/backend/03-message-queue/cases/cloudflare-queues-global-delivery-model/" data-link-title="3.C8 Cloudflare：Queues 全球交付模型" data-link-desc="事件佇列服務在全球網路下的交付語義與治理案例。">3.C8 Cloudflare Queues 全球交付</a> 的對照思路</li>
</ul>
<h3 id="jetstream-kv--object-store">JetStream KV / Object Store</h3>
<p>子議題：</p>
<ul>
<li>KV store（基於 JetStream、簡單 key-value）</li>
<li>Object Store（基於 JetStream、大 blob）</li>
<li>何時用 NATS KV vs 真的 KV 服務（Redis / etcd）</li>
</ul>
<h3 id="subject-based-acl-與多租戶">Subject-based ACL 與多租戶</h3>
<p>子議題：</p>
<ul>
<li>Account 隔離（multi-tenancy 主機制）</li>
<li>Subject-level permission（publish / subscribe）</li>
<li>Cross-account import / export</li>
</ul>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<h3 id="consumer-pending-累積">Consumer pending 累積</h3>
<p>操作原則：先看 pending 是 ack-pending 還是 stream backlog、再定位 consumer 慢 vs stream 寫入過快。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">nats --server nats://localhost:4222 consumer info &lt;stream&gt; &lt;consumer&gt;
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># 看 Unprocessed Messages（stream backlog）與 Redelivered / Acknowledgment Pending（ack-pending）區分兩種累積</span></span></span></code></pre></div><h3 id="stream-超-retention-limit">Stream 超 retention limit</h3>
<p>操作原則：超 MaxBytes / MaxMsgs 時 stream 觸發 discard policy、看是 old discard 還是 new discard。</p>
<h3 id="leaf-node-連線不穩">Leaf node 連線不穩</h3>
<p>操作原則：邊緣節點到 hub 的網路品質決定 subject mapping 延遲、看 reconnect 次數與 latency。</p>
<h3 id="subject-路由錯誤">Subject 路由錯誤</h3>
<p>操作原則：wildcard 設計錯導致訂閱不到、或匹配過多。看 subject hierarchy 規範與實際 subject。</p>
<h3 id="jetstream-raft-不一致">JetStream raft 不一致</h3>
<p>操作原則：replica 配置 R3 但只有 2 個健康節點、stream 變 read-only。看 cluster info 與 raft state。</p>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>高吞吐事件流（百萬 msg/sec）</td>
          <td><a href="/blog/backend/03-message-queue/vendors/kafka/" data-link-title="Apache Kafka" data-link-desc="Distributed event streaming platform、log-based 模型">Kafka</a></td>
      </tr>
      <tr>
          <td>複雜 routing（exchange model）</td>
          <td><a href="/blog/backend/03-message-queue/vendors/rabbitmq/" data-link-title="RabbitMQ" data-link-desc="Classic message broker、AMQP routing 為主">RabbitMQ</a></td>
      </tr>
      <tr>
          <td>Managed queue（AWS / GCP）</td>
          <td><a href="/blog/backend/03-message-queue/vendors/aws-sqs/" data-link-title="AWS SQS" data-link-desc="AWS managed queue、簡單可靠、無 ordering（standard）">SQS</a> / <a href="/blog/backend/03-message-queue/vendors/google-pubsub/" data-link-title="Google Cloud Pub/Sub" data-link-desc="GCP managed pub/sub、global routing、push/pull">Pub/Sub</a></td>
      </tr>
      <tr>
          <td>Redis 生態已存在</td>
          <td><a href="/blog/backend/03-message-queue/vendors/redis-streams/" data-link-title="Redis Streams" data-link-desc="Redis 生態內的 streams、append-only log &#43; consumer group">Redis Streams</a></td>
      </tr>
      <tr>
          <td>大型企業生態整合</td>
          <td>RabbitMQ / Kafka（社群更大）</td>
      </tr>
      <tr>
          <td>Managed NATS</td>
          <td>Synadia Cloud</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>各語言 client 完整 API（依官方文件）</li>
<li>NATS 跟 gRPC 的對比（在分散式通訊章節）</li>
<li>Synadia Cloud 商業功能</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<h3 id="nats-專屬案例c34-c41">NATS 專屬案例（C34-C41）</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>主討論議題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/nats-netlify-data-plane-fanout/" data-link-title="3.C34 Netlify：NATS 當全球 metrics/logs 統一資料平面" data-link-desc="Netlify 70K&#43; 網站、10 億 PV/月、跨多雲、NATS 當 all-purpose data plane fan-out bus、超 RabbitMQ 評估。">3.C34 Netlify data plane</a></td>
          <td>全球 metrics / logs fan-out</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/nats-form3-multi-cloud-payments/" data-link-title="3.C35 Form3：NATS JetStream 多雲低延遲支付" data-link-desc="Form3 服務 Tier-1 銀行、500ms SLA、SNS/SQS 吃 300ms 預算、改 NATS&#43;JetStream 跨雲 6x 延遲改善。">3.C35 Form3 multi-cloud</a></td>
          <td>JetStream Leaf Node 跨雲低延遲支付</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/nats-intelecy-industrial-iot/" data-link-title="3.C36 Intelecy：工業 IoT 即時感測 &#43; 多租戶" data-link-desc="Intelecy 工廠 gateway 接數萬感測器、&lt; 2 秒往返延遲做即時 ML、從 BoltDB 本地快取演進到 JetStream 持久化。">3.C36 Intelecy IoT</a></td>
          <td>工業 IoT / BoltDB → JetStream</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/nats-machinemetrics-edge-to-cloud/" data-link-title="3.C37 MachineMetrics：邊緣到雲端工廠資料管線" data-link-desc="MachineMetrics 跨數百工廠、數千機台、1000Hz 採樣、Kinesis 無法跑在 edge、改 NATS Leaf Node &#43; JetStream &#43; KV &#43; Object Store。">3.C37 MachineMetrics edge</a></td>
          <td>Leaf node + KV + Object Store + 多租戶 Auth</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/nats-clarifai-async-task-queue/" data-link-title="3.C38 Clarifai：NATS Streaming ML 平台非同步任務" data-link-desc="Clarifai custom model 訓練、rolling deploy 掉訊息、改 NATS Streaming queue group、3 週遷移 1 服務、5 月 5 服務、每日 100k&#43; 訊息 100% uptime。">3.C38 Clarifai ML</a></td>
          <td>NATS Streaming queue group / at-least-once</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/nats-choria-orchestration-fleet/" data-link-title="3.C39 Choria：NATS 管 50 萬 server fleet" data-link-desc="Choria 替代 Puppet MCollective、NATS 單 binary 無 Zookeeper、4GB node 可達 50 萬 server、wildcard &#43; queue group 做 scatter-gather RPC。">3.C39 Choria fleet</a></td>
          <td>Request/Reply + Queue group / 50 萬 server</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/nats-resgate-realtime-api-gateway/" data-link-title="3.C40 Resgate：WebSocket-to-NATS realtime API gateway" data-link-desc="Resgate 把 NATS subject 暴露成 REST &#43; WebSocket、subject 階層當 schema、event 延遲 &lt; 1ms、純 Core NATS。">3.C40 Resgate API gateway</a></td>
          <td>Subject hierarchy 即 schema / Core NATS</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/nats-iflow-ot-it-integration/" data-link-title="3.C41 i-flow：NATS 做 OT/IT 跨層整合 bus" data-link-desc="i-flow 每日 4 億筆 data operation、200&#43; OT/IT connector、客戶含 Bosch / Sto / Lenze、NATS 當邊緣到 central 整合 bus。">3.C41 i-flow OT/IT</a></td>
          <td>多工廠 leaf node hub-and-spoke</td>
      </tr>
  </tbody>
</table>
<h3 id="跨-vendor-對照">跨 vendor 對照</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>對 NATS 的對應</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/cloudflare-queues-global-delivery-model/" data-link-title="3.C8 Cloudflare：Queues 全球交付模型" data-link-desc="事件佇列服務在全球網路下的交付語義與治理案例。">3.C8 Cloudflare Queues</a></td>
          <td>全球交付對照：leaf node + supercluster</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/contrast-queue-model-by-scale/" data-link-title="3.C10 對照：規模差異下的佇列模型" data-link-desc="同一 queue 模型在不同規模下的治理與失敗邊界差異。">3.C10 規模對照</a></td>
          <td>小型 messaging / 中型 JetStream / 大型 supercluster</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游概念：<a href="/blog/backend/00-service-selection/async-delivery-selection/" data-link-title="0.3 非同步與事件傳遞選型" data-link-desc="區分背景工作、durable queue、stream、pub/sub 與 outbox 的選型邊界">0.3 非同步選型</a>、<a href="/blog/backend/03-message-queue/broker-basics/" data-link-title="3.1 broker 基礎與投遞模型" data-link-desc="先理解 broker、queue、consumer 與 delivery semantics">3.1 broker basics</a></li>
<li>平行 vendor：<a href="/blog/backend/03-message-queue/vendors/kafka/" data-link-title="Apache Kafka" data-link-desc="Distributed event streaming platform、log-based 模型">Kafka</a>、<a href="/blog/backend/03-message-queue/vendors/rabbitmq/" data-link-title="RabbitMQ" data-link-desc="Classic message broker、AMQP routing 為主">RabbitMQ</a></li>
<li>下游能力：<a href="/blog/backend/03-message-queue/consumer-design/" data-link-title="3.4 consumer 設計與去重" data-link-desc="整理 consumer、checkpoint 與 replay safety">3.4 consumer 設計</a>、<a href="/blog/backend/03-message-queue/processing-recovery-semantics/" data-link-title="3.6 Processing Semantics 與 Recovery Semantics" data-link-desc="說明投遞成功、處理成功與恢復成功為何是三個不同判斷。">3.6 processing recovery semantics</a></li>
</ul>
]]></content:encoded></item><item><title>systemd</title><link>https://tarrragon.github.io/blog/backend/05-deployment-platform/vendors/systemd/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/05-deployment-platform/vendors/systemd/</guid><description>&lt;p>systemd 是 Linux 主流 init system、承擔三個責任：service unit lifecycle（start / stop / restart / reload）、signal + journald + cgroups 整合、socket activation + timer（cron 替代）。設計取捨偏向「OS-level 整合 + 單機資源管理 + dependency graph」、適合 VM / bare metal 上單機服務、不需要 cluster orchestration 的場景。&lt;/p>
&lt;p>對「VM / bare metal 服務管理、邊緣 / appliance、單機 lifecycle + journal + cgroups」這條路徑、systemd 是 Linux 主流選擇。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>寫 service unit file、配置 Type / Restart / ExecStart&lt;/li>
&lt;li>設計 signal handling + graceful shutdown&lt;/li>
&lt;li>用 journald + journalctl 查 logs&lt;/li>
&lt;li>設定 cgroups v2 resource limit&lt;/li>
&lt;li>用 socket activation / timer 替代 inetd / cron&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑5-分鐘把-systemd-service-跑起來">最短路徑：5 分鐘把 systemd service 跑起來&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 1. 建 unit file（需 root 或 sudo）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">cat &amp;gt; /etc/systemd/system/myapp.service &lt;span class="s">&amp;lt;&amp;lt;&amp;#39;UNIT&amp;#39;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="s">[Unit]
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="s">Description=My Application
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">&lt;span class="s">After=network.target
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="s">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="s">[Service]
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="s">ExecStart=/usr/bin/myapp --config /etc/myapp/config.yaml
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="s">Restart=on-failure
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="s">RestartSec=5
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">&lt;span class="s">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">&lt;span class="s">[Install]
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">&lt;span class="s">WantedBy=multi-user.target
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">&lt;span class="s">UNIT&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl">&lt;span class="c1"># 2. 啟用 + 啟動&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl">systemctl daemon-reload
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl">systemctl &lt;span class="nb">enable&lt;/span> --now myapp
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl">&lt;span class="c1"># 3. 驗證&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl">systemctl status myapp
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">22&lt;/span>&lt;span class="cl">journalctl -u myapp -f&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="日常操作與決策形狀">日常操作與決策形狀&lt;/h2>
&lt;h3 id="unit-file-設計">Unit file 設計&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>Unit type：service / socket / timer / target / mount / path&lt;/li>
&lt;li>Service Type：simple / forking / oneshot / notify / dbus&lt;/li>
&lt;li>Restart：no / on-failure / on-abnormal / always&lt;/li>
&lt;li>ExecStart / ExecStop / ExecReload&lt;/li>
&lt;li>對應指令：&lt;code>systemctl cat myapp.service&lt;/code>、&lt;code>systemctl edit&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="systemctl-指令">systemctl 指令&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>Lifecycle：start / stop / restart / reload / enable / disable&lt;/li>
&lt;li>Status：status / is-active / is-enabled / list-units&lt;/li>
&lt;li>Reload after edit：daemon-reload&lt;/li>
&lt;li>對應指令範例：&lt;code>systemctl status myapp&lt;/code>、&lt;code>systemctl list-units --failed&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="journald-日誌">journald 日誌&lt;/h3>
&lt;p>子議題：&lt;/p></description><content:encoded><![CDATA[<p>systemd 是 Linux 主流 init system、承擔三個責任：service unit lifecycle（start / stop / restart / reload）、signal + journald + cgroups 整合、socket activation + timer（cron 替代）。設計取捨偏向「OS-level 整合 + 單機資源管理 + dependency graph」、適合 VM / bare metal 上單機服務、不需要 cluster orchestration 的場景。</p>
<p>對「VM / bare metal 服務管理、邊緣 / appliance、單機 lifecycle + journal + cgroups」這條路徑、systemd 是 Linux 主流選擇。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>寫 service unit file、配置 Type / Restart / ExecStart</li>
<li>設計 signal handling + graceful shutdown</li>
<li>用 journald + journalctl 查 logs</li>
<li>設定 cgroups v2 resource limit</li>
<li>用 socket activation / timer 替代 inetd / cron</li>
</ol>
<h2 id="最短路徑5-分鐘把-systemd-service-跑起來">最短路徑：5 分鐘把 systemd service 跑起來</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># 1. 建 unit file（需 root 或 sudo）</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">cat &gt; /etc/systemd/system/myapp.service <span class="s">&lt;&lt;&#39;UNIT&#39;
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="s">[Unit]
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="s">Description=My Application
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="s">After=network.target
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="s">
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="s">[Service]
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="s">ExecStart=/usr/bin/myapp --config /etc/myapp/config.yaml
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="s">Restart=on-failure
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="s">RestartSec=5
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="s">
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="s">[Install]
</span></span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="s">WantedBy=multi-user.target
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="s">UNIT</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">
</span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="c1"># 2. 啟用 + 啟動</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">systemctl daemon-reload
</span></span><span class="line"><span class="ln">18</span><span class="cl">systemctl <span class="nb">enable</span> --now myapp
</span></span><span class="line"><span class="ln">19</span><span class="cl">
</span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="c1"># 3. 驗證</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">systemctl status myapp
</span></span><span class="line"><span class="ln">22</span><span class="cl">journalctl -u myapp -f</span></span></code></pre></div><h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="unit-file-設計">Unit file 設計</h3>
<p>子議題：</p>
<ul>
<li>Unit type：service / socket / timer / target / mount / path</li>
<li>Service Type：simple / forking / oneshot / notify / dbus</li>
<li>Restart：no / on-failure / on-abnormal / always</li>
<li>ExecStart / ExecStop / ExecReload</li>
<li>對應指令：<code>systemctl cat myapp.service</code>、<code>systemctl edit</code></li>
</ul>
<h3 id="systemctl-指令">systemctl 指令</h3>
<p>子議題：</p>
<ul>
<li>Lifecycle：start / stop / restart / reload / enable / disable</li>
<li>Status：status / is-active / is-enabled / list-units</li>
<li>Reload after edit：daemon-reload</li>
<li>對應指令範例：<code>systemctl status myapp</code>、<code>systemctl list-units --failed</code></li>
</ul>
<h3 id="journald-日誌">journald 日誌</h3>
<p>子議題：</p>
<ul>
<li>結構化日誌（kv pairs）</li>
<li>journalctl filter（-u / &ndash;since / -p / -f）</li>
<li>對應 logging：persistent vs runtime journal</li>
<li>跟外部 log forwarder（Vector / Fluent Bit）對接</li>
</ul>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<h3 id="signal-handling--graceful-shutdown">Signal handling + graceful shutdown</h3>
<p>子議題：</p>
<ul>
<li>SIGTERM（default stop signal）/ SIGKILL（force kill after timeout）</li>
<li>TimeoutStopSec：grace period</li>
<li>應用程式要 trap SIGTERM 做 cleanup</li>
<li>對應 <a href="/blog/backend/05-deployment-platform/platform-lifecycle-contract/" data-link-title="5.6 Platform Lifecycle Contract" data-link-desc="說明 runtime、startup、readiness、liveness、shutdown 與 drain 如何組成平台生命週期合約。">Platform lifecycle contract</a>（concept 通用）</li>
</ul>
<h3 id="cgroups-v2--resource-limit">cgroups v2 + resource limit</h3>
<p>子議題：</p>
<ul>
<li>CPUQuota / MemoryMax / IOWeight / TasksMax</li>
<li>Slice unit（樹狀 resource 限制）</li>
<li>跟 Kubernetes 的 resource limit 對比（K8s 用 cgroups 但抽象更高）</li>
<li>對應指令：<code>systemd-cgls</code>、<code>systemd-cgtop</code></li>
</ul>
<h3 id="socket-activation">Socket activation</h3>
<p>子議題：</p>
<ul>
<li>用 .socket unit 持有 listening socket、service 啟動時繼承</li>
<li>啟動延遲：socket 一直在、service 按需起</li>
<li>替代 inetd</li>
<li>適合 occasional service / low-traffic</li>
</ul>
<h3 id="systemd-timer">systemd timer</h3>
<p>子議題：</p>
<ul>
<li>.timer unit 替代 cron</li>
<li>OnCalendar / OnUnitActiveSec / RandomizedDelaySec</li>
<li>跟對應 .service unit 配對</li>
<li>比 cron 強：journal log / dependency / 失敗 restart</li>
</ul>
<h3 id="portable-services--systemd-run">Portable services + systemd-run</h3>
<p>子議題：</p>
<ul>
<li>systemd-run：ad-hoc 跑 transient unit</li>
<li>Portable services：把 service + image 一起搬</li>
<li>systemd-nspawn 容器（systemd 自家輕量容器）</li>
</ul>
<h3 id="跟-container-整合">跟 container 整合</h3>
<p>子議題：</p>
<ul>
<li>跑 podman container 在 systemd（quadlet / generators）</li>
<li>Docker daemon 由 systemd 管</li>
<li>K8s kubelet 由 systemd 管（cluster node）</li>
<li>對應 single-node container management</li>
</ul>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<h3 id="service-start-failure">Service start failure</h3>
<p>操作原則：先 <code>systemctl status</code>、再 <code>journalctl -u</code> 看 log。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">systemctl status myapp                <span class="c1"># 看 Active state + Main PID + 最近 log</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">journalctl -u myapp --since<span class="o">=</span>-5m       <span class="c1"># 最近 5 分鐘的完整 log</span></span></span></code></pre></div><h3 id="restart-loop">Restart loop</h3>
<p>操作原則：Restart 配置不當 + StartLimit 觸發。判讀：<code>systemctl status</code> 看 restart count + RateLimit。</p>
<h3 id="journald-disk-full">journald disk full</h3>
<p>操作原則：journal storage 超 SystemMaxUse 設定。判讀：<code>journalctl --disk-usage</code>、<code>/etc/systemd/journald.conf</code> 設限。</p>
<h3 id="cgroup-oom">cgroup OOM</h3>
<p>操作原則：MemoryMax 超過、系統 OOM kill。判讀：<code>journalctl -k</code> 看 kernel oom 訊息。</p>
<h3 id="dependency-不對">Dependency 不對</h3>
<p>操作原則：unit 依賴 network / db 但 After= 沒設。判讀：<code>systemctl list-dependencies myapp</code>。</p>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>多實例 cluster</td>
          <td><a href="/blog/backend/05-deployment-platform/vendors/kubernetes/" data-link-title="Kubernetes" data-link-desc="Container orchestration 主流、GKE / EKS / AKS / 自管">Kubernetes</a></td>
      </tr>
      <tr>
          <td>Container workflow 為主</td>
          <td><a href="/blog/backend/05-deployment-platform/vendors/docker/" data-link-title="Docker" data-link-desc="Container runtime / image 標準">Docker</a> / Podman</td>
      </tr>
      <tr>
          <td>Process supervisor（非 init）</td>
          <td>supervisord / runit</td>
      </tr>
      <tr>
          <td>Cron-only 場景</td>
          <td>純 cron / systemd timer</td>
      </tr>
      <tr>
          <td>Non-Linux（Windows / macOS）</td>
          <td>Windows Service / launchd</td>
      </tr>
      <tr>
          <td>邊緣 K8s</td>
          <td>K3s（systemd 上跑 K3s）</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>完整 unit file directive reference</li>
<li>systemd internals（dbus / pid 1）</li>
<li>各 distro systemd 版本差異</li>
<li>systemd-resolved / systemd-networkd 等其他 component</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<h3 id="跨-vendor-對照">跨 vendor 對照</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>對 systemd 的對應</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/05-deployment-platform/cases/failure-platform-cutover-without-drain/" data-link-title="5.C9 反例：平台切流未先 Draining" data-link-desc="切流時忽略連線清退造成請求錯誤與重試風暴。">5.C9 cutover without drain</a></td>
          <td>systemd 服務切換要靠 ExecStop / TimeoutStopSec / SIGTERM trap 等價 drain</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/05-deployment-platform/cases/contrast-platform-migration-by-scale/" data-link-title="5.C10 對照：規模差異下的平台遷移" data-link-desc="平台遷移策略在小中大型組織下的差異。">5.C10 規模對照</a></td>
          <td>小規模 VM 服務首選 systemd、跨規模升階到 K8s 時要保留 unit-level 回退腳本</td>
      </tr>
  </tbody>
</table>
<p><strong>待補 systemd 案例</strong>：大規模 fleet（HashiCorp Nomad 跟 systemd 整合）、IoT / edge appliance 案例、systemd portable services 落地案例。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游概念：<a href="/blog/backend/05-deployment-platform/container-runtime/" data-link-title="5.1 container 與 runtime" data-link-desc="整理 image、resource limit 與啟動行為">5.1 container runtime</a></li>
<li>平行 vendor：<a href="/blog/backend/05-deployment-platform/vendors/kubernetes/" data-link-title="Kubernetes" data-link-desc="Container orchestration 主流、GKE / EKS / AKS / 自管">Kubernetes</a>、<a href="/blog/backend/05-deployment-platform/vendors/docker/" data-link-title="Docker" data-link-desc="Container runtime / image 標準">Docker</a></li>
<li>下游能力：<a href="/blog/backend/06-reliability/" data-link-title="模組六：可靠性驗證流程" data-link-desc="用 SRE 領域詞彙建問題節點、以服務級案例庫累積驗證脈絡，先建概念與案例庫再進實作交接">06 reliability</a>（graceful shutdown）、<a href="/blog/backend/04-observability/" data-link-title="模組四：可觀測性平台" data-link-desc="整理 log、metric、trace、dashboard 與 alert 的後端操作實務">4 observability</a>（journald）</li>
</ul>
]]></content:encoded></item><item><title>AWS IAM Identity Center</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-iam-identity-center/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-iam-identity-center/</guid><description>&lt;p>AWS IAM Identity Center 是 AWS 原生的 workforce SSO 控制面、前身為 AWS SSO（2022 改名）。它承擔三個責任：人類身份進 AWS 多帳號的 &lt;em>統一入口&lt;/em>（Access Portal）、把使用者映射到各帳號 IAM role 的 &lt;em>Permission Set&lt;/em> 模板、以及對少量已整合 SAML app 的 SSO gateway。它不是 AWS IAM 的替代品、是疊在 AWS IAM 之上的 &lt;em>人類入口層&lt;/em>。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>IAM Identity Center 是 &lt;em>人類身份進 AWS 的 portal&lt;/em>、不是 cloud resource permission engine。它跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM&lt;/a> 的分工是兩層：Identity Center 管「人是誰、能登入哪些 account」、AWS IAM 管「進到 account 後對 resource 能做什麼」。實際機制是 Identity Center 透過 Permission Set 在每個目標 account 建一個 &lt;code>AWSReservedSSO_*&lt;/code> 命名的 IAM role、使用者 assume 該 role 拿短期 STS token。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta&lt;/a> 相比、Identity Center 的核心優勢是 &lt;em>跟 AWS Organizations + Control Tower 原生整合&lt;/em>、Permission Set 可以一次發佈到數百個 account、不必每個 account 各接 SAML。代價是 SaaS app integration 量級遠少於 Okta（Okta 7000+ 預建、Identity Center 僅中等規模）、跨雲 federation（GCP / Azure）也不在原生範圍。&lt;/p>
&lt;p>許多大型組織採三層架構：Okta 是 HRIS 下游的 identity source of truth、SCIM push 進 Identity Center、Identity Center 再 map 到 AWS IAM Permission Set。Okta 管「人是誰」、Identity Center 管「AWS portal 入口」、AWS IAM 管「resource 能做什麼」。中小組織可以省略 Okta、直接用 Identity Center 內建 user store、但就失去跨 SaaS 統一 SSO。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本頁、讀者能判斷：&lt;/p>
&lt;ol>
&lt;li>Identity Center 在 &lt;em>人類身份 / AWS portal / resource permission&lt;/em> 三層裡的位置、何時該交回 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM&lt;/a> 或上游 IdP&lt;/li>
&lt;li>Identity Source 選擇（內建 / Active Directory / 外部 SAML）對 lifecycle 與 lock-in 的長期影響&lt;/li>
&lt;li>Permission Set / Account Assignment / Access Portal 三個核心概念的稽核重點&lt;/li>
&lt;li>何時 Identity Center 夠用、何時要疊 Okta 在前、何時 Identity Center 反而是錯選擇&lt;/li>
&lt;/ol>
&lt;h2 id="最短判讀路徑">最短判讀路徑&lt;/h2>
&lt;p>判斷 Identity Center 配置是否健康、最少看四件事：&lt;/p></description><content:encoded><![CDATA[<p>AWS IAM Identity Center 是 AWS 原生的 workforce SSO 控制面、前身為 AWS SSO（2022 改名）。它承擔三個責任：人類身份進 AWS 多帳號的 <em>統一入口</em>（Access Portal）、把使用者映射到各帳號 IAM role 的 <em>Permission Set</em> 模板、以及對少量已整合 SAML app 的 SSO gateway。它不是 AWS IAM 的替代品、是疊在 AWS IAM 之上的 <em>人類入口層</em>。</p>
<h2 id="服務定位">服務定位</h2>
<p>IAM Identity Center 是 <em>人類身份進 AWS 的 portal</em>、不是 cloud resource permission engine。它跟 <a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM</a> 的分工是兩層：Identity Center 管「人是誰、能登入哪些 account」、AWS IAM 管「進到 account 後對 resource 能做什麼」。實際機制是 Identity Center 透過 Permission Set 在每個目標 account 建一個 <code>AWSReservedSSO_*</code> 命名的 IAM role、使用者 assume 該 role 拿短期 STS token。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a> 相比、Identity Center 的核心優勢是 <em>跟 AWS Organizations + Control Tower 原生整合</em>、Permission Set 可以一次發佈到數百個 account、不必每個 account 各接 SAML。代價是 SaaS app integration 量級遠少於 Okta（Okta 7000+ 預建、Identity Center 僅中等規模）、跨雲 federation（GCP / Azure）也不在原生範圍。</p>
<p>許多大型組織採三層架構：Okta 是 HRIS 下游的 identity source of truth、SCIM push 進 Identity Center、Identity Center 再 map 到 AWS IAM Permission Set。Okta 管「人是誰」、Identity Center 管「AWS portal 入口」、AWS IAM 管「resource 能做什麼」。中小組織可以省略 Okta、直接用 Identity Center 內建 user store、但就失去跨 SaaS 統一 SSO。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>Identity Center 在 <em>人類身份 / AWS portal / resource permission</em> 三層裡的位置、何時該交回 <a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM</a> 或上游 IdP</li>
<li>Identity Source 選擇（內建 / Active Directory / 外部 SAML）對 lifecycle 與 lock-in 的長期影響</li>
<li>Permission Set / Account Assignment / Access Portal 三個核心概念的稽核重點</li>
<li>何時 Identity Center 夠用、何時要疊 Okta 在前、何時 Identity Center 反而是錯選擇</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Identity Center 配置是否健康、最少看四件事：</p>
<ul>
<li><strong>誰能 assume 哪個 role</strong>：Permission Set 跟 Account Assignment 是否走最小權限、<code>AdministratorAccess</code> 範圍 Permission Set 是否限定 break-glass、是否強制 <a href="/blog/backend/knowledge-cards/authentication/" data-link-title="Authentication" data-link-desc="說明系統如何確認呼叫者身份">phishing-resistant 認證</a> 才能 assume 高權限</li>
<li><strong>Permission Set 邊界</strong>：每個 Permission Set 的 session duration（預設 1 hour、可調 12 hour）、inline policy vs Customer Managed Policy reference、是否用 ABAC tag 收斂跨 account 散佈</li>
<li><strong>External IdP federation 狀態</strong>：Identity Source 是內建 / AD / 外部 SAML、若走外部 IdP SCIM push 是否監控 sync 失敗、signing certificate 是否在 rotation 排程內</li>
<li><strong>CloudTrail 是否完整</strong>：Identity Center 事件分布在 management account 跟 member account、是否有 organization trail 收齊、admin 變更 / Permission Set 變更 / failed assume 是否 alert</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">Audit Log</a> 與 <a href="/blog/backend/knowledge-cards/authorization/" data-link-title="Authorization" data-link-desc="說明授權如何判斷誰能對哪些資源執行哪些操作">Authorization</a> 邊界的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>Identity Source 是根信任</strong>：Identity Center 支援三種 user/group 來源 — 內建 store、AWS Managed AD / on-prem AD via AD Connector、外部 SAML IdP（Okta / Entra ID 等、SCIM 推進來）。選了之後 user lifecycle 從哪來就鎖死、換 Identity Source 是大工程（要重建所有 Permission Set assignment、舊 user GUID 不通用）。早期決定錯比 Permission Set 設錯難救。</p>
<p><strong>Permission Set 是 cross-account role template</strong>：定義一次、apply 到多 account、實際在每個 account 部署成一個 AWS-Reserved 命名的 IAM role。Permission Set 本身不是 role、是 <em>role 的部署模板</em> — 改 Permission Set 會 push 到所有 account 上對應的 role。Customer Managed Policy reference 比 inline policy 好維護、但要先確保每個 target account 都有同名 policy、否則 assignment 會失敗。</p>
<p><strong>Account Assignment</strong>：把 user/group 綁到 Permission Set + 特定 account 的三元組。這層用 group 而不是個別 user、跟著 Identity Source 的 group 變動自動同步。臨時權限（離職員工延長、incident 應變）走 access request workflow 或 IAM Access Analyzer + Just-in-Time、不要永久 assignment。</p>
<p><strong>Access Portal URL 是 phishing 目標</strong>：custom URL（<code>https://&lt;alias&gt;.awsapps.com/start</code>）設定後變成員工每天用的入口、phishing 攻擊會 mimic。要強制 phishing-resistant MFA（WebAuthn / passkey）、純 push MFA 抗不過 fatigue。CLI 走 <code>aws sso login</code> 自帶 browser-based flow、不要叫員工複製貼 access key。</p>
<p><strong>Application assignment</strong>：Identity Center 也能管 SAML app 的 SSO assignment、但 integration 數量遠少於 Okta。大量 SaaS app 的場景應該疊 Okta 在前、Identity Center 只管 AWS portal。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>IAM Identity Center</th>
          <th>Okta + AWS IAM</th>
          <th>直接用 AWS IAM Users（不推薦）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>控制面責任</td>
          <td>AWS 託管、限 AWS 帳號 + 中等 SAML app</td>
          <td>Okta 管人類身份、AWS IAM 管 resource、兩層分工</td>
          <td>每個 account 各自管 user、無跨帳號統一</td>
      </tr>
      <tr>
          <td>多帳號統一入口</td>
          <td>原生、Permission Set 一次發到全 Org</td>
          <td>透過 SAML federation 到 IAM role</td>
          <td>不存在 — 每個 account 各自 IAM Users</td>
      </tr>
      <tr>
          <td>SaaS app 範圍</td>
          <td>中等規模 integration</td>
          <td>7000+ 預建 integration</td>
          <td>無</td>
      </tr>
      <tr>
          <td>Lifecycle</td>
          <td>內建 / AD / 外部 SCIM 進來</td>
          <td>Okta 走 HRIS SCIM 同步、Identity Center 接 Okta SCIM</td>
          <td>手動管理、容易 stale</td>
      </tr>
      <tr>
          <td>退場成本</td>
          <td>中 — AWS 內部換</td>
          <td>高 — Okta + Identity Center 都要拆</td>
          <td>高 — 大量 IAM Users 散佈在 N 個 account</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>AWS-heavy、員工數中等、SaaS app 少</td>
          <td>多雲 + 大量 SaaS + AWS 帳號數十個以上</td>
          <td>不存在合理場景（small lab 例外）</td>
      </tr>
  </tbody>
</table>
<p>選 Identity Center 的核心訴求：<em>AWS 是主要工作環境、員工 SaaS app 用量低、要統一多帳號入口而不要再付 Okta 訂閱</em>。員工大量用 SaaS 的場景應該疊 Okta 在前。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>External IdP federation（Okta / Entra ID SCIM 進來）</strong>：Identity Center 接外部 IdP 是 <em>push model</em> — IdP 主動 SCIM push、Identity Center 不 pull。push provisioning 失敗會 silent（IdP 端有 log、Identity Center 端只看到 user 沒出現）、要在 IdP 端設 sync failure alert。SAML signing certificate rotation 兩邊都要排程、過期會整個 federation 斷。</p>
<p><strong>Multi-account Permission Set 設計</strong>：避免每個 environment / team 各自一份 Permission Set — 用 ABAC（tag-based access control）把「<code>Environment=Prod</code> + <code>Team=Payments</code>」的條件寫進一個 Permission Set 的 policy、tag 跟著 user attribute 跑。Permission Set 數量爆炸是 Identity Center 老化最常見訊號。</p>
<p><strong>Customer Managed Policy reference</strong>：Permission Set 可以 reference target account 裡的 customer managed policy（同名同 path）、policy 本身在每個 account 獨立維護。比 inline policy 適合大規模、但要靠 CI / Terraform 確保 policy 在所有 target account 同步存在、否則 assignment 失敗。</p>
<p><strong>Session duration 是攻擊面</strong>：預設 1 hour、可調到 12 hour。長 session 對 dev 體驗友善、但不利於 <a href="/blog/backend/07-security-data-protection/cases/failure-credential-rotation-without-scope/" data-link-title="7.C9 反例：憑證輪替未分 Scope" data-link-desc="憑證輪替若未分域分批，容易造成跨系統連鎖中斷。">credential rotation</a> — 高權限 Permission Set（<code>AdministratorAccess</code>、production write）應該短 session（1-2 hour）、低風險 read-only 可放 8-12 hour。</p>
<p><strong>IAM Identity Center API 不該當 workforce IdP 用</strong>：API 是給 admin 管 assignment 用、不是給 app 拿 user token。要 workforce app SSO 走 SAML / OIDC federation、不要叫 app 打 Identity Center API 查 user。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Permission Set 數量爆炸</strong>：每個 team / environment 各一份、上百個 Permission Set 沒人敢動 — 改用 ABAC + user attribute 把條件寫進 policy、收斂到十位數</li>
<li><strong>Identity Source 選錯難換</strong>：早期選內建 store、後來公司導入 Okta 要換成外部 SAML — 整個 user GUID 重新映射、Permission Set assignment 重綁、評估比建新 tenant 還久</li>
<li><strong>External SCIM sync 失敗 silent</strong>：Okta 端 push 失敗、Identity Center 沒人 — 要在上游 IdP 設 SCIM provisioning failure alert、不要等使用者反映「我登不進去」</li>
<li><strong>Access Portal URL 被 phishing</strong>：custom URL 員工記憶、phishing 站 mimic、無 phishing-resistant MFA 擋不住 — 強制 WebAuthn / passkey、員工教育只認 bookmark / SSO launcher</li>
<li><strong>CloudTrail 不完整</strong>：只開 management account trail、member account 的 role assumption 看不到 — 開 organization trail 收齊、特別 alert Permission Set 變更與失敗 assume</li>
<li><strong>Break-glass 缺席</strong>：Identity Center 控制面故障時 console 進不去 — 保留每個 account 的 root credential（離線存）跟少數 break-glass IAM User（hardware MFA、與 Identity Center 獨立 audit）、季度驗證</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>大量 SaaS app 統一 SSO</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta vendor</a>（疊在 Identity Center 前）</td>
      </tr>
      <tr>
          <td>Customer / B2C identity</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/auth0/" data-link-title="Auth0" data-link-desc="B2C / B2B Customer Identity Provider、Universal Login、Action / Rule hook、屬 Okta 旗下 Customer Identity Cloud">Auth0 vendor</a></td>
      </tr>
      <tr>
          <td>自管 / 不接受 cloud-managed IdP</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/keycloak/" data-link-title="Keycloak" data-link-desc="Open source self-hosted Identity Provider、Red Hat 主導、Realm-based multi-tenancy、適合資料主權與自訂 flow 需求">Keycloak vendor</a></td>
      </tr>
      <tr>
          <td>AWS resource permission（policy / role / STS）</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM vendor</a></td>
      </tr>
      <tr>
          <td>跨雲 federation（GCP / Azure workforce）</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google Cloud IAM</a> / <a href="/blog/backend/07-security-data-protection/vendors/azure-rbac/" data-link-title="Azure RBAC &#43; Entra ID" data-link-desc="Azure 雙層身份/權限體系、Entra ID（IdP）&#43; Azure RBAC（resource permission）、Conditional Access、PIM、Managed Identity">Azure RBAC</a></td>
      </tr>
      <tr>
          <td>Secret / API key 治理</td>
          <td><a href="/blog/backend/07-security-data-protection/secrets-and-machine-credential-governance/" data-link-title="7.6 秘密管理與機器憑證治理" data-link-desc="以問題驅動方式整理 secret、token、key 與機器身份治理">7.6 秘密管理與機器憑證治理</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>AWS IAM 的 policy / role / STS 機制細節（屬 AWS IAM vendor 頁）</li>
<li>Permission Set 的 JSON policy 撰寫教學</li>
<li>AWS Organizations / Control Tower 的完整架構</li>
<li>各 SaaS app SAML 接線教學</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 IAM Identity Center 的關係</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/cases/azure-ad-identity-control-plane-2021/" data-link-title="7.C3 Azure AD：2021 Identity Control-plane 事件" data-link-desc="身分控制面事件如何影響多服務信任鏈與回復優先序。">Azure AD Identity Control Plane 2021</a></td>
          <td>Identity Center 控制面故障會擋住 AWS console portal、降級路徑必須事先設計（emergency root credential、break-glass IAM User）</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/cases/failure-credential-rotation-without-scope/" data-link-title="7.C9 反例：憑證輪替未分 Scope" data-link-desc="憑證輪替若未分域分批，容易造成跨系統連鎖中斷。">Failure: Credential Rotation Without Scope</a></td>
          <td>Permission Set session duration 跟 external IdP signing key rotation 是不同域、要分開排程、不能混為一談</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/cases/okta-support-system-incident-2023/" data-link-title="7.C5 Okta：2023 Support System 事件" data-link-desc="支援系統憑證風險如何擴散到客戶租戶的案例。">Okta Support System Incident 2023</a></td>
          <td>Okta 作為 Identity Center 的 external IdP 時、上游事件會傳導下來、Identity Center 端要看 SCIM sync 異常與 federation token reuse</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/cloudflare-2023-okta-token-follow-through/" data-link-title="7.R7.1.6 Cloudflare 2023：供應商事件後的身分收斂" data-link-desc="同一條供應商事件鏈，如何在客戶端變成 session 與 token 的收斂壓力">Cloudflare 2023 Okta Token Follow-Through</a></td>
          <td>上游 IdP 出事後、Identity Center 端的 active session 是否要強制 reauth、不能等供應商公告</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/identity-access-boundary/" data-link-title="7.2 身分與授權邊界" data-link-desc="以問題驅動方式整理身分、授權、會話與供應商身分鏈">7.2 身分與授權邊界</a>、<a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">7.13 偵測覆蓋率與訊號治理</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta vendor</a>（外部 IdP 疊在前）、<a href="/blog/backend/07-security-data-protection/vendors/auth0/" data-link-title="Auth0" data-link-desc="B2C / B2B Customer Identity Provider、Universal Login、Action / Rule hook、屬 Okta 旗下 Customer Identity Cloud">Auth0 vendor</a>、<a href="/blog/backend/07-security-data-protection/vendors/keycloak/" data-link-title="Keycloak" data-link-desc="Open source self-hosted Identity Provider、Red Hat 主導、Realm-based multi-tenancy、適合資料主權與自訂 flow 需求">Keycloak vendor</a></li>
<li>下游：<a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM vendor</a>（Permission Set 落地的 resource permission 層）、<a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google Cloud IAM</a> / <a href="/blog/backend/07-security-data-protection/vendors/azure-rbac/" data-link-title="Azure RBAC &#43; Entra ID" data-link-desc="Azure 雙層身份/權限體系、Entra ID（IdP）&#43; Azure RBAC（resource permission）、Conditional Access、PIM、Managed Identity">Azure RBAC</a>（多雲對照）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（Identity Center 事件如何 routing 進 IR 流程）</li>
<li>官方：<a href="https://docs.aws.amazon.com/singlesignon/">AWS IAM Identity Center Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>AWS KMS</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-kms/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-kms/</guid><description>&lt;p>AWS KMS 是 AWS 原生的 key management service、解決 &lt;em>對稱 / 非對稱金鑰生命週期管理&lt;/em> 與 &lt;em>envelope encryption pattern&lt;/em>：service 內部保管 master key（KMS Key）、應用層用 &lt;code>GenerateDataKey&lt;/code> 取得短暫的 data key 對實際資料加密、master key 完全不離 KMS 服務邊界。整合面跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-secrets-manager/" data-link-title="AWS Secrets Manager" data-link-desc="AWS 原生 secret store &amp;#43; 內建 RDS / Redshift rotation Lambda、Resource Policy 跨帳號共享、KMS 加密">AWS Secrets Manager&lt;/a> / S3 / EBS / RDS 都串好、是 AWS 上幾乎所有靜態資料加密的後端。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>AWS KMS 的核心定位是 &lt;em>AWS-only 的 multi-tenant managed key management&lt;/em>，FIPS 140-2 Level 3 認證、跨服務 envelope encryption 的共同地基。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/cloudhsm/" data-link-title="AWS CloudHSM" data-link-desc="Single-tenant dedicated HSM（FIPS 140-2 Level 3）、AWS 不持 Crypto User credential、合規 &amp;#43; 資料主權場景的 key custody">CloudHSM&lt;/a> 比、KMS 是 &lt;em>managed + shared HSM 池&lt;/em>、CloudHSM 是 &lt;em>single-tenant dedicated HSM&lt;/em>；需要更高隔離 / 自管 cluster / FIPS Level 3 single-tenant 時走 CloudHSM、或用 KMS Custom Key Store 把 KMS 後端指向自己的 CloudHSM。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/google-cloud-kms/" data-link-title="Google Cloud KMS" data-link-desc="GCP 原生 key management service、KeyRing / CryptoKey Version 設計、CMEK 整合 &amp;#43; Cloud HSM &amp;#43; External Key Manager">Google Cloud KMS&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/azure-key-vault/" data-link-title="Azure Key Vault" data-link-desc="Azure 三合一 service（Secret &amp;#43; Key &amp;#43; Certificate）、整合 Managed Identity &amp;#43; Entra ID RBAC、Premium tier 走 HSM">Azure Key Vault&lt;/a> 比、設計概念相近、但 KMS 把 secret store 切出去（&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-secrets-manager/" data-link-title="AWS Secrets Manager" data-link-desc="AWS 原生 secret store &amp;#43; 內建 RDS / Redshift rotation Lambda、Resource Policy 跨帳號共享、KMS 加密">Secrets Manager&lt;/a>）、Key Vault 則把兩者合一。&lt;/p></description><content:encoded><![CDATA[<p>AWS KMS 是 AWS 原生的 key management service、解決 <em>對稱 / 非對稱金鑰生命週期管理</em> 與 <em>envelope encryption pattern</em>：service 內部保管 master key（KMS Key）、應用層用 <code>GenerateDataKey</code> 取得短暫的 data key 對實際資料加密、master key 完全不離 KMS 服務邊界。整合面跟 <a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM</a> / <a href="/blog/backend/07-security-data-protection/vendors/aws-secrets-manager/" data-link-title="AWS Secrets Manager" data-link-desc="AWS 原生 secret store &#43; 內建 RDS / Redshift rotation Lambda、Resource Policy 跨帳號共享、KMS 加密">AWS Secrets Manager</a> / S3 / EBS / RDS 都串好、是 AWS 上幾乎所有靜態資料加密的後端。</p>
<h2 id="服務定位">服務定位</h2>
<p>AWS KMS 的核心定位是 <em>AWS-only 的 multi-tenant managed key management</em>，FIPS 140-2 Level 3 認證、跨服務 envelope encryption 的共同地基。跟 <a href="/blog/backend/07-security-data-protection/vendors/cloudhsm/" data-link-title="AWS CloudHSM" data-link-desc="Single-tenant dedicated HSM（FIPS 140-2 Level 3）、AWS 不持 Crypto User credential、合規 &#43; 資料主權場景的 key custody">CloudHSM</a> 比、KMS 是 <em>managed + shared HSM 池</em>、CloudHSM 是 <em>single-tenant dedicated HSM</em>；需要更高隔離 / 自管 cluster / FIPS Level 3 single-tenant 時走 CloudHSM、或用 KMS Custom Key Store 把 KMS 後端指向自己的 CloudHSM。跟 <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-kms/" data-link-title="Google Cloud KMS" data-link-desc="GCP 原生 key management service、KeyRing / CryptoKey Version 設計、CMEK 整合 &#43; Cloud HSM &#43; External Key Manager">Google Cloud KMS</a> / <a href="/blog/backend/07-security-data-protection/vendors/azure-key-vault/" data-link-title="Azure Key Vault" data-link-desc="Azure 三合一 service（Secret &#43; Key &#43; Certificate）、整合 Managed Identity &#43; Entra ID RBAC、Premium tier 走 HSM">Azure Key Vault</a> 比、設計概念相近、但 KMS 把 secret store 切出去（<a href="/blog/backend/07-security-data-protection/vendors/aws-secrets-manager/" data-link-title="AWS Secrets Manager" data-link-desc="AWS 原生 secret store &#43; 內建 RDS / Redshift rotation Lambda、Resource Policy 跨帳號共享、KMS 加密">Secrets Manager</a>）、Key Vault 則把兩者合一。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault transit engine</a> 比、行為相似（key 不離 service、app 拿 ciphertext）、但治理面完全不同：KMS 綁 AWS 控制面、IAM + Key Policy 雙層授權、CloudTrail 是稽核入口；Vault transit 是跨雲統一介面、token + policy 為主、需要自管 cluster。AWS-heavy 組織首選 KMS、跨雲組織才會把 KMS 當下游、上游用 Vault transit 抽象。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>哪些資料 / 場景該用 Customer Managed KMS Key、哪些 AWS Managed Key 已經夠用、什麼時候直接走 CloudHSM</li>
<li>Key Policy + IAM + Grant 三層授權的分工、production 必開的 CloudTrail Data event 與 monitor 範圍</li>
<li>Multi-Region Key、Custom Key Store、External Key Store、BYOK 等進階形態的取捨</li>
<li>KMS 出事（IAM 過寬、Key Policy 把自己鎖死、Schedule Deletion 誤觸發）時的判讀路徑跟回退選項</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷一個 AWS KMS deployment 是否健康、最少看四件事：</p>
<ul>
<li><strong>Key Policy 設計</strong>：是否含 <code>root</code> principal（不然 key 變孤兒）、是否走 least privilege（不是 <code>kms:*</code> 給整個 account）、admin / user / monitor 三類 principal 是否分開、policy 變更是否走 PR review</li>
<li><strong>Grant 治理</strong>：哪些 service-to-service 短期授權走 Grant（rotation Lambda / RDS / EBS）、Grant TTL 是否設、廢棄 grant 是否定期 <code>RetireGrant</code></li>
<li><strong>Multi-Region 與 rotation 策略</strong>：是否啟用 annual automatic rotation（適用 symmetric encryption key）、Multi-Region Key 的 replica 是否跟 DR plan 對齊、asymmetric / signing key 的 manual rotation 流程是否有 runbook</li>
<li><strong>CloudTrail Data Event 必開</strong>：management event 預設記、但 <code>Encrypt</code> / <code>Decrypt</code> / <code>GenerateDataKey</code> 是 data event、預設不記 — 沒這層 forensic 沒著力點、Storm-0558 對照下完全無法回答「誰用哪把 key 簽了什麼 token」</li>
</ul>
<p>四件事任一缺失、就回到 <a href="/blog/backend/07-security-data-protection/secrets-and-machine-credential-governance/" data-link-title="7.6 秘密管理與機器憑證治理" data-link-desc="以問題驅動方式整理 secret、token、key 與機器身份治理">7.6 秘密管理與機器憑證治理</a> 跟 <a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">Audit Log</a> 的補丁清單。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>Key Type 選擇</strong>：symmetric encryption key（AES-256-GCM、最常用、S3 / EBS / RDS / Secrets Manager 都走這個）；asymmetric key pair（RSA / ECC、用於 sign / verify 或 encrypt / decrypt、JWT 簽署、CodeSign、文件簽章）；HMAC key（generate / verify MAC、API request signing）。對應 <a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/microsoft-storm-0558-2023-signing-key-chain/" data-link-title="7.R7.1.5 Microsoft Storm-0558 2023：簽章金鑰鏈與郵件存取" data-link-desc="從簽章金鑰保護失效到雲端郵件存取，拆解身分信任鏈的關鍵控制點">Storm-0558 signing key chain</a> — 自己 host signing key 出事的核心教訓是 <em>key 不該離 HSM service</em>、所以 JWT signing 用 asymmetric KMS key 是 baseline 設計、private key 永遠不離 KMS。</p>
<p><strong>Key Origin（key material 來源）</strong>：<code>AWS_KMS</code>（KMS 內部生成、預設）；<code>EXTERNAL</code>（BYOK、組織自己生成 key material、import 進 KMS、可以隨時 reimport 或刪除）；<code>AWS_CLOUDHSM</code>（Custom Key Store、key material 存在自己的 CloudHSM cluster）；<code>EXTERNAL_KEY_STORE</code>（XKS、AWS 外的 HSM、控制面在 AWS、key material 在 on-prem）。多數場景用 <code>AWS_KMS</code> 就夠、合規 / 主權需求才走 EXTERNAL / Custom Key Store。</p>
<p><strong>Key Policy 跟 IAM 的雙層</strong>：KMS 跟其他 AWS service 最大差異是 <em>Key Policy 是主要授權機制</em>、IAM policy 單獨不夠。Key Policy 必含 <code>arn:aws:iam::ACCOUNT_ID:root</code> 給 root principal（不是 root user、是讓 IAM 能參與授權的開關）— 沒這條 key 變孤兒、即使 IAM 開了 admin 也救不回來。production 通常分三類 statement：admin（Create / Delete / Schedule、走 break-glass）、user（Encrypt / Decrypt / GenerateDataKey、給 app）、monitor（Describe / List、給 SRE）。</p>
<p><strong>Grant 是程式化短期授權</strong>：service-to-service 整合（<a href="/blog/backend/07-security-data-protection/vendors/aws-secrets-manager/" data-link-title="AWS Secrets Manager" data-link-desc="AWS 原生 secret store &#43; 內建 RDS / Redshift rotation Lambda、Resource Policy 跨帳號共享、KMS 加密">Secrets Manager</a> rotation Lambda、RDS 自動加密、EBS volume attach）通常走 Grant 而不是改 Key Policy — 每個 grant 有自己的 grant token、可以帶 TTL、可以 <code>RetireGrant</code> / <code>RevokeGrant</code> 收回、不跟 key policy 永久綁定。沒治理時 grant 累積上千個 / 沒人 retire 是常見問題、跟 <a href="/blog/backend/07-security-data-protection/cases/failure-credential-rotation-without-scope/" data-link-title="7.C9 反例：憑證輪替未分 Scope" data-link-desc="憑證輪替若未分域分批，容易造成跨系統連鎖中斷。">Failure: Credential Rotation Without Scope</a> 同類 — 沒 scope map 等於沒治理。</p>
<p><strong>Alias 與 Key ID 的解耦</strong>：alias（<code>alias/my-app-prod-key</code>）是 <em>指向 key 的可變指標</em>、key ID / ARN 是 <em>不可變識別</em>。production code 應該用 alias、要換 key 時只需要重綁 alias、不用改 deployment。Cross-account 跨帳號使用必須用 ARN（alias 不跨帳號）。</p>
<p><strong>Key Rotation 的真實語義</strong>：annual automatic rotation（symmetric encryption key 才支援）換的是 <em>KMS 內部的 backing key material</em>、key ARN / Alias / Key ID 都不變、app 完全不需要動。<strong>舊資料仍用舊 backing key 解密、KMS 自動處理</strong>、不是「資料全部重新加密」— 這是常見誤解。asymmetric / HMAC key 不支援 automatic rotation、必須 manual 建新 key + alias 切換 + app 端雙讀容忍窗口（跟 JWT signing key rotation 同套路）。</p>
<p><strong>Multi-Region Key</strong>：跨 region replicate 的 KMS key 共用 <em>key material</em> 跟 <em>Key ID</em>（後綴帶 <code>mrk-</code>）、不是建立新 key — 跨 region 加密的 ciphertext 在另一 region 可以直接 decrypt、不用 cross-region API call。適合 multi-region active-active app + DR scenario。代價是 <em>replica region 跟 primary region 的權限要分別治理</em>、Key Policy 不會自動同步。</p>
<p><strong>Encryption Context 是 <em>authenticated data</em></strong>：encrypt 時帶的 key-value pair（例：<code>{&quot;app&quot;: &quot;billing&quot;, &quot;tenant&quot;: &quot;acme&quot;}</code>）、decrypt 必須提供同一組 context — 否則失敗。用來防 <em>ciphertext 被 replay 到別的 context</em>（攻擊者拿到 billing 的 ciphertext 想當 payroll 的 ciphertext 用）、所有 context 都會進 CloudTrail、是 forensic 上的關鍵欄位。production 一律帶 context、單純加密不帶 context 等於少一層防護。</p>
<p><strong>Customer Managed vs AWS Managed vs AWS Owned</strong>：三層分權 — Customer Managed（CMK、自己控 Key Policy + 自選 rotation）、AWS Managed（<code>aws/secretsmanager</code>、<code>aws/s3</code>、AWS 管 Key Policy、看得到但改不了）、AWS Owned（完全看不見、AWS 自己用、無 CloudTrail）。production 高敏感資料應該用 Customer Managed、才能控 policy + 開 data event + 自選 rotation 週期。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>AWS KMS</th>
          <th>Google Cloud KMS</th>
          <th>Azure Key Vault</th>
          <th>AWS CloudHSM</th>
          <th>Vault transit engine</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>部署模型</td>
          <td>AWS managed multi-tenant、FIPS 140-2 Level 3</td>
          <td>GCP managed multi-tenant、FIPS 140-2 L3</td>
          <td>Azure managed、Standard / Premium tier</td>
          <td>AWS managed single-tenant HSM cluster</td>
          <td>自管 Vault cluster</td>
      </tr>
      <tr>
          <td>跨雲</td>
          <td>弱 — AWS-only</td>
          <td>弱 — GCP-only</td>
          <td>弱 — Azure-only</td>
          <td>弱 — AWS-only</td>
          <td>強 — 跨雲統一介面</td>
      </tr>
      <tr>
          <td>授權模型</td>
          <td>Key Policy（強制） + IAM + Grant 三層</td>
          <td>IAM 為主、Resource policy 輔</td>
          <td>Access policy + RBAC 雙模式</td>
          <td>CloudHSM user / role + Cluster IAM</td>
          <td>path-based policy + token</td>
      </tr>
      <tr>
          <td>Multi-Region</td>
          <td>Multi-Region Key（共用 key material）</td>
          <td>自動跨 region replication 較易</td>
          <td>Geo-replication 透過 Premium tier</td>
          <td>自管 cross-region replication</td>
          <td>Replication（Enterprise）</td>
      </tr>
      <tr>
          <td>Envelope encryption</td>
          <td>一級 pattern（<code>GenerateDataKey</code>）</td>
          <td>一級 pattern</td>
          <td>一級 pattern</td>
          <td>自己實作</td>
          <td>內建（transit engine）</td>
      </tr>
      <tr>
          <td>Asymmetric signing</td>
          <td>支援（RSA / ECC、JWT / CodeSign 直用）</td>
          <td>支援</td>
          <td>支援</td>
          <td>支援 + 完整 PKCS#11</td>
          <td>支援（部分）</td>
      </tr>
      <tr>
          <td>整合面</td>
          <td>全 AWS service 原生（S3 / EBS / RDS / Lambda）</td>
          <td>全 GCP service 原生</td>
          <td>全 Azure service 原生</td>
          <td>PKCS#11 / JCE / OpenSSL</td>
          <td>應用層 SDK</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>AWS-heavy + envelope encryption + JWT signing</td>
          <td>GCP-heavy</td>
          <td>Azure-heavy + 跟 AD 整合</td>
          <td>合規 / FIPS L3 single-tenant / 自管 HSM</td>
          <td>跨雲 + key 不離 service</td>
      </tr>
      <tr>
          <td>不適合場景</td>
          <td>跨雲統一 custody、需 FIPS L4、需自管 HSM cluster</td>
          <td>同左</td>
          <td>同左</td>
          <td>純 envelope encryption 用 KMS 即可</td>
          <td>AWS-only 簡單需求（KMS 更便宜）</td>
      </tr>
  </tbody>
</table>
<p>KMS 是 AWS 上的 <em>預設選擇</em>、CloudHSM 是合規 / 自管要求才上的 <em>昇級</em>、Vault transit 是跨雲統一介面、Google / Azure 對標品在各自雲一樣是預設選擇。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>KMS Custom Key Store + CloudHSM 整合</strong>：Custom Key Store 把 KMS 的 <em>控制面</em>（API、Key Policy、CloudTrail、IAM 整合）保留、但 <em>key material 存在自己的 CloudHSM cluster</em>。組織需要 FIPS 140-2 Level 3 single-tenant 但又不想放棄 KMS 的 service 整合（S3 SSE-KMS / EBS encryption）時用。代價是 CloudHSM cluster 的運維成本（cluster HA、user 管理、backup）。</p>
<p><strong>External Key Store (XKS)</strong>：更激進的形態 — key material 完全在 AWS 之外（on-prem HSM 或第三方 HSM）、AWS 透過 XKS proxy 呼叫外部 HSM 做 cryptographic operation。用於 <em>資料主權</em> 場景（金融 / 政府 / 跨境合規要求 key 不出組織邊界）、代價是 latency 跟 availability 完全綁外部 HSM、AWS service 整合面要算清楚。</p>
<p><strong>Multi-Region Replica Key 跟 DR</strong>：primary region 出事時 replica region 仍能 decrypt 既有 ciphertext、不需要 cross-region API call。但 <em>primary 跟 replica 是各自獨立的 Key Policy</em>、變更不會自動同步 — 跟 <a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">Audit Log</a> 治理一樣、replica region 也要納入 CloudTrail Data Event 覆蓋範圍。</p>
<p><strong>BYOK（Bring Your Own Key）</strong>：<code>Origin = EXTERNAL</code> 的 KMS Key、key material 由組織自己生成、用 wrapping key 加密後 import 進 KMS。優點是組織保有 <em>master copy</em>（KMS 出事時仍能 re-import 到別處）、缺點是 <em>automatic rotation 不支援</em>（必須手動 import 新 key material）、且必須自己處理 wrapping key 的生命週期。</p>
<p><strong>跟 <a href="/blog/backend/07-security-data-protection/vendors/aws-secrets-manager/" data-link-title="AWS Secrets Manager" data-link-desc="AWS 原生 secret store &#43; 內建 RDS / Redshift rotation Lambda、Resource Policy 跨帳號共享、KMS 加密">Secrets Manager</a> 的整合</strong>：Secrets Manager 的 secret 本身用 KMS key 加密（預設 AWS Managed <code>aws/secretsmanager</code>、production 應該指到 Customer Managed CMK）。rotation Lambda 透過 Grant 取得 Decrypt + Encrypt 能力、跟 Secrets Manager 一起構成 <em>static secret rotation 的證據鏈</em> — 跟 <a href="/blog/backend/07-security-data-protection/credential-rotation-scoped-evidence/" data-link-title="7.27 Credential Rotation with Scoped Evidence 實作示範" data-link-desc="以 webhook/API credential 輪替示範 scope map、證據欄位與回退窗口如何一起設計。">credential rotation scoped evidence</a> 對齊。</p>
<p><strong>Asymmetric signing 的 use cases</strong>：JWT signing（KMS <code>Sign</code> API 直接簽 JWT header.payload、private key 不離 KMS、跟 Storm-0558 的設計對照鮮明）；CodeSign / S3 object signing（artifact integrity）；mTLS client cert 的 private key（搭配 <a href="/blog/backend/07-security-data-protection/vendors/cert-manager/" data-link-title="cert-manager" data-link-desc="K8s 原生 certificate lifecycle automation、支援 Let&#39;s Encrypt / Vault PKI / Venafi 等多 issuer、auto-renewal &#43; Challenge solver">cert-manager</a> AWS issuer）。代價是 <em>latency</em>（每次 sign 一次 KMS API call、~10ms 級別、不適合超高 QPS）跟 <em>cost</em>（asymmetric operation 比 symmetric 貴 ~5x）。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Key Policy 沒有 <code>root</code> principal</strong>：Schedule 時忘了寫、key 立刻變孤兒、誰都不能用 — 只能透過 AWS Support 救（流程慢）；建立流程強制 template 含 root principal</li>
<li><strong>IAM admin 改不動 KMS key</strong>：Key Policy 沒授權 IAM 介入、即使 admin policy 有 <code>kms:*</code> 也擋掉 — 加 <code>Enable IAM User Permissions</code> statement 給 root principal、IAM 才能參與授權</li>
<li><strong>Schedule Key Deletion 誤觸發</strong>：min 7 天、max 30 天的等待期、期內可 cancel — production key 必含 alert（CloudWatch Alarm on <code>ScheduleKeyDeletion</code> event）+ 強制 4-eyes approval</li>
<li><strong>CloudTrail Data Event 沒開</strong>：事故後想查「誰 decrypt 了什麼」、發現只有 management event — production 必開 KMS data event、預估 cost（每 100k events ~$0.10）、敏感 key 一律開</li>
<li><strong>Encryption Context 不一致</strong>：encrypt 時帶 context、decrypt 時忘了帶（或帶錯）、<code>InvalidCiphertextException</code> — code review 強制 context schema、用 typed wrapper 避免人手帶錯</li>
<li><strong>Grant 累積 + 沒 retire</strong>：每個 KMS key 有 50,000 grant 上限、rotation Lambda 跑久了 grant 累積 — 定期 <code>ListGrants</code> + <code>RetireGrant</code> 廢棄的、IaC 治理 grant lifecycle</li>
<li><strong>Cross-region decrypt 失敗</strong>：以為 ciphertext 跨 region 通用、結果原本不是 Multi-Region Key — production 跨 region 場景一律建 Multi-Region Key、不要事後補</li>
<li><strong>CMK rotation 後舊 ciphertext 還能 decrypt</strong>：annual rotation 不會 re-encrypt 舊資料、KMS 自動用對應 backing key — 這是設計、不是 bug；真要全量 re-encrypt 要走 application-level migration</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>FIPS 140-2 Level 3 single-tenant HSM</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/cloudhsm/" data-link-title="AWS CloudHSM" data-link-desc="Single-tenant dedicated HSM（FIPS 140-2 Level 3）、AWS 不持 Crypto User credential、合規 &#43; 資料主權場景的 key custody">CloudHSM</a>、或 KMS Custom Key Store 橋接</td>
      </tr>
      <tr>
          <td>GCP-heavy 環境</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/google-cloud-kms/" data-link-title="Google Cloud KMS" data-link-desc="GCP 原生 key management service、KeyRing / CryptoKey Version 設計、CMEK 整合 &#43; Cloud HSM &#43; External Key Manager">Google Cloud KMS</a></td>
      </tr>
      <tr>
          <td>Azure-heavy + 跟 AD / Managed Identity 整合</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/azure-key-vault/" data-link-title="Azure Key Vault" data-link-desc="Azure 三合一 service（Secret &#43; Key &#43; Certificate）、整合 Managed Identity &#43; Entra ID RBAC、Premium tier 走 HSM">Azure Key Vault</a></td>
      </tr>
      <tr>
          <td>跨雲統一 key custody</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault transit engine</a></td>
      </tr>
      <tr>
          <td>Static secret + rotation orchestration</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/aws-secrets-manager/" data-link-title="AWS Secrets Manager" data-link-desc="AWS 原生 secret store &#43; 內建 RDS / Redshift rotation Lambda、Resource Policy 跨帳號共享、KMS 加密">AWS Secrets Manager</a>（後端是 KMS）</td>
      </tr>
      <tr>
          <td>K8s workload mTLS cert</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/cert-manager/" data-link-title="cert-manager" data-link-desc="K8s 原生 certificate lifecycle automation、支援 Let&#39;s Encrypt / Vault PKI / Venafi 等多 issuer、auto-renewal &#43; Challenge solver">cert-manager</a>（可用 KMS asymmetric key）</td>
      </tr>
      <tr>
          <td>Public TLS cert</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/aws-acm/" data-link-title="AWS ACM" data-link-desc="AWS-managed certificate provisioning、DNS validation &#43; auto-renewal、整合 ELB / CloudFront / API Gateway、Private CA 後端">AWS ACM</a> / <a href="/blog/backend/07-security-data-protection/vendors/letsencrypt/" data-link-title="Let&#39;s Encrypt" data-link-desc="免費 &#43; 自動化的公共 ACME CA、90 天 TTL 強制自動化、跨雲跨平台 public TLS cert 的事實基礎">Let&rsquo;s Encrypt</a></td>
      </tr>
      <tr>
          <td>數據主權 / on-prem HSM required</td>
          <td>KMS External Key Store (XKS) 或直接 <a href="/blog/backend/07-security-data-protection/vendors/cloudhsm/" data-link-title="AWS CloudHSM" data-link-desc="Single-tenant dedicated HSM（FIPS 140-2 Level 3）、AWS 不持 Crypto User credential、合規 &#43; 資料主權場景的 key custody">CloudHSM</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>KMS 完整 API reference 跟 SDK 範例</li>
<li>各 AWS service（S3 SSE-KMS、EBS encryption、RDS encryption、DynamoDB encryption）的詳盡設定步驟</li>
<li>跟 AWS Organizations / SCPs 的 cross-account KMS sharing 完整治理流程</li>
<li>CloudHSM cluster 的完整運維（高可用、user 管理、backup）— 看 <a href="/blog/backend/07-security-data-protection/vendors/cloudhsm/" data-link-title="AWS CloudHSM" data-link-desc="Single-tenant dedicated HSM（FIPS 140-2 Level 3）、AWS 不持 Crypto User credential、合規 &#43; 資料主權場景的 key custody">CloudHSM</a></li>
<li>各種 cryptographic algorithm 的數學原理跟選型細節</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>KMS 在 07 案例庫沒有直接 vendor-level 事件、以下案例採對照引用：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 KMS 的關係（對照）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/cases/microsoft-storm-0558-signing-key-2023/" data-link-title="7.C4 Microsoft：Storm-0558 簽章金鑰事件" data-link-desc="簽章金鑰事件如何回寫 identity 信任邊界與觀測證據鏈。">Microsoft Storm-0558 Signing Key 2023</a></td>
          <td>KMS 設計核心對照 — signing key 必須 HSM-bound + 不可導出、KMS 預設 key 完全不離 service；自己 host private key 是 Storm-0558 級事件的根因</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/microsoft-storm-0558-2023-signing-key-chain/" data-link-title="7.R7.1.5 Microsoft Storm-0558 2023：簽章金鑰鏈與郵件存取" data-link-desc="從簽章金鑰保護失效到雲端郵件存取，拆解身分信任鏈的關鍵控制點">Microsoft Storm-0558 Signing Key Chain (red-team)</a></td>
          <td>三件事必到位：asymmetric KMS Key 做 JWT signing（private key 永遠不離 KMS）、強制 rotation 流程、CloudTrail Data Event 紀錄「誰用 key 簽什麼 token」</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/cases/failure-credential-rotation-without-scope/" data-link-title="7.C9 反例：憑證輪替未分 Scope" data-link-desc="憑證輪替若未分域分批，容易造成跨系統連鎖中斷。">Failure: Credential Rotation Without Scope</a></td>
          <td>KMS Alias / Grant 的 rotation 跟 revocation 要分域 — 一次 Schedule Key Deletion 沒 scope map 等於潛在全停、Grant lifecycle 要納入治理</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/secrets-and-machine-credential-governance/" data-link-title="7.6 秘密管理與機器憑證治理" data-link-desc="以問題驅動方式整理 secret、token、key 與機器身份治理">7.6 秘密管理與機器憑證治理</a>、<a href="/blog/backend/07-security-data-protection/transport-trust-and-certificate-lifecycle/" data-link-title="7.5 傳輸信任與憑證生命週期" data-link-desc="以問題驅動方式整理傳輸信任鏈、會話完整性與憑證節奏">7.5 傳輸信任與憑證生命週期</a>（KMS 為 TLS / signing key 的 root custodian）、<a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">7.13 偵測覆蓋率與訊號治理</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/google-cloud-kms/" data-link-title="Google Cloud KMS" data-link-desc="GCP 原生 key management service、KeyRing / CryptoKey Version 設計、CMEK 整合 &#43; Cloud HSM &#43; External Key Manager">Google Cloud KMS</a>、<a href="/blog/backend/07-security-data-protection/vendors/azure-key-vault/" data-link-title="Azure Key Vault" data-link-desc="Azure 三合一 service（Secret &#43; Key &#43; Certificate）、整合 Managed Identity &#43; Entra ID RBAC、Premium tier 走 HSM">Azure Key Vault</a>、<a href="/blog/backend/07-security-data-protection/vendors/cloudhsm/" data-link-title="AWS CloudHSM" data-link-desc="Single-tenant dedicated HSM（FIPS 140-2 Level 3）、AWS 不持 Crypto User credential、合規 &#43; 資料主權場景的 key custody">CloudHSM</a></li>
<li>下游：<a href="/blog/backend/07-security-data-protection/vendors/aws-secrets-manager/" data-link-title="AWS Secrets Manager" data-link-desc="AWS 原生 secret store &#43; 內建 RDS / Redshift rotation Lambda、Resource Policy 跨帳號共享、KMS 加密">AWS Secrets Manager</a>（後端用 KMS）、<a href="/blog/backend/07-security-data-protection/vendors/cert-manager/" data-link-title="cert-manager" data-link-desc="K8s 原生 certificate lifecycle automation、支援 Let&#39;s Encrypt / Vault PKI / Venafi 等多 issuer、auto-renewal &#43; Challenge solver">cert-manager</a>（可用 KMS asymmetric key 當 issuer）</li>
<li>對照：<a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a>（transit engine / 跨雲統一介面）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（KMS 事件如何 routing 進 IR 流程）</li>
<li>官方：<a href="https://docs.aws.amazon.com/kms/">AWS KMS Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>GitHub Advanced Security</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/github-advanced-security/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/github-advanced-security/</guid><description>&lt;p>GitHub Advanced Security（GHAS）是 GitHub 內建的 &lt;em>application security platform&lt;/em>、由四大模組組成：&lt;em>Code Scanning&lt;/em>（CodeQL 為預設 SAST、可接受第三方 SARIF）、&lt;em>Secret Scanning&lt;/em>（偵測 leaked credential、含 Push Protection 預防 push）、&lt;em>Dependency Review&lt;/em>（PR 級依賴變更 gate）、&lt;em>Dependabot&lt;/em>（自動化依賴 update + alert、細節見獨立 vendor 頁）。它跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &amp;#43; Code (SAST) &amp;#43; Container &amp;#43; IaC &amp;#43; Cloud (CSPM)、Reachability analysis">Snyk&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &amp;#43; Secret &amp;#43; License &amp;#43; SBOM、Apache 2.0、CI 友善">Trivy&lt;/a> 等獨立 SCA 工具的核心差異是 &lt;em>跟 GitHub workflow / PR / Security tab 深度整合&lt;/em> — security finding 直接出現在 PR review 跟 organization Security overview、不需另一個 dashboard。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>GHAS 的核心定位是 &lt;em>把 application security 控制面收斂回 GitHub 平台&lt;/em>：SAST、Secret Scanning、Dependency Review、Dependabot 共用 GitHub 的 identity / permission / PR / branch protection / Actions / Security tab，讓 security finding 跟 code review 在同一個 surface 上決策。這跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &amp;#43; Code (SAST) &amp;#43; Container &amp;#43; IaC &amp;#43; Cloud (CSPM)、Reachability analysis">Snyk&lt;/a> 走「跨 SCM、跨雲、自有 dashboard」是相反方向 — Snyk 把 security 抽到平台之上、GHAS 把 security 釘在 GitHub 之內。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &amp;#43; Secret &amp;#43; License &amp;#43; SBOM、Apache 2.0、CI 友善">Trivy&lt;/a> 比、定位差更遠。Trivy 主打 &lt;em>container image / IaC / SBOM scan&lt;/em>、open-source 免費、適合塞進任何 CI；GHAS 主打 &lt;em>source code + secret + dependency&lt;/em>、Enterprise 付費、container scan 有但偏弱。兩者通常 &lt;em>並存&lt;/em> — Trivy 跑 container artifact、GHAS 跑 source repo。&lt;/p></description><content:encoded><![CDATA[<p>GitHub Advanced Security（GHAS）是 GitHub 內建的 <em>application security platform</em>、由四大模組組成：<em>Code Scanning</em>（CodeQL 為預設 SAST、可接受第三方 SARIF）、<em>Secret Scanning</em>（偵測 leaked credential、含 Push Protection 預防 push）、<em>Dependency Review</em>（PR 級依賴變更 gate）、<em>Dependabot</em>（自動化依賴 update + alert、細節見獨立 vendor 頁）。它跟 <a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk</a> / <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> 等獨立 SCA 工具的核心差異是 <em>跟 GitHub workflow / PR / Security tab 深度整合</em> — security finding 直接出現在 PR review 跟 organization Security overview、不需另一個 dashboard。</p>
<h2 id="服務定位">服務定位</h2>
<p>GHAS 的核心定位是 <em>把 application security 控制面收斂回 GitHub 平台</em>：SAST、Secret Scanning、Dependency Review、Dependabot 共用 GitHub 的 identity / permission / PR / branch protection / Actions / Security tab，讓 security finding 跟 code review 在同一個 surface 上決策。這跟 <a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk</a> 走「跨 SCM、跨雲、自有 dashboard」是相反方向 — Snyk 把 security 抽到平台之上、GHAS 把 security 釘在 GitHub 之內。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> 比、定位差更遠。Trivy 主打 <em>container image / IaC / SBOM scan</em>、open-source 免費、適合塞進任何 CI；GHAS 主打 <em>source code + secret + dependency</em>、Enterprise 付費、container scan 有但偏弱。兩者通常 <em>並存</em> — Trivy 跑 container artifact、GHAS 跑 source repo。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/dependabot/" data-link-title="Dependabot" data-link-desc="GitHub 原生依賴更新自動化、Version Update &#43; Security Update &#43; Alerts、Grouped Updates 減 PR noise、Auto-merge 配 branch protection">Dependabot</a> 的關係是 <em>內含</em> — Dependabot 是 GHAS 四模組之一、跟 GHAS 同一個控制平面、跟 PR / Security tab 同一條 evidence chain。本頁聚焦 GHAS 整體 + Code Scanning / Secret Scanning / Dependency Review；Dependabot 的 update PR 政策、ecosystem 覆蓋、alert routing 細節留在該頁。</p>
<p>關鍵張力：GHAS 計費走 <em>per-active-committer + per-repo</em>、2024 後 Secret Scanning 跟 Code Scanning 拆開計費。大型 mono-repo 或 committer 數量膨脹的組織會撞到成本天花板、需要選擇性 enable repo + 拆模組買；同時、Push Protection 這類 <em>預防型</em> 控制只有 enable 後才有效、選擇性 enable 等於默認 risk 接受。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>GHAS 四大模組各自承擔哪段控制責任（SAST / Secret / PR-level dependency gate / 自動 update）、哪些跟 <a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk</a> / <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> 重疊或互補</li>
<li>CodeQL 跟 SARIF 標準的關係、為什麼第三方 SAST 工具的 finding 也能進 GHAS Security tab</li>
<li>Secret Scanning 的 <em>Push Protection</em>（預防 push）跟 <em>Secret Scanning Alert</em>（偵測 leaked）的職責差、partner pattern vs custom pattern 何時用</li>
<li>何時用 GHAS、何時改走 Snyk / Trivy / GitLab Ultimate（GitLab 自家相當品）</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 GHAS 配置是否健康、最少看四件事：</p>
<ul>
<li><strong>誰能 enable / disable</strong>：Organization owner / Security manager role 配置、enable GHAS 的 audit log 是否同步、誰能改 Code Scanning workflow（branch protection 是否擋住 workflow file 直接 push）</li>
<li><strong>哪些 repo 開啟</strong>：Org Security overview 看 <em>Code Scanning / Secret Scanning / Dependency Review coverage</em>、新建 repo 是否預設啟用（Organization-level default setting）、private / internal / public repo 是否一致開啟</li>
<li><strong>Push Protection 狀態</strong>：Secret Scanning Push Protection 是否 organization-wide enable、bypass 權限給誰（developer 個人 bypass vs 必須走 Security team approval）、bypass 事件是否進 audit</li>
<li><strong>Secret Scanning Coverage</strong>：partner pattern（AWS / GCP / Stripe / Slack 等預配）是否全開、custom pattern 是否涵蓋自家 internal token（service token、internal API key）、historical scan 是否跑過（不只新 commit、舊 commit 也要掃）</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/knowledge-cards/secret-management/" data-link-title="Secret Management" data-link-desc="說明 token、key、password 與憑證如何保存、輪替與撤銷">Secret Management</a> 跟 <a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">Supply Chain Integrity</a> 邊界的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>Code Scanning 走 SARIF 標準</strong>：Code Scanning 不只是 CodeQL 的 UI、是 <em>SAST aggregation layer</em>。所有 SAST 結果（CodeQL 預設、或 Semgrep / Snyk Code / Brakeman / Bandit / SonarCloud / Checkmarx 等第三方）以 SARIF（Static Analysis Results Interchange Format）upload 到 Code Scanning、Security tab 統一展示、PR review 統一標註。意義是 <em>組織可以用多個 SAST 工具但只看一個 dashboard</em> — 不需要每個 vendor 各自登入。多工具 SARIF upload 用 GitHub Actions 的 <code>github/codeql-action/upload-sarif</code> step。</p>
<p><strong>CodeQL 是 first-class query language</strong>：CodeQL 用 Datalog-like 語法寫 <em>自定 query</em>、可以檢測 <em>organization-specific anti-pattern</em>（例：禁用某內部 deprecated function、強制 input validation 在特定 trust boundary）。vendor-provided pack（GitHub 維護的 CodeQL pack）覆蓋 OWASP Top 10 / CWE Top 25、自定 query 補組織 idiomatic check。代價是 <em>CodeQL 學習曲線陡</em> — 不是 regex / AST pattern、是完整的 graph query language。</p>
<p><strong>Secret Scanning 三層職責</strong>：Secret Scanning 分三層。<em>Partner pattern</em> — GitHub 跟 AWS / GCP / Stripe / Slack / npm 等 vendor 預配 token pattern、預設 detection 範圍最大、leaked token 還會通知 vendor revoke。<em>Push Protection</em> — commit push 前 scan、發現 secret 直接 reject push、開發者必須先移除才能 push；這是 <em>預防</em> 不是 <em>偵測</em>、不需要等 leaked 後 rotation。<em>Custom pattern</em> — 組織自己的 internal token（service-to-service API key、legacy auth token）寫 regex pattern、配 validation endpoint 降 FP。</p>
<p><strong>Dependency Review 是 PR-level gate</strong>：每個 PR 跑 <em>新增 / 升級依賴的漏洞檢查 + license check</em>、把 <em>新引入 CVE</em> 列在 PR review、可設 branch protection 強制 PR 過 Dependency Review 才能 merge。這跟 <a href="/blog/backend/07-security-data-protection/vendors/dependabot/" data-link-title="Dependabot" data-link-desc="GitHub 原生依賴更新自動化、Version Update &#43; Security Update &#43; Alerts、Grouped Updates 減 PR noise、Auto-merge 配 branch protection">Dependabot</a> 是互補關係：Dependabot 是 <em>已 merge 依賴的 update PR</em>（時間軸：merge 後 vuln 出現、自動發 update PR）、Dependency Review 是 <em>PR 加新依賴時的 gate</em>（時間軸：merge 前 vuln 已知、擋 PR）。兩條軸都要開。</p>
<p><strong>Security overview 是 org-level dashboard</strong>：Organization Security tab 看 <em>跨 repo</em> 的 Code Scanning / Secret Scanning / Dependency / Dependabot alert 彙整、用 repo / severity / age filter 排序。對於 <em>security team 不是 repo owner</em> 的組織、Security manager role 給 security team 跨 repo read + triage 權限、不需要 admin。</p>
<p><strong>Security Advisories（CVE 揭露 workflow）</strong>：自家 OSS / 商業 product 出 CVE 時、走 <em>GitHub Security Advisory</em> — 在 private fork 修補、coordinated disclosure 時間到公開 advisory、GitHub 自動向 <a href="https://www.cve.org/">CVE Numbering Authority</a> 申請 CVE ID。這條 workflow 是 <em>維護者視角</em>、不是 <em>使用者視角</em>；使用者收到的是其他人發的 advisory 進 Dependabot alert。</p>
<p><strong>SARIF integration 是 GHAS 的 <em>aggregation</em> 角色關鍵</strong>：GHAS 不強迫只用 CodeQL — Snyk Code / Semgrep / SonarCloud 等 SAST 工具跑完輸出 SARIF、CI 上傳到 GitHub、Security tab 集中展示。意義是 <em>組織用 Snyk 做 SAST、但 finding 走 GHAS UI</em> 是合法配置；GHAS 賣的不只是 CodeQL、是 SAST 統一視圖。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>GHAS</th>
          <th>Snyk</th>
          <th>Trivy</th>
          <th>Dependabot（GHAS 子模組）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>主要範圍</td>
          <td>Source code + secret + dependency（PR-level）</td>
          <td>SCA + Container + IaC + SAST（跨 SCM）</td>
          <td>Container image + IaC + SBOM scan</td>
          <td>依賴 update + alert（merged code）</td>
      </tr>
      <tr>
          <td>SCM 綁定</td>
          <td>緊綁 GitHub</td>
          <td>跨 GitHub / GitLab / Bitbucket / Azure Repos</td>
          <td>無 SCM 綁定、跑在 CI / artifact registry</td>
          <td>緊綁 GitHub</td>
      </tr>
      <tr>
          <td>SAST 引擎</td>
          <td>CodeQL 預設 + 第三方 SARIF aggregation</td>
          <td>Snyk Code（DeepCode）</td>
          <td>無 SAST</td>
          <td>無</td>
      </tr>
      <tr>
          <td>Secret Scanning</td>
          <td>Partner pattern + Push Protection + custom pattern</td>
          <td>Snyk Secret Scanning（較弱）</td>
          <td>有限（filesystem secret scan）</td>
          <td>無</td>
      </tr>
      <tr>
          <td>Container 強度</td>
          <td>中（Code Scanning 可掃 Dockerfile）</td>
          <td>強（Snyk Container 是主打）</td>
          <td>強（Trivy 是 container scan 標準）</td>
          <td>無</td>
      </tr>
      <tr>
          <td>License / SBOM</td>
          <td>有（Dependency Review 含 license）</td>
          <td>強（SBOM 生成、license compliance dashboard）</td>
          <td>強（SBOM 是 first-class）</td>
          <td>無</td>
      </tr>
      <tr>
          <td>PR 整合</td>
          <td>深 — Security tab + PR review 直連</td>
          <td>中 — GitHub Check + 跨 SCM PR comment</td>
          <td>中 — 第三方 Action 整合</td>
          <td>深 — 自動發 PR</td>
      </tr>
      <tr>
          <td>計費</td>
          <td>Per-active-committer + per-repo（Enterprise）</td>
          <td>Per-developer + tier</td>
          <td>Open source 免費（Aqua 商業版加值）</td>
          <td>GHAS 一部分</td>
      </tr>
      <tr>
          <td>適合</td>
          <td>GitHub-heavy org、想統一 PR + security UI</td>
          <td>多 SCM / 多雲、SCA + Container 一站、license 強需求</td>
          <td>Container / IaC scan 為主、CI pluggable</td>
          <td>GitHub repo 想要自動依賴 update</td>
      </tr>
      <tr>
          <td>不適合</td>
          <td>GitLab / Bitbucket / 自管 Git 為主</td>
          <td>GitHub-only 又要省成本</td>
          <td>需要 SAST + Secret Scanning</td>
          <td>不想自動產生 PR（噪音）</td>
      </tr>
  </tbody>
</table>
<p>選 GHAS 的核心訴求：<em>GitHub 是 SCM</em> + 想 <em>PR review 跟 security finding 合一</em> + Enterprise 預算可吸收 per-committer cost。GitLab 主要的組織直接走 GitLab Ultimate 的對等功能；多 SCM 或 container 為主走 Snyk + Trivy 組合。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>CodeQL custom query 開發</strong>：寫自定 query 用 CodeQL CLI 本地開發、跑 <code>codeql database analyze</code>、SARIF output 上傳。常見場景：禁用 internal deprecated API、特定 framework 的 misuse pattern、組織 idiomatic security check。Query pack 可以 publish 到 GitHub Container Registry 或 internal registry、跨 repo 復用。代價是 <em>維護成本</em> — CodeQL query language 學習曲線陡、組織需要至少 1-2 個 security engineer 專門養護。</p>
<p><strong>Push Protection bypass workflow</strong>：Push Protection reject push 後、developer 可以 <em>bypass</em>（標記 false positive / test data / 風險已知）。Bypass 權限治理是關鍵 — 開放給 developer 個人 bypass 失去預防意義、強制 Security team approval 又拖慢 dev velocity。常見折中：低風險 pattern（test fixture token）developer 可 bypass、高風險 pattern（production credential）必須 Security team approve；所有 bypass 事件進 audit log。</p>
<p><strong>跟 GitHub Actions 整合</strong>：Code Scanning 走 GitHub Actions workflow 跑 CodeQL — <code>github/codeql-action/init</code> + <code>github/codeql-action/analyze</code>。同 workflow 可以加 <code>upload-sarif</code> step 接第三方 SAST 結果。Actions 用 GitHub-hosted runner 跑 CodeQL 是預設、大型 repo 跑 CodeQL analyze 可能超時、需改 self-hosted runner（大 RAM / 多 CPU）— 但 self-hosted runner 自身是 supply chain 風險、需要 ephemeral runner + 限制 secret access。</p>
<p><strong>SARIF 多工具整合</strong>：第三方 SAST / SCA / Container scan 工具（Snyk / Semgrep / Trivy / Brakeman / Bandit / Gosec）跑完輸出 SARIF、CI 上傳到 GHAS。實務上組織常用 <em>CodeQL + Semgrep</em> 雙軌 — CodeQL 跑深度 graph query、Semgrep 跑快速 pattern 規則；finding 在 Security tab 用 <em>tool</em> filter 分開看。</p>
<p><strong>Secret Scanning partner pattern</strong>：GitHub 維護的 partner pattern list 涵蓋 AWS / GCP / Azure / Stripe / Slack / npm / Docker Hub / GitHub PAT 等。leaked token detect 後、GitHub 自動通知 vendor、vendor 端可選擇 <em>自動 revoke</em> 該 token。意義是 <em>組織不需要做 rotation</em> — vendor 已經把 leaked token 廢掉。custom pattern 則需要組織自己提供 validation endpoint、GHAS 呼叫驗證才確認是真 leak。</p>
<p><strong>GHAS Cloud-hosted vs Self-hosted Runner 治理</strong>：CodeQL 跑在 GitHub-hosted runner 是預設、所有 source code 上傳到 GitHub 運算環境。對 <em>source code 機密度高</em> 的組織（金融 / 國防 / 法規限制 source 出境）、需走 self-hosted runner。Self-hosted runner 的供應鏈風險見 <a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/github-oauth-2022-token-supply-chain/" data-link-title="7.R7.2.2 GitHub OAuth 2022：第三方 token 供應鏈風險" data-link-desc="第三方整合 token 被竊後，如何形成跨組織存取風險">GitHub OAuth 2022</a> — runner token 是 supply chain entry、OIDC short-lived token 是建議方向。</p>
<p><strong>GHAS Enterprise pricing trap</strong>：Per-active-committer 計費、organization 內所有 <em>過去 90 天有 commit</em> 的 user 都算 active committer、即使只 commit 1 行也計費。大型公司容易超支；2024 後 Secret Scanning 跟 Code Scanning 拆開計費、可只買 Secret Scanning（單價較低）給全 org、Code Scanning 給關鍵 repo。Public repo 上 GHAS 功能多數免費（Code Scanning、Secret Scanning、Dependency Review）；GitHub Enterprise Cloud 的 internal / private repo 才落入 GHAS 計費範圍 — 兩者範圍不同、新組織常踩到把 private repo 全開的成本。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>新建 repo 沒自動開 GHAS</strong>：Organization-level default 沒設、新 repo 預設 disable — 開 Organization Security settings 的 <em>Enable for new repositories</em>、現有 repo 用 bulk enable</li>
<li><strong>Push Protection 大量誤殺</strong>：custom pattern regex 太寬、合法字串被當 secret — 加 validation endpoint 或收緊 regex、bypass 統計看 FP rate</li>
<li><strong>Secret Scanning 沒掃歷史 commit</strong>：只 enable 後新 commit 觸發、舊 commit leaked secret 沒被發現 — 跑 <em>historical scan</em>（enable 後 GitHub 自動掃過去全部 commit）、可能花數小時</li>
<li><strong>Dependency Review 沒擋住 vuln PR</strong>：Branch protection 沒加 <em>Dependency Review</em> required check — 加進 required status check、新 PR 才強制過</li>
<li><strong>Code Scanning workflow 跑很久 / 超時</strong>：repo 太大、GitHub-hosted runner RAM 不足 — 換 larger runner（GitHub Larger Runners）或 self-hosted、或只跑 changed file analysis</li>
<li><strong>Custom CodeQL query FP 多</strong>：query 寫得太寬、commit 都跳 alert — 加 <code>@precision high</code> 標籤、用 <code>Sink-Source</code> 分析降低 reach</li>
<li><strong>第三方 SAST SARIF 沒進 Security tab</strong>：upload-sarif step 沒設對 category 或 permissions — <code>security-events: write</code> permission 必須在 workflow 給；同 repo 多工具用不同 <code>category</code> 區分</li>
<li><strong>Bypass 沒進 audit</strong>：Push Protection bypass 沒同步到 SIEM — Enterprise audit log streaming 開、event filter 加 <code>secret_scanning.bypass</code></li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>多 SCM（GitHub + GitLab + Bitbucket）</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk</a></td>
      </tr>
      <tr>
          <td>Container image scan 為主</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> 或 Snyk Container</td>
      </tr>
      <tr>
          <td>SBOM 生成 + license compliance</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/syft-grype/" data-link-title="Syft &#43; Grype" data-link-desc="Anchore 開源姐妹工具：Syft 產 SBOM (CycloneDX / SPDX) &#43; Grype scan 漏洞、Unix philosophy、cosign attestation 整合">Syft + Grype</a>（SBOM-first OSS）/ <a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk</a> + <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a>（SBOM 含在 scan）</td>
      </tr>
      <tr>
          <td>GitLab 為主</td>
          <td>GitLab Ultimate（SAST / Secret Detection / Dependency Scanning 內建）</td>
      </tr>
      <tr>
          <td>Secret scan 但不在 GitHub</td>
          <td>GitGuardian / Gitleaks</td>
      </tr>
      <tr>
          <td>Runtime detection（不只 source code）</td>
          <td><a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">7.13 偵測覆蓋率與訊號治理</a> 系列工具</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>CodeQL 完整 query language reference</li>
<li>Dependabot 的 update PR 政策、ecosystem 覆蓋、grouped update（見 <a href="/blog/backend/07-security-data-protection/vendors/dependabot/" data-link-title="Dependabot" data-link-desc="GitHub 原生依賴更新自動化、Version Update &#43; Security Update &#43; Alerts、Grouped Updates 減 PR noise、Auto-merge 配 branch protection">Dependabot vendor 頁</a>）</li>
<li>GHAS Enterprise Server（自管 GitHub）跟 Cloud GHAS 的功能差異</li>
<li>各語言 / 框架的 CodeQL pack 完整覆蓋表</li>
<li>GHAS 跟 GitHub Copilot Autofix 整合的 AI-assisted remediation 細節</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>GHAS 在 07 案例庫沒有 <em>直接 GHAS-level vendor 事件</em>。對照引用展示 GHAS 在 supply chain / source-level 控制的能力邊界：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 GHAS 的關係</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/log4shell-cve-2021-44228-component-chain/" data-link-title="7.R7.2.7 Log4Shell 2021：共用元件風險與修補鏈" data-link-desc="共用元件漏洞如何同步影響多服務，並迫使團隊建立依賴治理 workflow">Log4Shell CVE-2021-44228</a></td>
          <td>Dependency Review + Code Scanning 應覆蓋 transitive 依賴、不只 direct import；Security Advisory 是維護者揭露 CVE 的 workflow</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/xz-backdoor-2024-open-source-supply-chain/" data-link-title="7.R7.2.4 XZ Backdoor 2024：開源供應鏈長期滲透" data-link-desc="開源維護鏈遭滲透後，為何會直接影響廣泛 Linux 發行流程">XZ Backdoor 2024</a></td>
          <td>對照啟示 — GHAS Dependency Review 看 <em>package version</em>、看不到 <em>maintainer takeover</em>；需補 release-tarball vs git tag 差異跟 maintainer trust baseline</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/solarwinds-2020-sunburst/" data-link-title="7.R7.2.1 SolarWinds 2020：更新鏈被濫用" data-link-desc="合法更新流程遭植入後，攻擊者如何長期潛伏與橫向擴散">SolarWinds 2020 Sunburst</a></td>
          <td>對照啟示 — Code Scanning 是 source-level、看不到 build-time 植入；需配合 artifact provenance（SLSA L2+）+ reproducible build</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/github-oauth-2022-token-supply-chain/" data-link-title="7.R7.2.2 GitHub OAuth 2022：第三方 token 供應鏈風險" data-link-desc="第三方整合 token 被竊後，如何形成跨組織存取風險">GitHub OAuth 2022 Token Supply Chain</a></td>
          <td>對照啟示 — GHAS 自身 token / Actions 權限治理是 supply chain risk、Push Protection + OIDC trust（非長期 token）是 mitigation</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">7.12 供應鏈完整性與 Artifact 信任</a></td>
          <td>GHAS 是 supply chain 治理工具集、章節原則對應四模組 workflow</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">7.12 供應鏈完整性與 Artifact 信任</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk</a>、<a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a>、<a href="/blog/backend/07-security-data-protection/vendors/dependabot/" data-link-title="Dependabot" data-link-desc="GitHub 原生依賴更新自動化、Version Update &#43; Security Update &#43; Alerts、Grouped Updates 減 PR noise、Auto-merge 配 branch protection">Dependabot</a>、<a href="/blog/backend/07-security-data-protection/vendors/syft-grype/" data-link-title="Syft &#43; Grype" data-link-desc="Anchore 開源姐妹工具：Syft 產 SBOM (CycloneDX / SPDX) &#43; Grype scan 漏洞、Unix philosophy、cosign attestation 整合">Syft + Grype</a>（SBOM 走 SARIF 進 GHAS Code Scanning 是常見組合）</li>
<li>下游：<a href="/blog/backend/07-security-data-protection/secrets-and-machine-credential-governance/" data-link-title="7.6 秘密管理與機器憑證治理" data-link-desc="以問題驅動方式整理 secret、token、key 與機器身份治理">7.6 秘密管理與機器憑證治理</a>（Secret Scanning 配 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a> rotation）</li>
<li>跨類：<a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">7.13 偵測覆蓋率與訊號治理</a>（GHAS alert 進 SIEM 的 routing）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（leaked secret / SAST critical finding 進 IR 流程）</li>
<li>官方：<a href="https://docs.github.com/en/get-started/learning-about-github/about-github-advanced-security">GitHub Advanced Security Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>Google Security Operations</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/google-security-operations/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/google-security-operations/</guid><description>&lt;p>Google Security Operations 是 Google 雲端的 SOC 整合平台、2023 年起把前 &lt;em>Chronicle SIEM&lt;/em> + 2022 收購的 &lt;em>Siemplify SOAR&lt;/em> + 2022 收購的 &lt;em>Mandiant threat intel&lt;/em> 三條產品線整合成單一品牌。它跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &amp;#43; indexer &amp;#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &amp;#43; EDR &amp;#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &amp;#43; CSPM &amp;#43; CWS &amp;#43; AAP &amp;#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Security&lt;/a> 的差異在 &lt;em>資料規模假設 + 計費哲學 + threat intel 內建程度&lt;/em>、偵測能力本身相近 — Google 的設計假設是 &lt;em>PB/day ingestion + Google 級基礎設施 + 固定費率 by data tier&lt;/em>、跟 Splunk per-GB 累進的計費哲學完全相反。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Google Security Operations 的核心定位是 &lt;em>為超大規模 SOC 設計的雲原生 SIEM + SOAR + threat intel 一體機&lt;/em>、底層走 Google 自家 search infrastructure、上層由四個 first-class concept 撐起來：&lt;em>UDM&lt;/em>（Unified Data Model、Google 自定 schema、所有 source 強制 normalize）、&lt;em>YARA-L&lt;/em>（Google 自家 detection rule 語言）、&lt;em>Curated Detection&lt;/em>（Google 維護的 detection rule 訂閱、客戶不需自己拉）、&lt;em>Mandiant Applied Threat Intel&lt;/em>（事件期間自動 enrich + IoC push）。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &amp;#43; indexer &amp;#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk&lt;/a> 比、Google 走 &lt;em>fixed-price by data tier + 強制 schema normalization&lt;/em> — Splunk per-GB ingestion 計費在 PB-scale 會痛、Google 在 multi-PB 通常便宜 3-5 倍、但客戶要接受 UDM 強制 schema 跟 YARA-L 新語法。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &amp;#43; EDR &amp;#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security&lt;/a> 比、Google 是 SaaS-only + 大規模優化、Elastic 可自管 + OSS-friendly。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &amp;#43; CSPM &amp;#43; CWS &amp;#43; AAP &amp;#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Security&lt;/a> 比、Google 是 &lt;em>純 SOC 專用工具&lt;/em>、Datadog 是 &lt;em>observability 平面上的 security view&lt;/em>；Datadog 適合中等規模 + observability 已用 Datadog、Google 適合大規模 SOC + 不需要 observability 同 plane。&lt;/p></description><content:encoded><![CDATA[<p>Google Security Operations 是 Google 雲端的 SOC 整合平台、2023 年起把前 <em>Chronicle SIEM</em> + 2022 收購的 <em>Siemplify SOAR</em> + 2022 收購的 <em>Mandiant threat intel</em> 三條產品線整合成單一品牌。它跟 <a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / <a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a> / <a href="/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &#43; CSPM &#43; CWS &#43; AAP &#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Security</a> 的差異在 <em>資料規模假設 + 計費哲學 + threat intel 內建程度</em>、偵測能力本身相近 — Google 的設計假設是 <em>PB/day ingestion + Google 級基礎設施 + 固定費率 by data tier</em>、跟 Splunk per-GB 累進的計費哲學完全相反。</p>
<h2 id="服務定位">服務定位</h2>
<p>Google Security Operations 的核心定位是 <em>為超大規模 SOC 設計的雲原生 SIEM + SOAR + threat intel 一體機</em>、底層走 Google 自家 search infrastructure、上層由四個 first-class concept 撐起來：<em>UDM</em>（Unified Data Model、Google 自定 schema、所有 source 強制 normalize）、<em>YARA-L</em>（Google 自家 detection rule 語言）、<em>Curated Detection</em>（Google 維護的 detection rule 訂閱、客戶不需自己拉）、<em>Mandiant Applied Threat Intel</em>（事件期間自動 enrich + IoC push）。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> 比、Google 走 <em>fixed-price by data tier + 強制 schema normalization</em> — Splunk per-GB ingestion 計費在 PB-scale 會痛、Google 在 multi-PB 通常便宜 3-5 倍、但客戶要接受 UDM 強制 schema 跟 YARA-L 新語法。跟 <a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a> 比、Google 是 SaaS-only + 大規模優化、Elastic 可自管 + OSS-friendly。跟 <a href="/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &#43; CSPM &#43; CWS &#43; AAP &#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Security</a> 比、Google 是 <em>純 SOC 專用工具</em>、Datadog 是 <em>observability 平面上的 security view</em>；Datadog 適合中等規模 + observability 已用 Datadog、Google 適合大規模 SOC + 不需要 observability 同 plane。</p>
<p>關鍵張力：<em>fixed-price tier</em> 在小規模反而不划算、PB-scale 才回本。組織要看清楚自己的 ingestion 量級 — TB/day 以下走 Datadog / Elastic 通常更便宜、TB-PB/day 之間是模糊地帶、PB/day 以上 Google 是少數能撐又便宜的選擇。Mandiant threat intel 跟 Gemini for Security 是 Google-only 的加值、但這兩個是 <em>enhancement</em>、不是選 Google 的主理由。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>Google Security Ops 在 SOC stack 承擔哪一段（log aggregation + SIEM + SOAR + threat intel 一體）、跟 <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google Cloud IAM</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-secret-manager/" data-link-title="Google Secret Manager" data-link-desc="GCP 原生 secret store、CMEK &#43; Workload Identity Federation 整合、rotation 走自寫 Cloud Function 而非 built-in Lambda">Google Secret Manager</a> 怎麼整合</li>
<li>UDM forced normalization 跟 YARA-L 對 detection 設計的影響（schema-first 而非 query-first）</li>
<li>Curated Detection + Mandiant Applied Threat Intel 在偵測 lifecycle 的位置（不是自己拉、是訂閱）</li>
<li>何時選 Google Security Ops、何時走 Splunk / Elastic / Datadog 的取捨</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Google Security Ops deployment 是否健康、最少看四件事：</p>
<ul>
<li><strong>Ingestion 邊界</strong>：哪些 source 進來（Forwarder / GCS bucket / Pub/Sub feed / Cloud-native API feed）、UDM normalization 是否覆蓋全部 source、自家 app log 的 parser 是否寫好</li>
<li><strong>Detection 治理</strong>：誰能改 YARA-L rule、Curated Detection 開了哪些、自家 rule 是否走版控（Git → API push）、staging tenant 是否在 production 之前 sanity-check</li>
<li><strong>Threat intel 流向</strong>：Mandiant Applied Threat Intel 是否啟用、Curated Detection 是否跟新 IoC 自動同步、IoC enrichment 是否回 alert 上下文</li>
<li><strong>Response 流向</strong>：Siemplify SOAR 是否接 alert、playbook 是否進版控、跟 <a href="/blog/backend/08-incident-response/" data-link-title="模組八：事故處理與復盤" data-link-desc="用 IR 領域詞彙建問題節點、以服務級案例庫累積事故脈絡，先建概念與案例庫再進實作交接">8 incident response</a> 的 routing 是否定義</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">Detection Coverage and Signal Governance</a> 的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>Ingestion 路徑</strong>：log 進 Google Security Ops 有三種主路徑 — <em>Chronicle Forwarder</em>（agent-based、on-prem / VM、syslog / file tail）、<em>Cloud Storage feed</em>（log 先進 GCS bucket、Google 拉）、<em>Pub/Sub feed</em>（serverless / GCP 原生 push）、再加 <em>Direct API feed</em>（cloud SaaS 像 Okta / Azure AD / AWS CloudTrail 透過原廠 connector）。SaaS-heavy 環境通常以 Direct API feed 為主、on-prem 才需要 Forwarder。</p>
<p><strong>UDM (Unified Data Model)</strong>：UDM 是 Google 自定的統一 event schema、所有 source（CloudTrail / Azure AD / Okta / endpoint / DNS）在 ingestion 時 <em>強制 normalize</em> 到 UDM 欄位（<code>principal.user</code>、<code>target.resource</code>、<code>security_result.action</code> 等）。跟 <a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> CIM 同概念、但 Splunk CIM 是 <em>選擇性 mapping</em>、Google UDM 是 <em>forced normalization</em> — 不寫 parser 就不能 ingest custom source。設計取捨：schema-first 讓跨 source query 一致、但客製 source 的 onboarding 變重。</p>
<p><strong>YARA-L detection rule</strong>：Google 自家 detection rule 語言、跟 SPL / EQL 同類但結構更明示 — <code>events { }</code> 段定義 source pattern、<code>match { }</code> 段定義 join / time window、<code>condition { }</code> 段定義 threshold、<code>outcome { }</code> 段定義 risk score。比 SPL 的 pipe 風格更接近 <em>關聯式宣告</em>、特別適合表達 <em>time-bounded sequence + cross-source join</em>。Uber MFA 那種「5min 內 50 個 MFA fail + 新裝置 + 異常地理」用 YARA-L 直接寫成 sequence pattern 比 SPL 清楚。</p>
<p><strong>Curated Detection</strong>：Google 維護的 detection rule 訂閱集合、跟 Splunk Security Content 同類但 Google 是 <em>built-in subscription</em>、客戶不需要自己拉 / merge — Google 自動跟 Mandiant threat intel 同步、新 IoC 發布後對應 rule 自動 enable。組織通常 <em>先全部啟用 baseline、再選擇性 disable noisy 規則 + 補自家 custom YARA-L</em>。</p>
<p><strong>Applied Threat Intel (Mandiant)</strong>：事件發生時 Google 自動把 alert 裡的 IoC（IP / domain / hash）跟 Mandiant feed 對照、若命中已知 APT 活動就升級 risk score + 附上 Mandiant 報告。跟其他 SIEM 走第三方 threat intel feed 需要自己 maintain enrichment pipeline 不同、Google 走 <em>vertical integration</em> — 收購 Mandiant 後直接內建。</p>
<p><strong>Siemplify SOAR</strong>：2022 收購 Siemplify 後整合進 Google Security Ops、playbook 處理 alert triage + 自動 response — 例如 leaked credential 自動 rotate（拉 <a href="/blog/backend/07-security-data-protection/vendors/google-secret-manager/" data-link-title="Google Secret Manager" data-link-desc="GCP 原生 secret store、CMEK &#43; Workload Identity Federation 整合、rotation 走自寫 Cloud Function 而非 built-in Lambda">Google Secret Manager</a> API）、suspect user 自動 disable（拉 <a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a> / Google Workspace API）、suspect IP 自動加 firewall block（拉 <a href="/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &#43; DDoS &#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF</a> custom rule）。playbook 進版控、走 approval gate for high-impact action、不能黑箱 fire-and-forget。</p>
<p><strong>Entity Graph</strong>：Google Security Ops 把 user / asset / IP / domain / hash 等實體做 graph、做 <em>correlation + lateral movement detection</em>。Snowflake 2024 那種「同一 credential / IP 跨多個 Snowflake account」的橫向擴散用 Entity Graph 直接視覺化關聯。</p>
<p><strong>Google Cloud 整合</strong>：跟 <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google Cloud IAM</a> / Workload Identity Federation 整合度高 — GCP audit log 直接內建 connector、IAM policy change 直接 surface 成 alert 候選、跨 GCP project 的 federation 走 <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google Cloud IAM</a> 認證。非 GCP 環境（AWS / Azure / on-prem）一樣支援、但設定路徑比 Splunk add-on 略陡。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Google Security Operations</th>
          <th>Splunk</th>
          <th>Elastic Security</th>
          <th>Datadog Security</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>計費模型</td>
          <td>Fixed price by data tier（PB-scale 划算）</td>
          <td>Ingestion-based（GB/day、累進）</td>
          <td>Resource-based（node / cluster size）</td>
          <td>Per-host + per-event（events/month）</td>
      </tr>
      <tr>
          <td>Schema 處理</td>
          <td>UDM forced normalization</td>
          <td>CIM optional mapping</td>
          <td>ECS optional mapping</td>
          <td>Tag-based、彈性高</td>
      </tr>
      <tr>
          <td>Detection 語言</td>
          <td>YARA-L（結構化 events / match / condition）</td>
          <td>SPL（pipe-based、表達力強）</td>
          <td>KQL / EQL</td>
          <td>Datadog query</td>
      </tr>
      <tr>
          <td>Detection content</td>
          <td>Curated Detection 內建訂閱</td>
          <td>Splunk Security Content（OSS、自拉）</td>
          <td>Elastic Prebuilt + Sigma</td>
          <td>Datadog Security Rules</td>
      </tr>
      <tr>
          <td>Threat intel</td>
          <td>Mandiant Applied Threat Intel 內建</td>
          <td>需第三方 feed + 自家 pipeline</td>
          <td>需第三方 feed</td>
          <td>Datadog 內建 + 第三方</td>
      </tr>
      <tr>
          <td>SOAR / Response</td>
          <td>Siemplify SOAR 內建</td>
          <td>Splunk SOAR（前 Phantom、業界先驅）</td>
          <td>Cases + Elastic Defend</td>
          <td>Workflow Automation（基本）</td>
      </tr>
      <tr>
          <td>LLM-assisted</td>
          <td>Gemini for Security 內建（2024+）</td>
          <td>Splunk AI Assistant</td>
          <td>Elastic AI Assistant</td>
          <td>Bits AI</td>
      </tr>
      <tr>
          <td>部署模型</td>
          <td>SaaS only（Google Cloud）</td>
          <td>Self-hosted / SaaS</td>
          <td>Self-hosted / SaaS / Serverless</td>
          <td>SaaS only</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>PB-scale SOC、Google Cloud heavy、要 Mandiant</td>
          <td>Enterprise + 跨 on-prem、預算允許</td>
          <td>OSS-friendly、Elastic stack 已用</td>
          <td>Cloud-native + observability 已用 Datadog</td>
      </tr>
      <tr>
          <td>退場成本</td>
          <td>中 — YARA-L 跟 UDM 是 Google-specific</td>
          <td>高 — SPL / detection / dashboard 量多</td>
          <td>中 — Sigma / Lucene 較可移植</td>
          <td>中</td>
      </tr>
  </tbody>
</table>
<p>選 Google Security Ops 的核心訴求：<em>PB-scale ingestion + fixed-price 計費可預期 + Mandiant threat intel 內建 + Google Cloud 整合度</em>。中等規模 / on-prem 為主 / 預算敏感 / 需要 observability 同 plane 的場景都更適合走 Splunk / Elastic / Datadog。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Risk Score multi-signal aggregation</strong>：Google Security Ops 給每個 entity（user / asset）累積 risk score、跨多 rule 加總、超 threshold 才升級 alert。設計上跟 <a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> RBA 同類、但 Google 把 risk decay 跟 attribution 走 Entity Graph、跨 entity 關係的 risk 傳遞比較細。配對 <a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/uber-2022-mfa-fatigue/" data-link-title="7.R7.1.1 Uber 2022：MFA 疲勞與內部工具擴散" data-link-desc="從社交工程到內部工具存取，拆解身分流程與權限邊界的失效點">Uber 2022 MFA Fatigue</a> 的 lesson：MFA fail 累積 + 新裝置 login + 異常地理三個 signal 加總、單獨任一個都不該 alert。</p>
<p><strong>Cross-tenant federated search</strong>：MSSP / 大型集團多 BU 可在 Google Security Ops 跨多個 tenant 做 federated search、單一 console 看跨組織 detection。權限走 <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google Cloud IAM</a> role assignment、跨 tenant admin 是高權限角色、走 break-glass + audit。</p>
<p><strong>Applied Threat Intel + Curated Detection 同步</strong>：Mandiant 揭露新 APT 活動後、Curated Detection 對應 rule 自動 enable + Applied Threat Intel IoC 自動 push、客戶 SOC 不需要手動 onboard。SolarWinds 2020 揭露當下、Mandiant client 是少數能即時 enable 對應 detection 的 SOC。</p>
<p><strong>Siemplify playbook 工程化</strong>：playbook 走 <em>graph-based workflow</em>（不是 linear pipeline）、可以 branching / approval gate / human-in-the-loop。Production rule 走 <em>containment-first</em>（disable session、不 delete account）+ approval gate for irreversible action。</p>
<p><strong>Gemini for Security (2024+)</strong>：LLM-assisted investigation — natural language 問「過去 24hr 哪些 user 有異常 GCP API 行為」直接生成 UDM query、alert 自動 summarize + 提供 next step 建議。不取代 SOC analyst、但縮短 triage time。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Custom source ingest 失敗</strong>：UDM parser 沒寫 / 寫錯、source 進不來或欄位 NULL — 補 parser、staging tenant 跑 sanity check、看 UDM event count by source 確認 normalization 通過</li>
<li><strong>Detection 沒觸發 / 漏報</strong>：YARA-L 的 <code>match { }</code> 段 time window 寫太短、或 <code>condition { }</code> threshold 寫太高 — staging tenant 用歷史資料 backtest、tune window / threshold 後 promote</li>
<li><strong>Alert volume 過多</strong>：Curated Detection 全開沒 tune、env-specific noise 沒 disable — 跟 <a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> 一樣走 staging 觀察 false positive curve、tune 或 disable 個別規則</li>
<li><strong>Mandiant threat intel 沒命中</strong>：licensing tier 沒包 Mandiant Advantage、或 enrichment pipeline 沒啟用 — 檢查 tier、確認 Applied Threat Intel 開</li>
<li><strong>Siemplify playbook 黑箱 fire-and-forget</strong>：自動 disable 結果誤殺合法 user — playbook 走 approval gate、預設 containment 不 deletion、定期 dry-run</li>
<li><strong>Cross-tenant admin 太多</strong>：日常運維用 cross-tenant admin、blast radius 太大 — 收 admin、改 tenant-scoped role + 特定 capability、跨 tenant 走 break-glass</li>
<li><strong>Cost 比預期高</strong>：data tier 選錯（買了 Enterprise Plus 卻只用 Enterprise feature）、retention 設太長 — 看實際 ingestion + retention 用量、tier 跟 retention 一起 review</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Enterprise + 跨 on-prem + detection 成熟</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a></td>
      </tr>
      <tr>
          <td>OSS-friendly / 自管 / 預算敏感</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a></td>
      </tr>
      <tr>
          <td>Cloud-native + observability 已用 Datadog</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &#43; CSPM &#43; CWS &#43; AAP &#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Security</a></td>
      </tr>
      <tr>
          <td>DLP / sensitive data discovery</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/google-dlp/" data-link-title="Google DLP" data-link-desc="GCP 原生 Sensitive Data Protection：infoType discovery &#43; transformation (mask / FPE / tokenize / k-anonymity)、整合 BigQuery / GCS / Cloud SQL">Google DLP</a> / <a href="/blog/backend/07-security-data-protection/vendors/microsoft-purview/" data-link-title="Microsoft Purview" data-link-desc="Microsoft 跨 M365 / Azure / endpoint 的 data governance &#43; information protection &#43; DLP &#43; insider risk 統合平台、label-driven">Microsoft Purview</a></td>
      </tr>
      <tr>
          <td>Endpoint detection 為主</td>
          <td>CrowdStrike Falcon / Microsoft Defender for Endpoint</td>
      </tr>
      <tr>
          <td>Incident routing</td>
          <td><a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>YARA-L 完整語法 reference、UDM 全欄位 schema</li>
<li>Chronicle / Siemplify / Mandiant 三條產品線整合前的歷史細節</li>
<li>Mandiant Advantage 平台（threat intel 訂閱、跟 SIEM 整合但獨立產品）</li>
<li>VirusTotal（Google 旗下、跟 Mandiant 互補但獨立服務）</li>
<li>Gemini for Security 的 prompt engineering 細節</li>
<li>Google Workspace security center（屬 Google Workspace、不在 Security Ops 範圍）</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>Google Security Ops 在 07 案例庫沒有直接 vendor-level 事件、但所有 detection-related case 都是 SIEM 偵測覆蓋率的對照：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 Google Security Ops 的關係（對照啟示）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/microsoft-storm-0558-2023-signing-key-chain/" data-link-title="7.R7.1.5 Microsoft Storm-0558 2023：簽章金鑰鏈與郵件存取" data-link-desc="從簽章金鑰保護失效到雲端郵件存取，拆解身分信任鏈的關鍵控制點">Microsoft Storm-0558 Signing Key Chain</a></td>
          <td>UDM 強制 normalize 跨 Azure AD / GCP / Okta token validation 欄位、YARA-L 跨 source join 直接表達跨租戶 token forging pattern、Entity Graph 視覺化</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/uber-2022-mfa-fatigue/" data-link-title="7.R7.1.1 Uber 2022：MFA 疲勞與內部工具擴散" data-link-desc="從社交工程到內部工具存取，拆解身分流程與權限邊界的失效點">Uber 2022 MFA Fatigue</a></td>
          <td>YARA-L sequence pattern 直接表達「MFA fail count + 新裝置 login」、Risk Score 累積到 threshold 觸發 Siemplify playbook 自動 disable session</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/solarwinds-2020-sunburst/" data-link-title="7.R7.2.1 SolarWinds 2020：更新鏈被濫用" data-link-desc="合法更新流程遭植入後，攻擊者如何長期潛伏與橫向擴散">SolarWinds 2020 Sunburst</a></td>
          <td>Mandiant 揭露 IoC 後 Applied Threat Intel 自動 push、Curated Detection 對應規則自動 enable、客戶不需要手動 onboard rule</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/data-exfiltration/snowflake-2024-credential-abuse/" data-link-title="7.R7.4.2 Snowflake 2024：憑證濫用與資料竊取" data-link-desc="外洩憑證與 MFA 缺口如何在資料平台形成高風險外送事件">Snowflake 2024 Credential Abuse</a></td>
          <td>YARA-L 表達「query 體積 / 跨 schema scan / 來源 IP baseline」三軸 correlation rule；Entity Graph 聚合 credential / IP / data warehouse account 視覺化異常擴散（公開 UNC5537 跨客戶模式屬案例外延伸）</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/blue-team/detection-engineering-lifecycle/" data-link-title="7.B5 Detection Engineering Lifecycle" data-link-desc="把偵測規則視為可維護資產，建立從來源、測試、調校到退場的完整生命週期">Detection Engineering Lifecycle (section)</a></td>
          <td>Curated Detection + 自家 YARA-L rule 走 propose → staging → promote lifecycle、Google Security Ops 內建 rule versioning + Git → API push</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/blue-team/alert-fatigue-and-signal-quality/" data-link-title="7.B10 Alert Fatigue and Signal Quality" data-link-desc="建立告警疲勞治理方法，讓訊號品質、分級一致性與處置效率同步提升">Alert Fatigue and Signal Quality (section)</a></td>
          <td>Risk Score multi-signal aggregation 是 alert fatigue 的工程化解法、跟 Splunk RBA 同類但 risk 傳遞走 Entity Graph、跨 entity 關係更細</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">7.13 偵測覆蓋率與訊號治理</a>、<a href="/blog/backend/07-security-data-protection/blue-team/detection-engineering-lifecycle/" data-link-title="7.B5 Detection Engineering Lifecycle" data-link-desc="把偵測規則視為可維護資產，建立從來源、測試、調校到退場的完整生命週期">Detection Engineering Lifecycle</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a>、<a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a>、<a href="/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &#43; CSPM &#43; CWS &#43; AAP &#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Security</a></li>
<li>下游：<a href="/blog/backend/07-security-data-protection/vendors/google-dlp/" data-link-title="Google DLP" data-link-desc="GCP 原生 Sensitive Data Protection：infoType discovery &#43; transformation (mask / FPE / tokenize / k-anonymity)、整合 BigQuery / GCS / Cloud SQL">Google DLP</a> / <a href="/blog/backend/07-security-data-protection/vendors/microsoft-purview/" data-link-title="Microsoft Purview" data-link-desc="Microsoft 跨 M365 / Azure / endpoint 的 data governance &#43; information protection &#43; DLP &#43; insider risk 統合平台、label-driven">Microsoft Purview</a>（DLP signal 進 Google Security Ops）</li>
<li>跨類：<a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google Cloud IAM</a>（GCP IAM log + Workload Identity Federation）、<a href="/blog/backend/07-security-data-protection/vendors/google-secret-manager/" data-link-title="Google Secret Manager" data-link-desc="GCP 原生 secret store、CMEK &#43; Workload Identity Federation 整合、rotation 走自寫 Cloud Function 而非 built-in Lambda">Google Secret Manager</a>（SOAR playbook 拉 API）、<a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a>（IdP log source）、<a href="/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &#43; DDoS &#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF</a>（WAF log + auto-block）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（alert → IR routing）、<a href="/blog/backend/04-observability/" data-link-title="模組四：可觀測性平台" data-link-desc="整理 log、metric、trace、dashboard 與 alert 的後端操作實務">4 observability</a>（log pipeline 共用判斷）</li>
<li>官方：<a href="https://cloud.google.com/security/products/security-operations">Google Security Operations Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>Locust</title><link>https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/locust/</link><pubDate>Fri, 15 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/locust/</guid><description>&lt;p>Locust 的核心責任是用 Python 表達高度自訂的使用者行為與 protocol client。它適合 Python 團隊、需要自訂 client、需要 distributed worker、或 scenario 邏輯比工具內建 sampler 更複雜的壓測流程。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Locust 適合把壓測寫成一般 Python 程式。當 workload model 需要呼叫 internal SDK、特殊 protocol、複雜資料準備、狀態機、隨機行為或自訂 client、Locust 可以直接使用 Python 生態來表達。底層架構是 &lt;em>master + worker&lt;/em> 分散式 swarm、worker 之間用 Gevent green-thread（非 OS thread）模擬大量並發 user、master 負責 spawn rate、aggregation 跟 Web UI。&lt;/p>
&lt;p>這個定位讓 Locust 接到 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/workload-modeling/" data-link-title="9.2 Workload Modeling" data-link-desc="把 production traffic shape 翻成可重播的壓測模型">9.2 Workload Modeling&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/bottleneck-localization/" data-link-title="9.5 瓶頸定位流程" data-link-desc="從 app 到 DB / cache / broker / 第三方 quota 的逐層瓶頸定位">9.5 瓶頸定位流程&lt;/a>。它能把特殊 client 與下游 dependency 放進同一個 user behavior、但也要求團隊處理 runner、資料與可重現性。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/k6/" data-link-title="k6" data-link-desc="用 scriptable scenario 建立 API、protocol 與 CI 友善壓測的效能工程工具">k6&lt;/a>（JS / Go runtime）比、Locust 用 Python 換到 &lt;em>自訂能力與生態相容&lt;/em>、但代價是單 worker capacity 低、CPU bound 容易先打到自己。跟 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/jmeter/" data-link-title="Apache JMeter" data-link-desc="用 GUI、plugin 與多 protocol sampler 承接企業壓測資產的效能工程工具">JMeter&lt;/a>（GUI / XML）比、Locust 偏 &lt;em>code-first 工程團隊&lt;/em>、scenario 直接走 Git review、不靠 GUI plugin 拼裝。跟 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/gatling/" data-link-title="Gatling" data-link-desc="用 JVM DSL、simulation 與 injection profile 表達複雜 scenario 的效能工程工具">Gatling&lt;/a>（Scala DSL）比、Locust 換到 &lt;em>Python team 友善 + 既有 domain library 重用&lt;/em>、但失去 JVM injection profile 的精細度與報表內建。&lt;/p>
&lt;p>關鍵張力：&lt;em>Python 表達力&lt;/em> ↔ &lt;em>runner 效能上限&lt;/em>。Python team 想 reuse domain library、staging fixture、API client 寫壓測腳本時 Locust 是首選；但要心裡有數 &lt;em>單 worker RPS 上限不高&lt;/em>、超過幾千 RPS 就要靠 worker scale-out、不是調 Locust 本身。&lt;/p>
&lt;h2 id="適用場景">適用場景&lt;/h2>
&lt;p>Python 團隊適合用 Locust 長期維護壓測。既有 domain library、API client、fixture、資料產生器與驗證 helper 都可以被壓測腳本重用。&lt;/p>
&lt;p>自訂 protocol 適合用 Locust。HTTP 之外、如果服務需要 gRPC、WebSocket、binary protocol、message broker client 或自家 SDK、Locust 可以直接接 Python library。&lt;/p>
&lt;p>Distributed load 適合用 Locust worker 擴展。當單機 Python runner 遇到 CPU 或 connection bottleneck、可以用 master / worker 拆開負載產生能力。&lt;/p></description><content:encoded><![CDATA[<p>Locust 的核心責任是用 Python 表達高度自訂的使用者行為與 protocol client。它適合 Python 團隊、需要自訂 client、需要 distributed worker、或 scenario 邏輯比工具內建 sampler 更複雜的壓測流程。</p>
<h2 id="服務定位">服務定位</h2>
<p>Locust 適合把壓測寫成一般 Python 程式。當 workload model 需要呼叫 internal SDK、特殊 protocol、複雜資料準備、狀態機、隨機行為或自訂 client、Locust 可以直接使用 Python 生態來表達。底層架構是 <em>master + worker</em> 分散式 swarm、worker 之間用 Gevent green-thread（非 OS thread）模擬大量並發 user、master 負責 spawn rate、aggregation 跟 Web UI。</p>
<p>這個定位讓 Locust 接到 <a href="/blog/backend/09-performance-capacity/workload-modeling/" data-link-title="9.2 Workload Modeling" data-link-desc="把 production traffic shape 翻成可重播的壓測模型">9.2 Workload Modeling</a> 與 <a href="/blog/backend/09-performance-capacity/bottleneck-localization/" data-link-title="9.5 瓶頸定位流程" data-link-desc="從 app 到 DB / cache / broker / 第三方 quota 的逐層瓶頸定位">9.5 瓶頸定位流程</a>。它能把特殊 client 與下游 dependency 放進同一個 user behavior、但也要求團隊處理 runner、資料與可重現性。</p>
<p>跟 <a href="/blog/backend/09-performance-capacity/vendors/k6/" data-link-title="k6" data-link-desc="用 scriptable scenario 建立 API、protocol 與 CI 友善壓測的效能工程工具">k6</a>（JS / Go runtime）比、Locust 用 Python 換到 <em>自訂能力與生態相容</em>、但代價是單 worker capacity 低、CPU bound 容易先打到自己。跟 <a href="/blog/backend/09-performance-capacity/vendors/jmeter/" data-link-title="Apache JMeter" data-link-desc="用 GUI、plugin 與多 protocol sampler 承接企業壓測資產的效能工程工具">JMeter</a>（GUI / XML）比、Locust 偏 <em>code-first 工程團隊</em>、scenario 直接走 Git review、不靠 GUI plugin 拼裝。跟 <a href="/blog/backend/09-performance-capacity/vendors/gatling/" data-link-title="Gatling" data-link-desc="用 JVM DSL、simulation 與 injection profile 表達複雜 scenario 的效能工程工具">Gatling</a>（Scala DSL）比、Locust 換到 <em>Python team 友善 + 既有 domain library 重用</em>、但失去 JVM injection profile 的精細度與報表內建。</p>
<p>關鍵張力：<em>Python 表達力</em> ↔ <em>runner 效能上限</em>。Python team 想 reuse domain library、staging fixture、API client 寫壓測腳本時 Locust 是首選；但要心裡有數 <em>單 worker RPS 上限不高</em>、超過幾千 RPS 就要靠 worker scale-out、不是調 Locust 本身。</p>
<h2 id="適用場景">適用場景</h2>
<p>Python 團隊適合用 Locust 長期維護壓測。既有 domain library、API client、fixture、資料產生器與驗證 helper 都可以被壓測腳本重用。</p>
<p>自訂 protocol 適合用 Locust。HTTP 之外、如果服務需要 gRPC、WebSocket、binary protocol、message broker client 或自家 SDK、Locust 可以直接接 Python library。</p>
<p>Distributed load 適合用 Locust worker 擴展。當單機 Python runner 遇到 CPU 或 connection bottleneck、可以用 master / worker 拆開負載產生能力。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>Locust 在壓測 stack 中承擔哪一段（user behavior modeling / load generation / distributed swarm）、哪些要外接（<a href="/blog/backend/04-observability/" data-link-title="模組四：可觀測性平台" data-link-desc="整理 log、metric、trace、dashboard 與 alert 的後端操作實務">Prometheus / Grafana</a> 觀測 worker 自身、APM 看目標 saturation）</li>
<li>User class / task weight / on_start lifecycle 的 ownership 設計（誰寫 locustfile、誰 review、誰調 spawn rate）</li>
<li>Distributed master-worker 部署的容量規劃（單 worker user 上限、worker 數量計算、target RPS 對應 worker count）</li>
<li>何時用 Locust、何時走 k6 / JMeter / Gatling 的取捨</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Locust 壓測是否健康、最少看四件事：</p>
<ul>
<li><strong>User class 設計</strong>：每個 <code>HttpUser</code> / <code>User</code> subclass 是不是一個明確的 <em>persona</em>（mobile user / API client / admin user）、<code>wait_time</code> 是否反映真實使用者間隔（不是 0 拼最大 RPS、是 <code>between(1, 5)</code> 模擬 think time）、user state 是否在 instance 內封閉</li>
<li><strong>Task 比例</strong>：<code>@task(weight)</code> 數字是否對應 production traffic mix（80% read / 15% write / 5% admin、不是每個 endpoint 等比例）、weight 是否走版控 review</li>
<li><strong>on_start lifecycle</strong>：login / token fetch / session bootstrap 是否寫在 <code>on_start</code>（每個 user 一次）、不是寫在 <code>@task</code> 裡（每個 request 都重做）— 寫錯位置會讓 auth endpoint 變成主要 traffic</li>
<li><strong>Distributed master-worker</strong>：worker 數量是否夠（單 worker 跑幾千 user 後 CPU 會先打死、不是目標服務先死）、master 是否獨立機器（master 也跑 user 時 aggregation 跟 Web UI 會卡）、<code>--expect-workers</code> 是否設、worker sync drift 是否觀察</li>
</ul>
<p>四件事任一缺失、就是壓測證據可信度的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>locustfile 結構</strong>：locustfile.py 是 Python module、定義 <code>User</code> / <code>HttpUser</code> subclass、每個 user 有 <code>wait_time</code>、若干 <code>@task(weight)</code> method、<code>on_start</code> / <code>on_stop</code> lifecycle hook。執行用 <code>locust -f locustfile.py --host=https://target</code> 起 Web UI、或 <code>locust --headless -u 1000 -r 100 -t 10m</code> 在 CI 跑無 UI 模式。locustfile 應該走 Git review、不是 GUI 改完就跑。</p>
<p><strong>Task weight / wait_time 設計</strong>：weight 是 <em>相對權重</em>、不是百分比 —<code>@task(8)</code> + <code>@task(2)</code> 等於 80% / 20%。<code>wait_time = between(1, 5)</code> 在每個 task 之間等 1-5 秒、模擬 think time；若要拚最大 RPS 用 <code>constant(0)</code>、但同時要意識到這就不是 user behavior 模型、是 <em>throughput probe</em>。</p>
<p><strong>on_start vs @task 的邊界</strong>：<code>on_start(self)</code> 每個 user instance 啟動時跑一次、適合做 login、token fetch、cache warm、fixture lookup；<code>@task</code> 是 user 行為主迴圈、每次選一個 task 跑。把 login 寫在 <code>@task</code> 是常見錯誤、會讓 IdP 變成主壓力來源、不是目標 API。</p>
<p><strong>Gevent-based concurrency</strong>：Locust 用 <a href="https://www.gevent.org/">gevent</a> 的 green-thread 模擬大量 concurrent user、不是 OS thread。意義是單 worker 可以跑幾千個 <em>user</em>、但 CPU bound 工作（JSON serialization、加密、本地計算）會 <em>blocking</em> 整個 worker 的 event loop。<code>gevent.monkey.patch_all()</code> 要在 import 第一行、否則 socket / time / ssl 不會被 patch、blocking call 會卡死 swarm。</p>
<p><strong>Distributed master-worker</strong>：單機到極限時開 distributed — <code>locust --master</code> 起 master、<code>locust --worker --master-host=master.example.com</code> 起 worker。Master 負責 Web UI、spawn rate 控制、result aggregation、stat 收集；worker 負責跑 user。Master 不該跑 user（會跟 aggregation 搶 CPU、stat 失真）。worker 數量計算：先單 worker 拉到 CPU 80% 看能撐多少 user、目標 user 數除這個值 + 20% buffer。</p>
<p><strong>Custom load shape</strong>：除了固定 <code>-u 1000</code>、Locust 支援 <code>LoadTestShape</code> subclass 寫 <em>時間軸負載曲線</em> — spike test（瞬間 0 → 5000 user）、ramp test（線性爬升）、wave test（週期性高低交替）、step test（階梯式增加）。<code>tick()</code> method 每秒回傳 <code>(user_count, spawn_rate)</code>。用 custom shape 才能模擬 <a href="/blog/backend/09-performance-capacity/cases/seatgeek-virtual-waiting-room/" data-link-title="9.C16 SeatGeek：DynamoDB &#43; Lambda 打造的虛擬等候室" data-link-desc="SeatGeek 用 DynamoDB 4 張表 &#43; Lambda Bouncer 實作 flash-sale 限流排隊機制、取代第三方 waiting room 服務">9.C16 SeatGeek waiting room</a> 那種 ticket drop 瞬間衝擊。</p>
<p><strong>Prometheus exporter / 觀測</strong>：Locust 內建 stat 只是 in-memory 的 p50 / p95 / p99 / RPS、結束就消失。長期觀測接 <a href="https://github.com/ContainerSolutions/locust_exporter">locust-prometheus-exporter</a>（或 <code>--csv result.csv</code> 自己抓）、把 metric 推到 <a href="/blog/backend/04-observability/" data-link-title="模組四：可觀測性平台" data-link-desc="整理 log、metric、trace、dashboard 與 alert 的後端操作實務">Prometheus</a> + Grafana。<strong>worker 自身的 CPU / memory / network</strong> 一定要同時觀測、不然分不出是目標 saturation 還是 worker 已死。</p>
<p><strong>Locust Cloud（managed SaaS）</strong>：2024 後 Locust 推官方 <a href="https://docs.locust.cloud/">Locust Cloud</a>、託管 master + worker + result storage、付費換 ops 成本。自管 master-worker 對 CI / staging 是合理的；production 等級的 scale test（10k+ concurrent user）跑一次要拉幾十台 worker、用 Cloud 省 infra ops 是合理 trade-off。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Locust</th>
          <th>k6</th>
          <th>JMeter</th>
          <th>Gatling</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>腳本語言</td>
          <td>Python（generic）</td>
          <td>JavaScript (k6 runtime)</td>
          <td>XML / GUI / Groovy</td>
          <td>Scala DSL（也支援 Java / Kotlin）</td>
      </tr>
      <tr>
          <td>Runtime</td>
          <td>Python + Gevent green-thread</td>
          <td>Go-based、單 binary、低 overhead</td>
          <td>JVM、heavy</td>
          <td>JVM、async actor model</td>
      </tr>
      <tr>
          <td>單 worker capacity</td>
          <td>中低（Python overhead、千級 user）</td>
          <td>高（Go runtime、萬級 VU 單機）</td>
          <td>中（JVM tuning 後可用）</td>
          <td>高（Akka actor、效能好）</td>
      </tr>
      <tr>
          <td>Distributed mode</td>
          <td>內建 master-worker</td>
          <td>內建 k6 Cloud / k6 Operator</td>
          <td>內建 master-slave</td>
          <td>Gatling Enterprise（前 FrontLine）</td>
      </tr>
      <tr>
          <td>User behavior 彈性</td>
          <td>高 — 一般 Python、任意 library</td>
          <td>中 — JS 但 k6 runtime 受限</td>
          <td>中 — GUI 拼裝 + plugin</td>
          <td>中高 — Scala DSL 表達 simulation</td>
      </tr>
      <tr>
          <td>Custom protocol</td>
          <td>強 — 接任何 Python library</td>
          <td>強 — 有 gRPC / WS / Kafka extension</td>
          <td>強但繁瑣 — plugin 生態廣</td>
          <td>中 — 主要 HTTP / WS</td>
      </tr>
      <tr>
          <td>CI / headless</td>
          <td><code>--headless</code> 支援</td>
          <td>CI-first design</td>
          <td>non-GUI mode 支援</td>
          <td>內建支援</td>
      </tr>
      <tr>
          <td>Report / UI</td>
          <td>Web UI 即時 + CSV 匯出</td>
          <td>k6 Cloud / Grafana / 簡 stdout</td>
          <td>GUI listener / HTML report</td>
          <td>HTML report 內建、視覺豐富</td>
      </tr>
      <tr>
          <td>學習曲線</td>
          <td>緩（Python team）/ 陡（非 Python）</td>
          <td>中 — JS-style scripting</td>
          <td>緩（GUI）/ 陡（深度 tuning）</td>
          <td>陡 — Scala 語法</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>Python team + 自訂 behavior / client</td>
          <td>DevOps + CI / 標準 HTTP / 高 RPS 單機</td>
          <td>非工程角色協作 / legacy enterprise</td>
          <td>JVM team + 精細 injection profile</td>
      </tr>
      <tr>
          <td>退場成本</td>
          <td>低 — Python 腳本可移植</td>
          <td>中 — k6 runtime 綁定</td>
          <td>中 — XML jmx 不易他移</td>
          <td>中 — Scala DSL 綁定</td>
      </tr>
  </tbody>
</table>
<p>選 Locust 的核心訴求：<em>Python team + custom user behavior + 既有 domain library 重用</em>、且能投入 worker scale-out 預算（單 worker capacity 低、要靠分散式補）+ scenario 走 Git review 不靠 GUI。標準 HTTP 高 RPS 單機壓測直接走 k6 更快、非工程角色協作壓測走 JMeter、JVM team 精細模擬走 Gatling。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Distributed Locust 的 master-worker swarm</strong>：production scale test 通常需要 10-100 個 worker。實作要點：worker 之間 <em>不要</em> 共享 state、shared resource 由 master 統一發（用 <a href="https://zeromq.org/">zeromq</a> message bus）；worker 加入 / 離開時 user 會 redistribute、避免 user index 當 unique key；worker 跨 region 跑時 <em>latency 來自 worker → target 不只是 target 內部</em>、要在 worker 本身的 region 對齊。</p>
<p><strong>Custom load shape（spike / wave / step）</strong>：<code>LoadTestShape.tick(self)</code> return <code>(user_count, spawn_rate)</code> tuple 每秒被叫一次。Spike test：前 60 秒 0 user、第 61 秒瞬間衝 5000、模擬 <a href="/blog/backend/09-performance-capacity/cases/seatgeek-virtual-waiting-room/" data-link-title="9.C16 SeatGeek：DynamoDB &#43; Lambda 打造的虛擬等候室" data-link-desc="SeatGeek 用 DynamoDB 4 張表 &#43; Lambda Bouncer 實作 flash-sale 限流排隊機制、取代第三方 waiting room 服務">9.C16 SeatGeek waiting room</a> 的 admission storm。Wave test：sine wave 在 1000-3000 user 之間振盪、測 autoscaling 反應速度。Step test：每 5 分鐘加 1000 user、觀察哪一階開始降級。custom shape 是 Locust 比 k6 強的點之一。</p>
<p><strong>跟 Prometheus exporter 整合</strong>：locust-prometheus-exporter 把 Locust stat 推到 Prometheus / Grafana、做長期 baseline、跨 test 比較、p99 退化偵測。實務上要在 dashboard 同時放 <em>Locust 內部 stat</em> + <em>worker host metric</em> + <em>目標服務 APM</em>、三層 stack 起來才能判讀是 runner 還是目標 saturation。</p>
<p><strong>Locust Cloud（managed SaaS）</strong>：2024+ 官方 SaaS、託管 master + worker + result + dashboard。trade-off：自管適合 CI / staging / 內網壓測（target 跑在內網時 Cloud 連不到）；Cloud 適合大規模一次性 scale test（拉 50 worker 跑 2 小時、跑完即停、不想自己 infra ops）。</p>
<h2 id="操作成本">操作成本</h2>
<p>Locust 的主要成本是 runner overhead 與分散式治理。Python runner 的效能上限要用 worker scale-out 解決；壓測結論要同時檢查目標服務 saturation 與 worker 本身 CPU、connection、network 是否已成瓶頸。</p>
<p>腳本工程成本來自自由度。Python 可以很快寫出複雜行為、也容易把測試資料、randomness、side effect、sleep 與 exception handling 寫散；團隊要維持 scenario structure、fixture、logging 與 artifact 標準。</p>
<p>自訂 client 成本來自校正。使用 SDK 或 custom protocol client 時、要確認 client retry、timeout、connection pool 與 serialization 行為是否接近 production、避免 runner 模擬出不存在的壓力形狀。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Worker CPU 100% 但目標服務閒</strong>：Python runner 先死、不是 target saturation — 加 worker 數量、或檢查 task 裡有沒有 CPU bound 的本地計算（大 JSON parse、加密、本地 fixture 生成）擠掉 event loop</li>
<li><strong>Gevent monkey-patch gotcha</strong>：<code>requests</code> / <code>psycopg2</code> / 自家 SDK 在第三方 library 內部 blocking call、整個 worker 卡住 — <code>gevent.monkey.patch_all()</code> 一定要寫在 import 第一行；無法 patch 的 C extension（如 native MySQL driver）改用 gevent-friendly client</li>
<li><strong>RPS 達不到目標 / 看起來像 target 慢</strong>：實際是 worker connection pool 耗盡、或 worker 本身網卡飽和 — 觀測 worker 本身的 TCP socket 數、netstat ESTABLISHED、network throughput；不要直接 blame target</li>
<li><strong>Distributed sync drift</strong>：worker 之間 user count 不平均、aggregation 顯示 RPS 抖動 — <code>--expect-workers=N</code> 確認 master 等所有 worker join 才開測；worker 跨 region 時 message bus latency 也會影響 sync</li>
<li><strong>on_start 在 @task 裡跑</strong>：壓測啟動瞬間打爆 auth endpoint、看到 IdP latency 飆高以為是 target — 把 login / token fetch 移到 <code>on_start</code>、每個 user 只做一次</li>
<li><strong>wait_time = 0 拼最大 RPS 結果結論奇怪</strong>：這已經不是 user behavior 是 throughput probe、p99 跟 production 對不上 — 改成 <code>between(1, 5)</code> 模擬 think time 或寫 custom shape</li>
<li><strong>Web UI 卡 / master CPU 100%</strong>：master 同時在跑 user + aggregation — <code>locust --master</code> 跟 worker 拆機器、master 不跑 user</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>標準 HTTP / 高 RPS 單機 / CI-first</td>
          <td><a href="/blog/backend/09-performance-capacity/vendors/k6/" data-link-title="k6" data-link-desc="用 scriptable scenario 建立 API、protocol 與 CI 友善壓測的效能工程工具">k6</a></td>
      </tr>
      <tr>
          <td>非工程角色協作 / GUI 拼裝</td>
          <td><a href="/blog/backend/09-performance-capacity/vendors/jmeter/" data-link-title="Apache JMeter" data-link-desc="用 GUI、plugin 與多 protocol sampler 承接企業壓測資產的效能工程工具">JMeter</a></td>
      </tr>
      <tr>
          <td>JVM team / 精細 injection profile</td>
          <td><a href="/blog/backend/09-performance-capacity/vendors/gatling/" data-link-title="Gatling" data-link-desc="用 JVM DSL、simulation 與 injection profile 表達複雜 scenario 的效能工程工具">Gatling</a></td>
      </tr>
      <tr>
          <td>極簡 HTTP probe / 命令列 one-shot</td>
          <td><a href="/blog/backend/09-performance-capacity/vendors/vegeta/" data-link-title="Vegeta" data-link-desc="用簡潔 CLI 與固定 rate HTTP attack 快速探測 latency、throughput 與 saturation 的效能工程工具">Vegeta</a></td>
      </tr>
      <tr>
          <td>Production traffic replay / shadow</td>
          <td><a href="/blog/backend/09-performance-capacity/vendors/goreplay/" data-link-title="GoReplay" data-link-desc="用 production HTTP traffic capture 與 replay 驗證真實請求形狀的效能工程工具">GoReplay</a> / <a href="/blog/backend/09-performance-capacity/vendors/service-mesh-mirroring/" data-link-title="Service Mesh Mirroring" data-link-desc="用 sidecar / proxy 層 mirror production traffic 到新版本或 shadow service 的 production validation 方式">Service Mesh Mirroring</a></td>
      </tr>
      <tr>
          <td>壓測結果回寫到效能工程 lifecycle</td>
          <td><a href="/blog/backend/09-performance-capacity/bottleneck-localization/" data-link-title="9.5 瓶頸定位流程" data-link-desc="從 app 到 DB / cache / broker / 第三方 quota 的逐層瓶頸定位">9.5 瓶頸定位流程</a>、<a href="/blog/backend/09-performance-capacity/load-test-tooling/" data-link-title="9.3 壓測工具選型" data-link-desc="k6 / JMeter / Gatling / Locust / Vegeta / Production Replay 的工程選型">9.3 壓測工具選型</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>locustfile 完整語法 reference、<code>User</code> 跟 <code>HttpUser</code> 的 attribute 細節</li>
<li>Locust Cloud 計費跟 quota 細節（看官方 docs）</li>
<li>gevent 跟 asyncio 的取捨（Locust 選了 gevent、不在本頁討論替代）</li>
<li>壓測證據怎麼歸檔（看 <a href="/blog/backend/04-observability/observability-evidence-package/" data-link-title="4.20 Observability Evidence Package" data-link-desc="把 log、metric、trace、audit 與資料品質限制包成可交接證據">9.7 evidence package</a> 通則）</li>
</ul>
<h2 id="evidence-package">Evidence Package</h2>
<p>Locust 結果應回寫到 evidence package。最小欄位包括 locustfile version、user class、task weight、spawn rate、worker count、client library version、target environment、p95 / p99、error rate、throughput、target saturation metric、known gap 與 owner。</p>
<table>
  <thead>
      <tr>
          <th>欄位</th>
          <th>Locust 證據來源</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Source</td>
          <td>locustfile、CSV / JSON result、dashboard link</td>
      </tr>
      <tr>
          <td>Time range</td>
          <td>test start / end</td>
      </tr>
      <tr>
          <td>Query link</td>
          <td>APM / metrics / logs 查詢連結</td>
      </tr>
      <tr>
          <td>Data quality</td>
          <td>user behavior coverage、fixture freshness</td>
      </tr>
      <tr>
          <td>Confidence</td>
          <td>worker capacity、client realism</td>
      </tr>
      <tr>
          <td>Known gap</td>
          <td>worker bottleneck、custom client 偏差、資料偏差</td>
      </tr>
  </tbody>
</table>
<p>Evidence package 的核心用途是區分目標瓶頸與 runner 瓶頸。Locust 分散式測試要同時保存 worker 數量、worker 資源、spawn rate 與 client behavior、讓 reviewer 知道壓力是否真的打到目標服務。</p>
<h2 id="案例回寫">案例回寫</h2>
<p>Locust 適合回寫需要高度自訂 user behavior 的案例。它可接 <a href="/blog/backend/09-performance-capacity/cases/fanduel-dual-peak-betting-streaming/" data-link-title="9.C28 FanDuel：體育直播 &#43; 投注的雙重峰值" data-link-desc="FanDuel 3.5M MAU、Super Bowl 期間擴容 5-10 倍、用 AWS Local Zones &#43; Wavelength &#43; Outposts 處理 20&#43; 州的雙重峰值">9.C28 FanDuel 雙峰 workload</a> 的投注行為模型、<a href="/blog/backend/09-performance-capacity/cases/seatgeek-virtual-waiting-room/" data-link-title="9.C16 SeatGeek：DynamoDB &#43; Lambda 打造的虛擬等候室" data-link-desc="SeatGeek 用 DynamoDB 4 張表 &#43; Lambda Bouncer 實作 flash-sale 限流排隊機制、取代第三方 waiting room 服務">9.C16 SeatGeek waiting room</a> 的 admission / token flow、<a href="/blog/backend/09-performance-capacity/cases/paypay-mobile-payment-messaging/" data-link-title="9.C26 PayPay：行動支付每日 3 億訊息的 DynamoDB 後端" data-link-desc="日本最大行動支付 PayPay 每日 3 億訊息、用 DynamoDB 處理通知與訊息功能、支撐次秒級反應">9.C26 PayPay mobile payment messaging</a> 的外部推送與下游 quota 模擬、<a href="/blog/backend/09-performance-capacity/cases/niantic-pokemon-go-fifty-x-surge-gcp/" data-link-title="9.C8 Niantic Pokémon GO：在 GCP 上承載 50 倍突發流量" data-link-desc="Pokémon GO 上線時實際流量達原始預估 50 倍、Google CRE 怎麼即時補容量">9.C8 Niantic Pokémon GO 50x surge</a> 的玩家移動 + 互動混合行為、以及 <a href="/blog/backend/09-performance-capacity/cases/zoom-covid-surge-dynamodb/" data-link-title="9.C18 Zoom：COVID 期間從 1000 萬到 3 億 DAU 的 30 倍突發" data-link-desc="Zoom 在 2020 年 COVID 爆發時、日活從 1000 萬衝到 3 億、用 DynamoDB 撐住會議後端">9.C18 Zoom COVID 30x surge</a> 的會議建立 / 加入 / 離開行為混合。</p>
<p>這些案例的重點是 domain behavior。Locust 頁引用案例時、要把 case 轉成 user class、task weight、custom client、downstream mock 與 worker capacity、再把總 RPS 放回這些行為條件下判讀 — 例如 Pokémon GO 玩家行為跟一般 web user 完全不同（持續 GPS 上報 + 偶發互動）、不能直接用 HTTP RPS 衡量；SeatGeek waiting room 要寫 <code>LoadTestShape</code> 模擬 ticket drop 瞬間衝擊、不是穩態 RPS。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/09-performance-capacity/workload-modeling/" data-link-title="9.2 Workload Modeling" data-link-desc="把 production traffic shape 翻成可重播的壓測模型">9.2 Workload Modeling</a></li>
<li>上游：<a href="/blog/backend/09-performance-capacity/load-test-tooling/" data-link-title="9.3 壓測工具選型" data-link-desc="k6 / JMeter / Gatling / Locust / Vegeta / Production Replay 的工程選型">9.3 壓測工具選型</a></li>
<li>上游：<a href="/blog/backend/09-performance-capacity/bottleneck-localization/" data-link-title="9.5 瓶頸定位流程" data-link-desc="從 app 到 DB / cache / broker / 第三方 quota 的逐層瓶頸定位">9.5 瓶頸定位流程</a></li>
<li>平行：<a href="/blog/backend/09-performance-capacity/vendors/k6/" data-link-title="k6" data-link-desc="用 scriptable scenario 建立 API、protocol 與 CI 友善壓測的效能工程工具">k6</a>、<a href="/blog/backend/09-performance-capacity/vendors/jmeter/" data-link-title="Apache JMeter" data-link-desc="用 GUI、plugin 與多 protocol sampler 承接企業壓測資產的效能工程工具">JMeter</a>、<a href="/blog/backend/09-performance-capacity/vendors/gatling/" data-link-title="Gatling" data-link-desc="用 JVM DSL、simulation 與 injection profile 表達複雜 scenario 的效能工程工具">Gatling</a>、<a href="/blog/backend/09-performance-capacity/vendors/vegeta/" data-link-title="Vegeta" data-link-desc="用簡潔 CLI 與固定 rate HTTP attack 快速探測 latency、throughput 與 saturation 的效能工程工具">Vegeta</a></li>
<li>跨類：<a href="/blog/backend/09-performance-capacity/vendors/goreplay/" data-link-title="GoReplay" data-link-desc="用 production HTTP traffic capture 與 replay 驗證真實請求形狀的效能工程工具">GoReplay</a>（production traffic replay 替代 synthetic load）</li>
<li>跨模組：<a href="/blog/backend/04-observability/" data-link-title="模組四：可觀測性平台" data-link-desc="整理 log、metric、trace、dashboard 與 alert 的後端操作實務">4 Observability</a>（worker 自身 + 目標 APM 雙觀測）</li>
<li>官方：<a href="https://docs.locust.io/">Locust documentation</a></li>
</ul>
]]></content:encoded></item><item><title>CockroachDB</title><link>https://tarrragon.github.io/blog/backend/01-database/vendors/cockroachdb/</link><pubDate>Wed, 13 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/01-database/vendors/cockroachdb/</guid><description>&lt;p>CockroachDB 是分散式 SQL、PostgreSQL wire protocol 相容、跨 region 強一致。設計理念接近 Spanner（線性化、跨 region &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/quorum/" data-link-title="Quorum" data-link-desc="分散式系統以多數節點同意作為提交或讀取有效性的門檻">quorum&lt;/a>），但採 HLC + Raft 而非 TrueTime hardware，是 open source + 跨雲可用的全球 OLTP 選擇。&lt;/p>
&lt;h2 id="教學路線distributed-sql-與跨雲一致性">教學路線：Distributed SQL 與跨雲一致性&lt;/h2>
&lt;p>CockroachDB 服務頁的教學目標是把 PostgreSQL-like 介面背後的 range sharding、Raft replication、serializable transaction、leaseholder 與 region placement 說清楚。讀者讀完後要能判斷 distributed SQL 何時能取代自管 sharding，何時會把 latency 與 retry 壓力推回應用層。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>學習段&lt;/th>
 &lt;th>核心問題&lt;/th>
 &lt;th>對應段落&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Distributed SQL&lt;/td>
 &lt;td>SQL 介面如何藏住 range sharding 與 Raft replication&lt;/td>
 &lt;td>定位、容量特性&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Serializable default&lt;/td>
 &lt;td>transaction retry、contention、latency 如何影響應用設計&lt;/td>
 &lt;td>容量規劃要點、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/isolation-level/" data-link-title="Isolation Level" data-link-desc="說明資料庫交易隔離級別如何影響並發讀寫結果">Isolation Level&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Region placement&lt;/td>
 &lt;td>multi-region table、leaseholder、survival goal 如何服務產品需求&lt;/td>
 &lt;td>適用場景、跟其他 vendor 的取捨&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Migration pressure&lt;/td>
 &lt;td>從 PostgreSQL / MySQL 或自管 sharding 過來時要檢查哪些差異&lt;/td>
 &lt;td>預計實作話題、案例對照&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>替代路由&lt;/td>
 &lt;td>何時留 PostgreSQL、用 Spanner、Aurora DSQL 或 application sharding&lt;/td>
 &lt;td>不適用場景、下一步路由&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="定位spanner-的開源--跨雲替代">定位：Spanner 的開源 / 跨雲替代&lt;/h2>
&lt;p>CockroachDB 跟 Spanner 解決同一個問題（跨 region 強一致 SQL）、但定位不同：&lt;/p>
&lt;ul>
&lt;li>Spanner：GCP managed service、用 TrueTime hardware&lt;/li>
&lt;li>CockroachDB：開源（雙授權）、可自管 + Cockroach Cloud、跨 AWS / GCP / Azure / on-prem、用 HLC + Raft&lt;/li>
&lt;/ul>
&lt;p>選 CockroachDB 的核心訴求：需要跨 region 強一致 SQL + 想避免雲商 lock-in、想自管或跨雲部署。&lt;/p>
&lt;p>詳見 &lt;a href="https://tarrragon.github.io/blog/backend/01-database/global-distributed-oltp/" data-link-title="1.11 全球分散式 OLTP" data-link-desc="Spanner / Aurora DSQL / Cosmos DB multi-region write / CockroachDB / TiDB 的全球一致性取捨">1.11 全球分散式 OLTP&lt;/a> 的 CockroachDB 段。&lt;/p>
&lt;h2 id="容量特性">容量特性&lt;/h2>
&lt;p>&lt;strong>節點即容量單位&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>跟 Spanner 同樣設計、節點數量決定容量&lt;/li>
&lt;li>每節點承擔 query + storage + replication&lt;/li>
&lt;li>線性擴展（理論）、實際依 query pattern&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>跨 region 配置&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>multi-region survival goal（zone-level / region-level）&lt;/li>
&lt;li>跨 region quorum 必要、決定 latency&lt;/li>
&lt;li>跟 Spanner 同樣的物理限制（跨洲 100ms+）&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Replication&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>Raft consensus per range&lt;/li>
&lt;li>預設 3-replica&lt;/li>
&lt;li>可配置每個 region 不同 replica count（Survival Goals）&lt;/li>
&lt;/ul>
&lt;h2 id="適用場景">適用場景&lt;/h2>
&lt;p>&lt;strong>1. 需要跨 region 強一致 SQL + 跨雲&lt;/strong>：&lt;/p></description><content:encoded><![CDATA[<p>CockroachDB 是分散式 SQL、PostgreSQL wire protocol 相容、跨 region 強一致。設計理念接近 Spanner（線性化、跨 region <a href="/blog/backend/knowledge-cards/quorum/" data-link-title="Quorum" data-link-desc="分散式系統以多數節點同意作為提交或讀取有效性的門檻">quorum</a>），但採 HLC + Raft 而非 TrueTime hardware，是 open source + 跨雲可用的全球 OLTP 選擇。</p>
<h2 id="教學路線distributed-sql-與跨雲一致性">教學路線：Distributed SQL 與跨雲一致性</h2>
<p>CockroachDB 服務頁的教學目標是把 PostgreSQL-like 介面背後的 range sharding、Raft replication、serializable transaction、leaseholder 與 region placement 說清楚。讀者讀完後要能判斷 distributed SQL 何時能取代自管 sharding，何時會把 latency 與 retry 壓力推回應用層。</p>
<table>
  <thead>
      <tr>
          <th>學習段</th>
          <th>核心問題</th>
          <th>對應段落</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Distributed SQL</td>
          <td>SQL 介面如何藏住 range sharding 與 Raft replication</td>
          <td>定位、容量特性</td>
      </tr>
      <tr>
          <td>Serializable default</td>
          <td>transaction retry、contention、latency 如何影響應用設計</td>
          <td>容量規劃要點、<a href="/blog/backend/knowledge-cards/isolation-level/" data-link-title="Isolation Level" data-link-desc="說明資料庫交易隔離級別如何影響並發讀寫結果">Isolation Level</a></td>
      </tr>
      <tr>
          <td>Region placement</td>
          <td>multi-region table、leaseholder、survival goal 如何服務產品需求</td>
          <td>適用場景、跟其他 vendor 的取捨</td>
      </tr>
      <tr>
          <td>Migration pressure</td>
          <td>從 PostgreSQL / MySQL 或自管 sharding 過來時要檢查哪些差異</td>
          <td>預計實作話題、案例對照</td>
      </tr>
      <tr>
          <td>替代路由</td>
          <td>何時留 PostgreSQL、用 Spanner、Aurora DSQL 或 application sharding</td>
          <td>不適用場景、下一步路由</td>
      </tr>
  </tbody>
</table>
<h2 id="定位spanner-的開源--跨雲替代">定位：Spanner 的開源 / 跨雲替代</h2>
<p>CockroachDB 跟 Spanner 解決同一個問題（跨 region 強一致 SQL）、但定位不同：</p>
<ul>
<li>Spanner：GCP managed service、用 TrueTime hardware</li>
<li>CockroachDB：開源（雙授權）、可自管 + Cockroach Cloud、跨 AWS / GCP / Azure / on-prem、用 HLC + Raft</li>
</ul>
<p>選 CockroachDB 的核心訴求：需要跨 region 強一致 SQL + 想避免雲商 lock-in、想自管或跨雲部署。</p>
<p>詳見 <a href="/blog/backend/01-database/global-distributed-oltp/" data-link-title="1.11 全球分散式 OLTP" data-link-desc="Spanner / Aurora DSQL / Cosmos DB multi-region write / CockroachDB / TiDB 的全球一致性取捨">1.11 全球分散式 OLTP</a> 的 CockroachDB 段。</p>
<h2 id="容量特性">容量特性</h2>
<p><strong>節點即容量單位</strong>：</p>
<ul>
<li>跟 Spanner 同樣設計、節點數量決定容量</li>
<li>每節點承擔 query + storage + replication</li>
<li>線性擴展（理論）、實際依 query pattern</li>
</ul>
<p><strong>跨 region 配置</strong>：</p>
<ul>
<li>multi-region survival goal（zone-level / region-level）</li>
<li>跨 region quorum 必要、決定 latency</li>
<li>跟 Spanner 同樣的物理限制（跨洲 100ms+）</li>
</ul>
<p><strong>Replication</strong>：</p>
<ul>
<li>Raft consensus per range</li>
<li>預設 3-replica</li>
<li>可配置每個 region 不同 replica count（Survival Goals）</li>
</ul>
<h2 id="適用場景">適用場景</h2>
<p><strong>1. 需要跨 region 強一致 SQL + 跨雲</strong>：</p>
<ul>
<li>multi-region active-active write</li>
<li>GCP-only（Spanner）或 AWS-only（Aurora DSQL）和部署策略不合</li>
<li>對應 <a href="/blog/backend/01-database/global-distributed-oltp/" data-link-title="1.11 全球分散式 OLTP" data-link-desc="Spanner / Aurora DSQL / Cosmos DB multi-region write / CockroachDB / TiDB 的全球一致性取捨">1.11 全球分散式 OLTP</a> 的選型決策</li>
</ul>
<p><strong>2. PostgreSQL wire protocol 相容路徑</strong>：</p>
<ul>
<li>既有 PostgreSQL 應用想升級到分散式</li>
<li>應用層改動小（保留 PostgreSQL driver / ORM）</li>
<li>注意：PostgreSQL 相容要以實際 query、extension 與 migration test 驗證</li>
</ul>
<p><strong>3. 自管 on-prem / hybrid</strong>：</p>
<ul>
<li>金融 / 受監管產業需要 on-prem</li>
<li>Spanner / Aurora DSQL 以 cloud service 為主</li>
<li>CockroachDB 可自管</li>
</ul>
<p><strong>4. 想避免單一 vendor 全球分散式 lock-in</strong>：</p>
<ul>
<li>開源 + 跨雲、可遷移性高</li>
<li>但企業版功能要付費（CockroachDB Cloud 或 Enterprise license）</li>
</ul>
<h2 id="不適用場景">不適用場景</h2>
<p><strong>1. single-region OLTP 夠用</strong>：</p>
<ul>
<li>90% 場景 PostgreSQL / Aurora 已夠</li>
<li>CockroachDB 有分散式 overhead（每個寫經 Raft）</li>
<li>替代：PostgreSQL、Aurora、MySQL</li>
</ul>
<p><strong>2. 極端高吞吐 single-query</strong>：</p>
<ul>
<li>CockroachDB 寫入有 Raft 開銷、單機吞吐 &lt; PostgreSQL</li>
<li>整體吞吐靠 scale-out 達成、單一 query latency 較高</li>
</ul>
<p><strong>3. 跨洲低延遲（&lt; 50ms）</strong>：</p>
<ul>
<li>跟 Spanner 同樣物理限制</li>
<li>跨洲 quorum 100ms+ 是物理成本</li>
</ul>
<p><strong>4. 預算極敏感的小 workload</strong>：</p>
<ul>
<li>CockroachDB 至少 3 個節點（Raft quorum）</li>
<li>跟 single-instance PostgreSQL 比較貴</li>
</ul>
<p><strong>5. 需要 PostgreSQL 進階特性</strong>：</p>
<ul>
<li>部分 PostgreSQL extension 或行為需要替代方案</li>
<li>partial index、exclusion constraint 等可能缺</li>
</ul>
<h2 id="跟其他-vendor-的取捨">跟其他 vendor 的取捨</h2>
<p><strong>vs Spanner（GCP）</strong>：</p>
<ul>
<li>CockroachDB：開源、跨雲、可自管</li>
<li>Spanner：GCP-only、TrueTime hardware、Google 規模驗證</li>
<li>選 CockroachDB：跨雲 / on-prem 需求</li>
<li>選 Spanner：GCP 生態 + managed operation + Google 規模驗證的成熟度</li>
</ul>
<p><strong>vs Aurora DSQL（AWS 2024）</strong>：</p>
<ul>
<li>CockroachDB：跨雲、生產驗證較久</li>
<li>Aurora DSQL：AWS-only、serverless、新（2024）</li>
<li>選 CockroachDB：跨雲、想避免 AWS lock-in</li>
<li>選 Aurora DSQL：AWS 生態 + 已用 PostgreSQL + serverless 訴求</li>
</ul>
<p><strong>vs TiDB</strong>：</p>
<ul>
<li>CockroachDB：PostgreSQL wire、英語 / 歐美生態深</li>
<li>TiDB：MySQL wire、亞洲生態深、HTAP（OLTP + OLAP 同庫）</li>
<li>選 CockroachDB：PostgreSQL 應用、跨雲</li>
<li>選 TiDB：MySQL 應用、需要 OLAP 整合、亞洲市場</li>
</ul>
<p><strong>vs PostgreSQL（傳統）</strong>：</p>
<ul>
<li>CockroachDB：分散式、跨 region 強一致</li>
<li>PostgreSQL：single-primary、跨 region 是 async replication</li>
<li>選 CockroachDB：需要跨 region 強一致</li>
<li>選 PostgreSQL：single-region 夠用（90% 場景）</li>
</ul>
<p><strong>vs Aurora（single-region scaling）</strong>：</p>
<ul>
<li>CockroachDB：multi-region 強一致</li>
<li>Aurora：single-region scaling、跨 region 是 async Global Database</li>
<li>選 CockroachDB：需要 multi-region write</li>
<li>選 Aurora：single-region scaling + AWS 生態</li>
</ul>
<p><strong>vs MySQL + Vitess（self-managed distributed MySQL）</strong>：</p>
<ul>
<li>CockroachDB：PostgreSQL wire、transparent sharding（range-based）、跨 region 強一致內建</li>
<li>MySQL + Vitess：MySQL wire、application 層配 keyspace + shard key、跨 region 靠 application + async replication</li>
<li>選 CockroachDB：PostgreSQL 應用 + transparent multi-region + 想避開 Vitess operation burden</li>
<li>選 MySQL + Vitess：MySQL 應用 + 有 DBA 養 Vitess + 已是 YouTube / Slack 規模</li>
</ul>
<h2 id="容量規劃要點">容量規劃要點</h2>
<p><strong>1. Node count + zone / region 配置</strong>：</p>
<ul>
<li>至少 3 個節點（Raft quorum）</li>
<li>multi-region 通常 9+ 節點（3 region × 3 replica）</li>
<li>Survival Goals 配置決定每 region 復原能力</li>
</ul>
<p><strong>2. Range（CockroachDB 的 partition）</strong>：</p>
<ul>
<li>跟 DynamoDB partition、Spanner split 同類</li>
<li>CockroachDB 自動 split 大 range</li>
<li>application 主要管理 query locality、transaction retry 與 region placement</li>
</ul>
<p><strong>3. Locality 配置</strong>：</p>
<ul>
<li>跟 Spanner 一樣可以指定 voting region</li>
<li>寫入 locality 影響跨 region latency</li>
</ul>
<p><strong>4. Backup / restore</strong>：</p>
<ul>
<li>CockroachDB 原生 backup 支援 cluster-level snapshot</li>
<li>增量 backup 支援</li>
<li>注意：incremental backup chain 可能很長、定期 full backup</li>
</ul>
<p><strong>5. Self-managed vs Cockroach Cloud</strong>：</p>
<ul>
<li>Self-managed：需要 ops team、可跨雲 / on-prem</li>
<li>Cockroach Cloud：managed、跨 cloud（AWS / GCP / Azure）、可考慮 serverless tier</li>
</ul>
<h2 id="deep-article已完成">Deep article（已完成）</h2>
<p>本批 deep article 覆蓋 CockroachDB 從 consensus 機制、multi-region 配置到 managed 形態選型的核心 production 議題：</p>
<table>
  <thead>
      <tr>
          <th>主題</th>
          <th>文章</th>
          <th>對應 production 議題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>HLC + per-range Raft、leaseholder、寫入 latency 結構</td>
          <td><a href="hlc-raft-consensus/">hlc-raft-consensus</a></td>
          <td>DoorDash Aurora 撞牆訊號（1.636 M QPS）、Netflix 380+ artery of small DBs 容量規劃顆粒</td>
      </tr>
      <tr>
          <td>SURVIVE ZONE / REGION FAILURE 倒推、業務 SLO 決定副本拓樸</td>
          <td><a href="survival-goals/">survival-goals</a></td>
          <td>Hard Rock RPO=0 倒推、Netflix Gaming 48-node 跨 4 region「為求 survival 而非 latency」反直覺</td>
      </tr>
      <tr>
          <td>Serializable default、application 必須包 retry loop、SAVEPOINT 語法</td>
          <td><a href="transaction-retry-pattern/">transaction-retry-pattern</a></td>
          <td>PG → CockroachDB application contract 重塑、5 種 retry failure mode（跨 case 合成 frame）</td>
      </tr>
      <tr>
          <td>REGIONAL BY ROW / TABLE / GLOBAL、跨州合規 + 邏輯一個 cluster</td>
          <td><a href="locality-aware-schema/">locality-aware-schema</a></td>
          <td>Hard Rock 跨 8 州 sportsbook + AWS Outposts、Outposts 是合規工具不是 latency 工具反直覺判讀</td>
      </tr>
      <tr>
          <td>三種 table locality 的選擇與 latency / 一致性取捨、選錯重配代價</td>
          <td><a href="multi-region-table-config/">multi-region-table-config</a></td>
          <td>Netflix multi-region 動機為 survival 非 latency、Hard Rock row-level 歸屬 + 單一邏輯 cluster</td>
      </tr>
      <tr>
          <td>Cockroach Cloud serverless vs dedicated、RU 計費、冷啟動 / scale</td>
          <td><a href="cloud-serverless/">cloud-serverless</a></td>
          <td>Netflix 需 Platform Team 反向 = managed 入口、Hard Rock 可預測賽季擴縮 vs serverless 突發甜蜜區</td>
      </tr>
      <tr>
          <td>Distributed SQL 三選一決策樹：撞牆訊號分型 + 七問題</td>
          <td><a href="aurora-dsql-spanner-decision-tree/">aurora-dsql-spanner-decision-tree</a></td>
          <td>DB4 cross-vendor entry：DoorDash / Netflix / Hard Rock driver path 識別 + sizing barrier</td>
      </tr>
  </tbody>
</table>
<p>DB4 cross-vendor entry：先看 <a href="aurora-dsql-spanner-decision-tree/">aurora-dsql-spanner-decision-tree</a> 識別 driver path、再進個別 vendor 深度。</p>
<p>multi-region-table-config 與 locality-aware-schema 切分：前者主寫「三種 table locality 怎麼選 + 選錯重配代價」、後者主寫「schema 怎麼配合 locality 設計（合規 boundary、跨州業務邏輯、Outposts 拓樸）」、兩者互補、survival goal 機制以 survival-goals 為 SSoT。</p>
<h2 id="後續擴充仍待補">後續擴充（仍待補）</h2>
<ul>
<li>PostgreSQL 相容性 audit（partial index / extension / SQL 行為 gap 清單）</li>
<li>Backup / restore 與 PITR 操作（incremental chain 管理、restore 演練）</li>
<li>Changefeed / CDC 配置（CockroachDB 原生 CDC 到 Kafka / sink）</li>
</ul>
<blockquote>
<p>「從 PostgreSQL 遷到 CockroachDB（playbook）」已由 <a href="/blog/backend/01-database/vendors/postgresql/migrate-to-cockroachdb/" data-link-title="PostgreSQL → CockroachDB：三維皆 High 的多重歸類 migration" data-link-desc="PostgreSQL → CockroachDB 是 Schema / Operational / Paradigm 三維皆 High 的 multi-axis migration、實證 [#127](/report/content-structure-by-max-diff-dimension/) 的「多重歸類跟 tie-breaking」規則；主結構走 Type E paradigm shift、Schema 差 &#43; Operational redesign 抽出獨立段；涵蓋 transaction model 重設計、SQL dialect gap、5 個 production 踩雷">PostgreSQL → CockroachDB migration</a> 涵蓋、不再列為待補。</p></blockquote>
<h2 id="anti-recommendation-與升級路由">Anti-recommendation 與升級路由</h2>
<p>CockroachDB 的 PostgreSQL-like 介面會降低導入門檻，但 distributed SQL 的成本會出現在 transaction retry、range lease、multi-region latency 與操作拓樸。這一段先說何時維持 PostgreSQL / Aurora，再說何時升級 CockroachDB、Cockroach Cloud、Spanner、Aurora DSQL 或 Vitess。</p>
<table>
  <thead>
      <tr>
          <th>機制 / 路線</th>
          <th>維持簡單設計的條件</th>
          <th>升級訊號</th>
          <th>主要引用路徑</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>PostgreSQL / Aurora</td>
          <td>single-region primary、async DR、read replica 已滿足需求</td>
          <td>multi-region write、region failure survival、跨雲部署是硬需求</td>
          <td><a href="/blog/backend/01-database/vendors/postgresql/" data-link-title="PostgreSQL" data-link-desc="多用途 OLTP 主流關聯式資料庫、MVCC、豐富 SQL 特性、是 Aurora / Cosmos DB / Spanner / CockroachDB / Aurora DSQL 的相容目標">PostgreSQL vendor</a>、<a href="/blog/backend/01-database/vendors/aurora/" data-link-title="AWS Aurora" data-link-desc="AWS managed PostgreSQL / MySQL、storage / compute 分離、&#43;75% 效能改善的 production 證據">Aurora vendor</a></td>
      </tr>
      <tr>
          <td>CockroachDB single-region</td>
          <td>需要水平擴容或 future multi-region，但目前在單區運作</td>
          <td>Raft overhead 讓成本高於 PostgreSQL，且沒有 region requirement</td>
          <td><a href="/blog/backend/knowledge-cards/distributed-sql/" data-link-title="Distributed SQL" data-link-desc="把 SQL 與交易語意延伸到多節點與多區域的資料庫形態">Distributed SQL</a></td>
      </tr>
      <tr>
          <td>CockroachDB multi-region</td>
          <td>跨雲 / on-prem、PostgreSQL wire、strong consistency 是主需求</td>
          <td>跨洲 p99 目標過低、transaction retry 影響 user flow</td>
          <td><a href="/blog/backend/knowledge-cards/quorum/" data-link-title="Quorum" data-link-desc="分散式系統以多數節點同意作為提交或讀取有效性的門檻">Quorum</a>、<a href="/blog/backend/knowledge-cards/latency-budget/" data-link-title="Latency Budget" data-link-desc="把 user-perceived latency 拆到每個 stage 的配額、反推架構選擇">Latency Budget</a></td>
      </tr>
      <tr>
          <td>Cockroach Cloud</td>
          <td>團隊仍能自管 Raft、backup、upgrade、node failure</td>
          <td>想把 operation transfer 給 vendor</td>
          <td><a href="/blog/backend/knowledge-cards/rto/" data-link-title="RTO" data-link-desc="說明恢復時間目標如何約束事故回復策略">RTO</a>、<a href="/blog/backend/knowledge-cards/rpo/" data-link-title="RPO" data-link-desc="說明恢復點目標如何定義可接受資料損失範圍">RPO</a></td>
      </tr>
      <tr>
          <td>Spanner</td>
          <td>跨雲或自管是硬需求</td>
          <td>GCP managed、TrueTime 成熟度、Google scale evidence 是主訴求</td>
          <td><a href="/blog/backend/01-database/vendors/spanner/" data-link-title="Google Cloud Spanner" data-link-desc="全球分散式 strong-consistency OLTP、TrueTime API、線性擴展到 10 億 req/sec">Spanner vendor</a></td>
      </tr>
      <tr>
          <td>Aurora DSQL</td>
          <td>跨雲 / on-prem 是硬需求</td>
          <td>AWS-only、serverless、PostgreSQL 相容與 AWS operation model 是主訴求</td>
          <td><a href="/blog/backend/01-database/vendors/postgresql/migrate-to-aurora-dsql/" data-link-title="PostgreSQL → Aurora DSQL Migration：PG wire-compatible Distributed SQL 的 Paradigm Shift" data-link-desc="Aurora DSQL（2024-12 re:Invent preview / 2025-05 GA）是 AWS 推的 PG wire-compatible *active-active distributed SQL*、跟 self-managed PG / Aurora PG 不同 paradigm（OCC &#43; snapshot isolation &#43; multi-region strong consistency）。Migration 結構是 *protocol drop-in &#43; paradigm shift*：app SQL 不太改、但 transaction retry / extension 缺位 / 多 region 一致性需重設計。本文走 DSQL vs Aurora PG vs self-managed PG 三軸對比、為什麼遷的三條 driver（global write / operational zero-touch / region resiliency）、Type E phased plan、5 production 踩雷（transaction retry 沒處理 / extension 缺位 / sequence throughput 限制 / Aurora PG 直升 DSQL 不可行 / region failover semantic）、跟 PG → Aurora 跟 PG → CockroachDB 對比">PG → Aurora DSQL Migration</a></td>
      </tr>
      <tr>
          <td>MySQL + Vitess</td>
          <td>PostgreSQL-like SQL 與 strong consistency 是主需求</td>
          <td>MySQL ecosystem、application sharding 與 Vitess ops 已成熟</td>
          <td><a href="/blog/backend/01-database/vendors/mysql/vitess-sharding/" data-link-title="MySQL Vitess Sharding：VTGate / VTTablet / VReplication / VSchema 四件套協作" data-link-desc="Vitess 不只是 MySQL sharding proxy、是 4 個 component 協作的完整 sharding 系統 — VTGate（query routing layer）、VTTablet（per-MySQL agent）、VReplication（跨 shard 資料移動）、VSchema（sharding metadata）。本文走 4 件套各自責任、keyspace / shard / tablet 架構、shard key 設計（Vindex）、配置 step-by-step、5 production 踩雷（cross-shard transaction / VStream lag / Vindex 不均勻 / resharding 切流 / VReplication 卡住）、跟自管 sharding 跟 PlanetScale 的對比">MySQL Vitess Sharding</a>、<a href="/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">Database Sharding</a></td>
      </tr>
  </tbody>
</table>
<p>CockroachDB 的簡單路徑是先證明 distributed SQL 的價值大於 retry 與 latency 成本。若 workload 仍是 single-region OLTP，PostgreSQL / Aurora 通常提供更低成本；若跨 region 寫入與一致性是產品承諾，CockroachDB 才成為主要候選。</p>
<p>Transaction retry 的升級路徑要進入 application contract。Serializable default 能保護一致性，但 retry 會把 idempotency、timeout、user-visible latency 與 workflow compensation 帶回應用層；這些條件要在 migration playbook 前先盤點。</p>
<h2 id="已知-limitation-與後續路由">已知 limitation 與後續路由</h2>
<p>CockroachDB overview 目前完成 distributed SQL 判斷。下一輪 deep article / playbook 應補 HLC + Raft、range / leaseholder、multi-region table locality、transaction retry pattern、PostgreSQL compatibility audit、Cockroach Cloud operation 與 PostgreSQL → CockroachDB migration。</p>
<h2 id="案例對照">案例對照</h2>
<p>CockroachDB 在 09 案例庫已有三條直接 case 軸線（OLTP 寫入擴展、polyglot 補位、合規邊界），另外兩條對比參考軸線（Spanner 設計理念、受監管金融）一併保留。</p>
<h3 id="direct-casecockroachdb-為主角">Direct case（CockroachDB 為主角）</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>主要工程議題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/cases/doordash-cockroachdb-orders-platform/" data-link-title="9.C39 DoorDash：Aurora Postgres 寫入瓶頸 → CockroachDB 多主寫入" data-link-desc="DoorDash 從 Aurora Postgres 遷到 CockroachDB、解 1.6 M QPS 單主寫入瓶頸、外送平台爆量壓力下重做 OLTP 拓樸">9.C39 DoorDash</a></td>
          <td>Aurora Postgres single-primary 1.6 M QPS 撞牆 → multi-primary 解寫入</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/cases/netflix-cockroachdb-multi-region-fleet/" data-link-title="9.C40 Netflix：380&#43; CockroachDB cluster 的 multi-active 拓樸艦隊" data-link-desc="Netflix 把 Cassandra 不夠用的 transactional workload 移到 CockroachDB、380&#43; cluster / 60&#43; 跨 region、含 Open Connect、studio cloud drive、gaming control plane">9.C40 Netflix</a></td>
          <td>380+ cluster 艦隊、Cassandra 不夠用的 transactional workload 補位</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/cases/hard-rock-digital-cockroachdb-sports-betting/" data-link-title="9.C41 Hard Rock Digital：CockroachDB on AWS Outposts、Wire Act 合規 &#43; 跨州單一邏輯 DB" data-link-desc="Hard Rock Digital 用 CockroachDB 跨 AWS Outposts &#43; US-East-1、Wire Act 強制資料留州、單一邏輯 DB 解多州 sportsbook、100 node 32 vCPU 撐 Super Bowl">9.C41 Hard Rock Digital</a></td>
          <td>AWS Outposts + 跨州單一邏輯 DB、Wire Act 合規 + 賽季型擴縮容</td>
      </tr>
  </tbody>
</table>
<h3 id="對比參考案例">對比參考案例</h3>
<table>
  <thead>
      <tr>
          <th>案例（對比參考）</th>
          <th>跟 CockroachDB 的關係</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/cases/spanner-planetary-scale-database-gcp/" data-link-title="9.C10 Cloud Spanner：每秒 10 億請求的全球一致性資料庫" data-link-desc="Google Cloud Spanner 內部峰值 10 億 req/sec、跨地區強一致 — 全球分散式 OLTP 容量參考">9.C10 Spanner</a></td>
          <td>設計理念對標、CockroachDB 是開源版本</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/cases/standard-chartered-aurora-banking/" data-link-title="9.C14 Standard Chartered：受監管銀行的 Aurora 4000 TPS 容量提升" data-link-desc="Standard Chartered 銀行遷移到 Aurora 後吞吐量提升 10 倍至 4000 TPS、跨 7 個受監管市場">9.C14 Standard Chartered</a></td>
          <td>受監管金融、CockroachDB 可作為 on-prem 替代候選</td>
      </tr>
  </tbody>
</table>
<p>CockroachDB direct case 的讀法是「寫入擴展（DoorDash）→ polyglot 補位（Netflix）→ 合規邊界（Hard Rock Digital）」三條軸線；對比案例則提醒讀者：Spanner 提供 global consistency 的成熟對照，受監管金融類案例提醒部署位置、合規邊界與自管能力常和一致性需求同時決定 vendor。</p>
<h2 id="反向-sibling-路由">反向 sibling 路由</h2>
<p>CockroachDB 的反向 sibling 路由用來把 PostgreSQL 相容性和 distributed SQL 責任拆開。若讀者從 PostgreSQL 章節過來，先讀 <a href="/blog/backend/01-database/vendors/postgresql/migrate-to-cockroachdb/" data-link-title="PostgreSQL → CockroachDB：三維皆 High 的多重歸類 migration" data-link-desc="PostgreSQL → CockroachDB 是 Schema / Operational / Paradigm 三維皆 High 的 multi-axis migration、實證 [#127](/report/content-structure-by-max-diff-dimension/) 的「多重歸類跟 tie-breaking」規則；主結構走 Type E paradigm shift、Schema 差 &#43; Operational redesign 抽出獨立段；涵蓋 transaction model 重設計、SQL dialect gap、5 個 production 踩雷">PostgreSQL → CockroachDB migration</a>；若只是要 managed SQL 與 storage autoscale，先回 <a href="/blog/backend/01-database/vendors/aurora/" data-link-title="AWS Aurora" data-link-desc="AWS managed PostgreSQL / MySQL、storage / compute 分離、&#43;75% 效能改善的 production 證據">Aurora vendor</a>；若要 Google Cloud 原生 external consistency 與 fully managed control plane，再對照 <a href="/blog/backend/01-database/vendors/spanner/" data-link-title="Google Cloud Spanner" data-link-desc="全球分散式 strong-consistency OLTP、TrueTime API、線性擴展到 10 億 req/sec">Spanner vendor</a>。</p>
<p>這條路由的判準是「應用是否能承擔 distributed transaction 的語意差異」。SQL dialect 相近只降低 migration entry cost，真正的交付風險在 transaction retry、hot range、survival goal、backup restore 與 locality design。</p>
<h2 id="常見陷阱">常見陷阱</h2>
<ul>
<li><strong>single-region 用 CockroachDB</strong>：浪費分散式開銷、PostgreSQL 便宜很多</li>
<li><strong>跨洲 active-active 期待低延遲</strong>：物理限制、跨洲 quorum 100ms+</li>
<li><strong>PostgreSQL extension 假設</strong>：部分 extension 或 SQL 行為需要替代方案，應用要驗證</li>
<li><strong>不規劃 Survival Goals</strong>：default 配置可能不符合 RTO / RPO 需求</li>
<li><strong>backup chain 過長</strong>：incremental 不 full、recovery time 變長</li>
</ul>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>完整 T1 對照：<a href="/blog/backend/01-database/vendors/" data-link-title="資料庫 Vendor 清單" data-link-desc="規劃 SQL、managed SQL、document、KV 與 distributed SQL 的服務頁撰寫順序與教學大綱">01-database vendors index</a></li>
<li>平行：<a href="/blog/backend/01-database/vendors/spanner/" data-link-title="Google Cloud Spanner" data-link-desc="全球分散式 strong-consistency OLTP、TrueTime API、線性擴展到 10 億 req/sec">Spanner vendor</a>、<a href="/blog/backend/01-database/vendors/aurora/" data-link-title="AWS Aurora" data-link-desc="AWS managed PostgreSQL / MySQL、storage / compute 分離、&#43;75% 效能改善的 production 證據">Aurora vendor</a>、<a href="/blog/backend/01-database/vendors/postgresql/" data-link-title="PostgreSQL" data-link-desc="多用途 OLTP 主流關聯式資料庫、MVCC、豐富 SQL 特性、是 Aurora / Cosmos DB / Spanner / CockroachDB / Aurora DSQL 的相容目標">PostgreSQL vendor</a></li>
<li>上游：<a href="/blog/backend/01-database/global-distributed-oltp/" data-link-title="1.11 全球分散式 OLTP" data-link-desc="Spanner / Aurora DSQL / Cosmos DB multi-region write / CockroachDB / TiDB 的全球一致性取捨">1.11 全球分散式 OLTP</a> — 完整選型對比</li>
<li>跨模組：<a href="/blog/backend/09-performance-capacity/capacity-planning/" data-link-title="9.6 容量規劃模型" data-link-desc="peak forecast、headroom budget、growth curve、autoscaling sizing">9.6 容量規劃模型</a>、<a href="/blog/backend/09-performance-capacity/slo-performance-budget/" data-link-title="9.12 SLO 與 Performance Budget" data-link-desc="performance budget 跟 SLO / error budget 的對接">9.12 SLO 與 Performance Budget</a></li>
<li>Last reviewed：2026-05-22（PostgreSQL compatibility / survival goal / managed offering 屬時間敏感 claim）</li>
<li>官方：<a href="https://www.cockroachlabs.com/docs/">CockroachDB Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>Datadog</title><link>https://tarrragon.github.io/blog/backend/04-observability/vendors/datadog/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/04-observability/vendors/datadog/</guid><description>&lt;p>Datadog 是 all-in-one SaaS observability 平台、承擔三個責任：覆蓋 APM / logs / metrics / RUM / synthetics / security / CI visibility 全訊號類型、auto-instrumentation 廣度業界第一、跟 600+ integrations 即插即用。設計取捨偏向「turnkey + 廣度 + integration」、成本是主要取捨點。&lt;/p>
&lt;p>對「想要 turnkey 體驗、不想自管 observability、多訊號類型統一平台、團隊規模可承擔成本」這條路徑、Datadog 是首選。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>安裝 Datadog Agent、配置 APM auto-instrumentation&lt;/li>
&lt;li>用 Datadog Logs / Metrics / APM 三大查詢介面&lt;/li>
&lt;li>控制 cost（log indexing / metric cardinality / APM trace sampling）&lt;/li>
&lt;li>寫 Monitor as code（Terraform）&lt;/li>
&lt;li>評估 OTLP ingestion 跟 Datadog SDK 的取捨&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑5-分鐘把-datadog-跑起來">最短路徑：5 分鐘把 Datadog 跑起來&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 1. 安裝 Agent&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: DD_API_KEY=&amp;lt;key&amp;gt; DD_SITE=&amp;#34;datadoghq.com&amp;#34; bash -c &amp;#34;$(curl -L ...)&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="c1"># 2. 啟用 APM&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: 在 Agent config 加 apm_config.enabled: true&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: 應用程式加 ddtrace-run / dd-trace-py&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl">&lt;span class="c1"># 3. 驗證 Agent + APM 上線&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">9&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: 在 Datadog UI 看 Host map + APM Service List&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="日常操作與決策形狀">日常操作與決策形狀&lt;/h2>
&lt;h3 id="agent-安裝與配置">Agent 安裝與配置&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>安裝方式：package（apt/yum）/ container / K8s DaemonSet / Lambda extension&lt;/li>
&lt;li>Agent config：core / APM / Logs / NetFlow / SNMP 各 sub-config&lt;/li>
&lt;li>DogStatsD：應用層 custom metrics 入口&lt;/li>
&lt;li>對應指令：&lt;code>datadog-agent status&lt;/code>、&lt;code>/etc/datadog-agent/datadog.yaml&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="apm-自動-instrumentation">APM 自動 instrumentation&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>各語言 tracer：dd-trace-java / dd-trace-py / dd-trace-js / dd-trace-go&lt;/li>
&lt;li>Auto-instrumentation 廣度（業界最廣）&lt;/li>
&lt;li>Service / Resource / Operation 三層 trace 結構&lt;/li>
&lt;li>對應 &lt;a href="https://tarrragon.github.io/blog/backend/04-observability/cases/datadog-otel-migration-practice/" data-link-title="4.C7 Datadog：OTel 相容遷移實務" data-link-desc="APM 採集從專有代理轉向 OTel 相容模式的治理案例。">4.C7 Datadog OTel migration&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="logs-配置">Logs 配置&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>採集方式：Agent 採集 / Fluent Bit / Vector → Datadog&lt;/li>
&lt;li>Indexing vs Archives：indexing 費錢但可查、archives 便宜但只能 rehydrate&lt;/li>
&lt;li>Log Pipeline：parsing / enrichment / sensitive data scrubbing&lt;/li>
&lt;li>對應 cost 控制：indexing rate / retention&lt;/li>
&lt;/ul>
&lt;h3 id="metrics">Metrics&lt;/h3>
&lt;p>子議題:&lt;/p></description><content:encoded><![CDATA[<p>Datadog 是 all-in-one SaaS observability 平台、承擔三個責任：覆蓋 APM / logs / metrics / RUM / synthetics / security / CI visibility 全訊號類型、auto-instrumentation 廣度業界第一、跟 600+ integrations 即插即用。設計取捨偏向「turnkey + 廣度 + integration」、成本是主要取捨點。</p>
<p>對「想要 turnkey 體驗、不想自管 observability、多訊號類型統一平台、團隊規模可承擔成本」這條路徑、Datadog 是首選。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>安裝 Datadog Agent、配置 APM auto-instrumentation</li>
<li>用 Datadog Logs / Metrics / APM 三大查詢介面</li>
<li>控制 cost（log indexing / metric cardinality / APM trace sampling）</li>
<li>寫 Monitor as code（Terraform）</li>
<li>評估 OTLP ingestion 跟 Datadog SDK 的取捨</li>
</ol>
<h2 id="最短路徑5-分鐘把-datadog-跑起來">最短路徑：5 分鐘把 Datadog 跑起來</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 1. 安裝 Agent</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># TODO: DD_API_KEY=&lt;key&gt; DD_SITE=&#34;datadoghq.com&#34; bash -c &#34;$(curl -L ...)&#34;</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 2. 啟用 APM</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="c1"># TODO: 在 Agent config 加 apm_config.enabled: true</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="c1"># TODO: 應用程式加 ddtrace-run / dd-trace-py</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl">
</span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="c1"># 3. 驗證 Agent + APM 上線</span>
</span></span><span class="line"><span class="ln">9</span><span class="cl"><span class="c1"># TODO: 在 Datadog UI 看 Host map + APM Service List</span></span></span></code></pre></div><h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="agent-安裝與配置">Agent 安裝與配置</h3>
<p>子議題：</p>
<ul>
<li>安裝方式：package（apt/yum）/ container / K8s DaemonSet / Lambda extension</li>
<li>Agent config：core / APM / Logs / NetFlow / SNMP 各 sub-config</li>
<li>DogStatsD：應用層 custom metrics 入口</li>
<li>對應指令：<code>datadog-agent status</code>、<code>/etc/datadog-agent/datadog.yaml</code></li>
</ul>
<h3 id="apm-自動-instrumentation">APM 自動 instrumentation</h3>
<p>子議題：</p>
<ul>
<li>各語言 tracer：dd-trace-java / dd-trace-py / dd-trace-js / dd-trace-go</li>
<li>Auto-instrumentation 廣度（業界最廣）</li>
<li>Service / Resource / Operation 三層 trace 結構</li>
<li>對應 <a href="/blog/backend/04-observability/cases/datadog-otel-migration-practice/" data-link-title="4.C7 Datadog：OTel 相容遷移實務" data-link-desc="APM 採集從專有代理轉向 OTel 相容模式的治理案例。">4.C7 Datadog OTel migration</a></li>
</ul>
<h3 id="logs-配置">Logs 配置</h3>
<p>子議題：</p>
<ul>
<li>採集方式：Agent 採集 / Fluent Bit / Vector → Datadog</li>
<li>Indexing vs Archives：indexing 費錢但可查、archives 便宜但只能 rehydrate</li>
<li>Log Pipeline：parsing / enrichment / sensitive data scrubbing</li>
<li>對應 cost 控制：indexing rate / retention</li>
</ul>
<h3 id="metrics">Metrics</h3>
<p>子議題:</p>
<ul>
<li>Custom metrics（DogStatsD / Agent / API）</li>
<li>Metric Type：count / gauge / histogram / distribution</li>
<li>Cardinality 控制：每 metric 收 tags 數限制</li>
<li>對應 <a href="/blog/backend/04-observability/cases/gaming-peak-signal-freshness-and-cardinality/" data-link-title="Gaming：高峰流量下的訊號新鮮度與 Cardinality" data-link-desc="在高峰事件中控制訊號延遲與維度爆炸，維持告警與定位可信度。">4.C2 Gaming cardinality</a></li>
</ul>
<h2 id="deep-article">Deep Article</h2>
<ul>
<li><a href="cost-governance-agent-config/">Datadog 成本治理與 Agent 配置</a>：計價模型、custom metrics 成本控制、Agent 部署配置與常見故障</li>
<li><a href="otlp-ingestion-otel-integration/">OTLP Ingestion 與 OTel 整合</a>：Agent OTLP receiver 配置、OTel SDK feature parity、resource mapping 與故障判讀</li>
</ul>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<h3 id="成本治理">成本治理</h3>
<p>子議題：</p>
<ul>
<li>Hosts pricing（vs APM / Logs / Custom Metrics 各自獨立）</li>
<li>Log indexing rate 控制（Exclusion Filters）</li>
<li>Custom metrics 計費（per metric per host）</li>
<li>APM trace sampling</li>
<li>對應 Datadog Usage Attribution</li>
</ul>
<h3 id="otlp-ingestion">OTLP ingestion</h3>
<p>子議題：</p>
<ul>
<li>Datadog Agent 接受 OTLP（gRPC + HTTP）</li>
<li>對 OTel SDK 用戶的優勢（avoid Datadog SDK lock-in）</li>
<li>對應 <a href="/blog/backend/04-observability/cases/datadog-otel-migration-practice/" data-link-title="4.C7 Datadog：OTel 相容遷移實務" data-link-desc="APM 採集從專有代理轉向 OTel 相容模式的治理案例。">4.C7 Datadog OTel migration</a></li>
<li>Datadog 自家 SDK vs OTel：feature parity 取捨</li>
</ul>
<h3 id="monitor-as-code">Monitor as code</h3>
<p>子議題：</p>
<ul>
<li>Terraform Datadog provider：dashboard / monitor / SLO / synthetic</li>
<li>跟 IaC pipeline 整合</li>
<li>多環境（dev / staging / prod）配置</li>
</ul>
<h3 id="apm-trace-sampling">APM Trace Sampling</h3>
<p>子議題：</p>
<ul>
<li>Head-based sampling（rate-based）</li>
<li>Tail-based（Datadog 新功能、需 Agent 支援）</li>
<li>Ingestion vs Indexing sampling 兩層</li>
<li>對應 cost 控制</li>
</ul>
<h3 id="rum--synthetics">RUM / Synthetics</h3>
<p>子議題：</p>
<ul>
<li>RUM（Real User Monitoring）：前端用戶體驗</li>
<li>Synthetics：browser test / API test 主動探測</li>
<li>Session Replay</li>
<li>跟 APM 關聯：frontend trace → backend trace</li>
</ul>
<h3 id="security-monitoring">Security Monitoring</h3>
<p>子議題：</p>
<ul>
<li>Cloud SIEM</li>
<li>ASM（Application Security Management、wAF/RASP）</li>
<li>Cloud Security Posture Management</li>
<li>跟 <a href="/blog/backend/07-security-data-protection/" data-link-title="模組七：資安與資料保護" data-link-desc="以問題驅動方式擴充資安知識網：先定義服務環節問題，再以案例作為觸發式參考">07 security 模組</a> 對照</li>
</ul>
<h2 id="跟-monitoring-模組的分工">跟 Monitoring 模組的分工</h2>
<p>本頁從 server-side APM 平台角度說明 Datadog — agent 部署、cost governance、OTel 遷移、跟 Grafana Stack 的對照。Client-side 的 RUM 體驗（RUM SDK 四種事件、session replay、全棧追蹤的 client 端視角）見 <a href="/blog/monitoring/06-commercial-comparison/datadog-rum/" data-link-title="Datadog RUM" data-link-desc="全棧 APM 的 client-side 觀點 — client action 到 server trace 的完整鏈路追蹤">Monitoring 模組 Datadog RUM</a>。</p>
<p>兩者的交叉點是 trace context — RUM SDK 注入的 trace header 讓 client action 跟 server span 串在同一個 trace。沒有 server-side APM 的團隊用 RUM 也有價值（client-side error + performance），但全棧追蹤需要兩邊都部署。</p>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<h3 id="agent-連不上-datadog">Agent 連不上 Datadog</h3>
<p>操作原則：先 <code>datadog-agent status</code> 看 connectivity、再看 API key + region。</p>
<h3 id="apm-trace-缺失">APM trace 缺失</h3>
<p>操作原則：trace context propagation 在跨 service / 跨 thread 邊界丟失。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># TODO: dd-trace-py debug mode / `DD_TRACE_DEBUG=true`</span></span></span></code></pre></div><h3 id="log-indexing-cost-爆">Log indexing cost 爆</h3>
<p>操作原則：indexed log 量超預期、用 Exclusion Filter 過濾不必要 log。判讀：Datadog Usage page 看每 day indexed log。</p>
<h3 id="custom-metrics-爆預算">Custom metrics 爆預算</h3>
<p>操作原則：每 host 每 metric 計費、cardinality 高（per-user / per-request label）會爆。判讀：Metrics Summary 看 metric volume。</p>
<h3 id="monitor-noise">Monitor noise</h3>
<p>操作原則：alert 太多、低品質、用 Composite Monitor + Recovery / No data threshold。</p>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>預算敏感</td>
          <td><a href="/blog/backend/04-observability/vendors/grafana-stack/" data-link-title="Grafana Stack" data-link-desc="Grafana / Loki / Tempo / Mimir / Pyroscope 全棧">Grafana Stack</a>（OSS）/ Cloud（cheaper）</td>
      </tr>
      <tr>
          <td>需要 OSS / self-host</td>
          <td><a href="/blog/backend/04-observability/vendors/grafana-stack/" data-link-title="Grafana Stack" data-link-desc="Grafana / Loki / Tempo / Mimir / Pyroscope 全棧">Grafana Stack</a> + <a href="/blog/backend/04-observability/vendors/prometheus/" data-link-title="Prometheus" data-link-desc="Pull-based metrics 主流 OSS、PromQL 與 alerting">Prometheus</a></td>
      </tr>
      <tr>
          <td>High-cardinality debug 深度</td>
          <td><a href="/blog/backend/04-observability/vendors/honeycomb/" data-link-title="Honeycomb" data-link-desc="High-cardinality observability 平台、events-based 模型">Honeycomb</a></td>
      </tr>
      <tr>
          <td>AWS-only + 成本</td>
          <td><a href="/blog/backend/04-observability/vendors/aws-cloudwatch/" data-link-title="AWS CloudWatch" data-link-desc="AWS 原生觀測性服務、Logs / Metrics / Traces (X-Ray)">CloudWatch</a></td>
      </tr>
      <tr>
          <td>純 error tracking</td>
          <td><a href="/blog/backend/04-observability/vendors/sentry/" data-link-title="Sentry" data-link-desc="Error tracking 主流、APM / Profiling / Session Replay 擴展">Sentry</a></td>
      </tr>
      <tr>
          <td>多 vendor 標準化</td>
          <td><a href="/blog/backend/04-observability/vendors/opentelemetry/" data-link-title="OpenTelemetry" data-link-desc="可觀測性開放標準、SDK 與 Collector">OpenTelemetry</a> + 任一 backend</td>
      </tr>
      <tr>
          <td>Logs full-text 為主</td>
          <td><a href="/blog/backend/04-observability/vendors/elastic-stack/" data-link-title="Elastic Stack" data-link-desc="ELK：Elasticsearch / Logstash / Kibana &#43; Beats / APM">Elastic</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>各語言 dd-trace SDK 完整 API</li>
<li>Datadog UI 操作詳細</li>
<li>Pricing 詳細計算（用 Datadog Usage page）</li>
<li>600+ integrations 各自設定</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<h3 id="直接相關案例">直接相關案例</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>主討論議題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/datadog-otel-migration-practice/" data-link-title="4.C7 Datadog：OTel 相容遷移實務" data-link-desc="APM 採集從專有代理轉向 OTel 相容模式的治理案例。">4.C7 Datadog OTel migration</a></td>
          <td>OTLP ingestion + SDK 移轉</td>
      </tr>
  </tbody>
</table>
<h3 id="跨-vendor-對照">跨 vendor 對照</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>對 Datadog 的對應</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/fintech-audit-evidence-observability/" data-link-title="FinTech：審計證據鏈的可觀測性設計" data-link-desc="把交易與存取事件轉成可回查證據，降低合規審核與事故判讀落差。">4.C1 Fintech audit</a></td>
          <td>Datadog Logs Indexing / Archives 作為審計證據面</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/gaming-peak-signal-freshness-and-cardinality/" data-link-title="Gaming：高峰流量下的訊號新鮮度與 Cardinality" data-link-desc="在高峰事件中控制訊號延遲與維度爆炸，維持告警與定位可信度。">4.C2 Gaming cardinality</a></td>
          <td>Custom metrics cardinality 治理</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/failure-otel-migration-signal-drift/" data-link-title="4.C9 反例：OTel 遷移後訊號漂移" data-link-desc="雙軌採集未對齊導致告警與 SLO 判讀失真。">4.C9 OTel migration signal drift</a></td>
          <td>（反例）Datadog SDK ↔ OTLP 雙軌語意漂移</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/contrast-observability-rollout-by-scale/" data-link-title="4.C10 對照：規模差異下的觀測遷移" data-link-desc="觀測遷移在不同規模團隊下的流程與風險差異。">4.C10 規模對照</a></td>
          <td>中大型常選 Datadog turnkey</td>
      </tr>
  </tbody>
</table>
<p><strong>待補 Datadog 案例</strong>：客戶 cost optimization stories、large scale 部署（Shopify / Coinbase / Zoom 等）engineering blog。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游概念：<a href="/blog/backend/04-observability/telemetry-data-quality/" data-link-title="4.17 Telemetry Data Quality" data-link-desc="把 missing signal、schema drift、sampling bias 與 timestamp skew 變成資料品質問題">4.17 Telemetry Data Quality</a></li>
<li>平行 vendor：<a href="/blog/backend/04-observability/vendors/opentelemetry/" data-link-title="OpenTelemetry" data-link-desc="可觀測性開放標準、SDK 與 Collector">OpenTelemetry</a>、<a href="/blog/backend/04-observability/vendors/grafana-stack/" data-link-title="Grafana Stack" data-link-desc="Grafana / Loki / Tempo / Mimir / Pyroscope 全棧">Grafana Stack</a></li>
<li>下游能力：<a href="/blog/backend/04-observability/observability-evidence-package/" data-link-title="4.20 Observability Evidence Package" data-link-desc="把 log、metric、trace、audit 與資料品質限制包成可交接證據">4.20 Observability Evidence Package</a></li>
</ul>
]]></content:encoded></item><item><title>DragonflyDB</title><link>https://tarrragon.github.io/blog/backend/02-cache-redis/vendors/dragonflydb/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/02-cache-redis/vendors/dragonflydb/</guid><description>&lt;p>DragonflyDB 是 C++ 重寫的 in-memory store、承擔三個責任：Redis / Memcached protocol 相容（drop-in 替換）、shared-nothing 多核架構（充分利用 CPU）、高 memory efficiency。設計取捨偏向「協議相容但效能大幅提升」、宣稱比 Redis 高 25 倍 throughput。授權從 Apache 2.0 改 BSL（Business Source License）、商業使用有限制。&lt;/p>
&lt;p>對「需要極高 single-instance throughput、多核機器希望充分利用 CPU、Redis drop-in 但要 scale up 而非 out」這條路徑、DragonflyDB 是值得評估的替代。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>跑起 DragonflyDB、用 redis-cli 驗證 protocol 相容&lt;/li>
&lt;li>評估從 Redis 遷移的相容性風險（unsupported commands）&lt;/li>
&lt;li>看懂 shared-nothing 多核架構跟 Redis I/O thread 的差異&lt;/li>
&lt;li>評估 BSL 授權對你的商業使用影響&lt;/li>
&lt;li>區分 DragonflyDB 跟 Redis Cluster / Garnet / KeyDB 的選用判讀&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑5-分鐘把-dragonflydb-跑起來">最短路徑：5 分鐘把 DragonflyDB 跑起來&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 1. 啟動 DragonflyDB（thread 數預設 = CPU 核數、自動多核）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">docker run -d --name dragonfly -p 6379:6379 &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> docker.dragonflydb.io/dragonflydb/dragonfly
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">&lt;span class="c1"># 2. 用 redis-cli 驗證（wire-protocol 相容、直接用 redis-cli）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">redis-cli SET foo bar &lt;span class="c1"># → OK&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">redis-cli GET foo &lt;span class="c1"># → bar&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="c1"># 3. 確認版本與多核：DragonflyDB 回報相容的 redis_version + 自身版本 + thread 數&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">redis-cli INFO server &lt;span class="p">|&lt;/span> grep -E &lt;span class="s2">&amp;#34;redis_version|dragonfly_version|thread_count|multiplexing_api&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">&lt;span class="c1"># redis_version:7.4.0 ← client library 以此判斷相容性&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">&lt;span class="c1"># dragonfly_version:df-v1.39.0 ← DragonflyDB 自身版本&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">&lt;span class="c1"># thread_count:8 ← 自動對齊 CPU 核數（shared-nothing 多核）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">&lt;span class="c1"># multiplexing_api:epoll&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>第三步是 DragonflyDB 跟 Redis 的核心差異證據：&lt;code>thread_count&lt;/code> 自動對齊 CPU 核數、每個 thread 管自己的 partition（shared-nothing），這是它高吞吐的來源；&lt;code>redis_version:7.4.0&lt;/code> 讓既有 Redis client 直接相容、無需改 code。實機驗證於 dragonfly df-v1.39.0、最後檢查日 2026-06-16。實際遷移評估見 &lt;a href="#redis-%e7%9b%b8%e5%ae%b9%e9%82%8a%e7%95%8c">Redis 相容邊界&lt;/a>。&lt;/p>
&lt;h2 id="日常操作與決策形狀">日常操作與決策形狀&lt;/h2>
&lt;h3 id="cli-與-client-api">CLI 與 client API&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>直接用 redis-cli（DragonflyDB 100% wire-protocol 相容）&lt;/li>
&lt;li>所有 Redis client library 自動相容&lt;/li>
&lt;li>沒有 dragonfly-cli、用 INFO 命令確認 server type&lt;/li>
&lt;/ul>
&lt;h3 id="redis-相容邊界">Redis 相容邊界&lt;/h3>
&lt;p>DragonflyDB 相容大多數 Redis commands、但部分行為差異。子議題：&lt;/p></description><content:encoded><![CDATA[<p>DragonflyDB 是 C++ 重寫的 in-memory store、承擔三個責任：Redis / Memcached protocol 相容（drop-in 替換）、shared-nothing 多核架構（充分利用 CPU）、高 memory efficiency。設計取捨偏向「協議相容但效能大幅提升」、宣稱比 Redis 高 25 倍 throughput。授權從 Apache 2.0 改 BSL（Business Source License）、商業使用有限制。</p>
<p>對「需要極高 single-instance throughput、多核機器希望充分利用 CPU、Redis drop-in 但要 scale up 而非 out」這條路徑、DragonflyDB 是值得評估的替代。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>跑起 DragonflyDB、用 redis-cli 驗證 protocol 相容</li>
<li>評估從 Redis 遷移的相容性風險（unsupported commands）</li>
<li>看懂 shared-nothing 多核架構跟 Redis I/O thread 的差異</li>
<li>評估 BSL 授權對你的商業使用影響</li>
<li>區分 DragonflyDB 跟 Redis Cluster / Garnet / KeyDB 的選用判讀</li>
</ol>
<h2 id="最短路徑5-分鐘把-dragonflydb-跑起來">最短路徑：5 分鐘把 DragonflyDB 跑起來</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># 1. 啟動 DragonflyDB（thread 數預設 = CPU 核數、自動多核）</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">docker run -d --name dragonfly -p 6379:6379 <span class="se">\
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="se"></span>  docker.dragonflydb.io/dragonflydb/dragonfly
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="c1"># 2. 用 redis-cli 驗證（wire-protocol 相容、直接用 redis-cli）</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">redis-cli SET foo bar    <span class="c1"># → OK</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">redis-cli GET foo        <span class="c1"># → bar</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="c1"># 3. 確認版本與多核：DragonflyDB 回報相容的 redis_version + 自身版本 + thread 數</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">redis-cli INFO server <span class="p">|</span> grep -E <span class="s2">&#34;redis_version|dragonfly_version|thread_count|multiplexing_api&#34;</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="c1"># redis_version:7.4.0          ← client library 以此判斷相容性</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="c1"># dragonfly_version:df-v1.39.0 ← DragonflyDB 自身版本</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="c1"># thread_count:8               ← 自動對齊 CPU 核數（shared-nothing 多核）</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="c1"># multiplexing_api:epoll</span></span></span></code></pre></div><p>第三步是 DragonflyDB 跟 Redis 的核心差異證據：<code>thread_count</code> 自動對齊 CPU 核數、每個 thread 管自己的 partition（shared-nothing），這是它高吞吐的來源；<code>redis_version:7.4.0</code> 讓既有 Redis client 直接相容、無需改 code。實機驗證於 dragonfly df-v1.39.0、最後檢查日 2026-06-16。實際遷移評估見 <a href="#redis-%e7%9b%b8%e5%ae%b9%e9%82%8a%e7%95%8c">Redis 相容邊界</a>。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="cli-與-client-api">CLI 與 client API</h3>
<p>子議題：</p>
<ul>
<li>直接用 redis-cli（DragonflyDB 100% wire-protocol 相容）</li>
<li>所有 Redis client library 自動相容</li>
<li>沒有 dragonfly-cli、用 INFO 命令確認 server type</li>
</ul>
<h3 id="redis-相容邊界">Redis 相容邊界</h3>
<p>DragonflyDB 相容大多數 Redis commands、但部分行為差異。子議題：</p>
<ul>
<li>支援：Core data types / commands / persistence / pub-sub / transactions</li>
<li>注意：部分 Module 不支援（RedisJSON 有自家版、RedisSearch 沒有）</li>
<li>注意：Lua scripting 支援但效能取捨不同</li>
<li>限制：Cluster mode 採 single-instance scale-up、沒有 Redis Cluster mode（單 instance 已能處理 Redis Cluster 規模）</li>
</ul>
<p>對應指令：<code>INFO server</code> 確認 dragonfly version + 配置。</p>
<h3 id="配置與調優">配置與調優</h3>
<p>子議題：</p>
<ul>
<li><code>--threads</code>：thread 數量、預設 CPU core 數</li>
<li><code>--maxmemory</code>：memory limit、行為跟 Redis 類似</li>
<li><code>--cache_mode</code>：傳統 cache 模式 vs DragonflyDB 預設模式</li>
<li><code>--snapshot_cron</code>：snapshot 策略</li>
</ul>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<h3 id="shared-nothing-多核架構">Shared-nothing 多核架構</h3>
<p>子議題：</p>
<ul>
<li>每個 thread 管自己的 partition、no shared state</li>
<li>VLL（Very Lightweight Lock）取代 Redis 的 single-thread model</li>
<li>Hash 分到不同 thread、靠 epoll 跟 io_uring 做 I/O</li>
<li>跟 Redis I/O threads 的對比：Redis 仍 single main thread、只 I/O 多線；DragonflyDB 完全多線</li>
</ul>
<h3 id="memory-efficiency">Memory efficiency</h3>
<p>子議題：</p>
<ul>
<li>用 dashtable（DragonflyDB 自製 hash table）取代 Redis dict</li>
<li>Snapshot 用 fork-less 機制、避免大記憶體 fork 開銷</li>
<li>同樣 dataset 通常比 Redis 省 20-40% memory（依資料形狀）</li>
</ul>
<h3 id="bsl-授權影響">BSL 授權影響</h3>
<p>子議題：</p>
<ul>
<li>BSL（Business Source License）：商業使用受限、4 年後轉 Apache 2.0</li>
<li>限制：不可作為 managed DragonflyDB service 對外提供</li>
<li>內部使用無限制（多數企業場景）</li>
<li>對 SaaS 供應商：要審慎評估</li>
</ul>
<h3 id="跟-keydb--garnet-的對比">跟 KeyDB / Garnet 的對比</h3>
<p>子議題：</p>
<ul>
<li><strong>KeyDB</strong>：Redis fork、multi-threaded、Snap 收購後相對停滯</li>
<li><strong>Garnet</strong>（Microsoft）：研究用、極高 throughput、生態淺</li>
<li><strong>DragonflyDB</strong>：商業化最積極、生態最活躍</li>
</ul>
<h3 id="scale-up-vs-scale-out">Scale-up vs Scale-out</h3>
<p>子議題：</p>
<ul>
<li>DragonflyDB 哲學：single instance 撐到很大規模（廠商宣稱 1TB+ memory / 6.4M QPS）</li>
<li>Redis 哲學：single instance 有上限、靠 Cluster sharding</li>
<li>何時 scale-up 不夠：跨 region / 跨 AZ HA 需求 → 仍需 replica / sentinel</li>
</ul>
<h3 id="從-redis-遷移">從 Redis 遷移</h3>
<p>子議題：</p>
<ul>
<li>評估 module 使用：列出當前 modules、確認 DragonflyDB 對應</li>
<li>評估 Cluster mode 使用：DragonflyDB 不支援 Cluster mode、要評估能否回到 single instance</li>
<li>遷移路徑：replica 模式雙寫 / 直接 cutover</li>
<li>對應 BSL 授權影響評估</li>
</ul>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<h3 id="performance-不如預期">Performance 不如預期</h3>
<p>操作原則：先確認 thread 數對齊 CPU core、再看 memory pressure。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">redis-cli INFO server <span class="p">|</span> grep -E <span class="s2">&#34;dragonfly_version|thread_count&#34;</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># dragonfly_version:df-v1.39.0</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="c1"># thread_count:8                ← 對齊 CPU 核數才能發揮多核</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">redis-cli INFO memory <span class="p">|</span> grep -E <span class="s2">&#34;used_memory:|maxmemory:&#34;</span></span></span></code></pre></div><p>判讀：thread &lt; core → 沒充分利用 CPU；memory &gt; 50% maxmemory → 影響 throughput。</p>
<h3 id="command-不支援">Command 不支援</h3>
<p>操作原則：DragonflyDB 不支援全部 Redis commands、看 dragonflydb.io/docs/api/redis 確認。</p>
<p>判讀路徑：client error「unknown command」→ 確認 DragonflyDB 對應實作狀態。</p>
<h3 id="cluster-mode-client-連不上">Cluster mode client 連不上</h3>
<p>操作原則：DragonflyDB 不支援 Redis Cluster mode、若 client 配置 cluster mode 會連不上。判讀：改回 standalone client config。</p>
<h3 id="module-不可用">Module 不可用</h3>
<p>對應 KeyDB / Garnet 的對照思路：DragonflyDB 自家 modules 偏少、Redis Stack modules 大多沒有 fork。</p>
<h3 id="bsl-授權商業使用問題">BSL 授權商業使用問題</h3>
<p>操作原則：商業使用前審 license terms、若是 managed service 對外提供、需聯絡 DragonflyDB 取得商業 license。</p>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>需要 Redis Cluster mode</td>
          <td><a href="/blog/backend/02-cache-redis/vendors/redis/" data-link-title="Redis" data-link-desc="OSS in-memory data structure store、cache 主流">Redis</a> / <a href="/blog/backend/02-cache-redis/vendors/valkey/" data-link-title="Valkey" data-link-desc="Redis fork、Linux Foundation 託管、BSD 授權">Valkey</a></td>
      </tr>
      <tr>
          <td>需要 OSI 認可開源授權</td>
          <td><a href="/blog/backend/02-cache-redis/vendors/valkey/" data-link-title="Valkey" data-link-desc="Redis fork、Linux Foundation 託管、BSD 授權">Valkey</a></td>
      </tr>
      <tr>
          <td>需要 Redis Stack 完整 modules</td>
          <td><a href="/blog/backend/02-cache-redis/vendors/redis/" data-link-title="Redis" data-link-desc="OSS in-memory data structure store、cache 主流">Redis</a></td>
      </tr>
      <tr>
          <td>純 KV 不需 data types</td>
          <td><a href="/blog/backend/02-cache-redis/vendors/memcached/" data-link-title="Memcached" data-link-desc="純記憶體 key-value cache、無持久化">Memcached</a></td>
      </tr>
      <tr>
          <td>AWS managed</td>
          <td><a href="/blog/backend/02-cache-redis/vendors/aws-elasticache/" data-link-title="AWS ElastiCache" data-link-desc="AWS managed Redis / Valkey / Memcached">AWS ElastiCache</a>（無 Dragonfly managed）</td>
      </tr>
      <tr>
          <td>Multi-threaded Redis fork</td>
          <td>KeyDB（停滯中）</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>DragonflyDB internal 架構細節（dashtable、VLL 等）</li>
<li>BSL 授權法律解讀（請諮詢律師）</li>
<li>各語言 client 完整對應表</li>
<li>詳細 benchmark methodology</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<h3 id="直接相關案例沿用-redis-compatible-同源案例--待補-dragonflydb-specific-case">直接相關案例（沿用 Redis-compatible 同源案例 + 待補 DragonflyDB-specific case）</h3>
<p>DragonflyDB 2022 年開源、wire-protocol 與 Redis 相容、Redis 上的 cache pattern 案例可作為框架參考。Production case 仍累積中。</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>對 DragonflyDB 的對應</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/shopify-write-through-cache-at-scale/" data-link-title="2.C5 Shopify：Write-through Cache 在高讀流量的實作" data-link-desc="read-heavy 服務如何轉向 write-through 快取模型。">2.C5 Shopify write-through</a></td>
          <td>Write-through 模式在 DragonflyDB 上行為一致、單 instance 多核可承接更大 throughput</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/shopify-cache-serialization-migration/" data-link-title="2.C3 Shopify：快取序列化格式遷移" data-link-desc="快取 payload 從 Marshal 轉 MessagePack 的遷移策略。">2.C3 Shopify serialization</a></td>
          <td>Payload 雙軌遷移 client-side 實作、DragonflyDB 跟 Redis 共用 API、遷移路徑相同</td>
      </tr>
  </tbody>
</table>
<p><strong>待補 DragonflyDB-specific 案例</strong>：早期採用者 benchmark 報告、從 Redis Cluster 收回 single-instance 的遷移案例、BSL 授權實際商業使用評估、multi-core 加速效果的 production 實測。</p>
<h3 id="跨-vendor-對照">跨 vendor 對照</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>對 DragonflyDB 的對應</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/contrast-cache-strategy-by-scale/" data-link-title="2.C10 對照：規模差異下的快取策略" data-link-desc="同一快取策略在小中大型服務下會產生不同風險。">2.C10 規模對照</a></td>
          <td>DragonflyDB 擅長 scale-up、中大型 single instance 取代 Redis Cluster 是核心賣點</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/failure-cache-stampede-rollout-regression/" data-link-title="2.C9 反例：快取切換引發 Stampede 回歸" data-link-desc="快取策略切換若缺乏保護，會導致回源壓力與錯誤率連鎖上升。">2.C9 Cache Stampede</a></td>
          <td>TTL jitter 通用、DragonflyDB 行為跟 Redis 一致、多核擴展不會消除 stampede 風險</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/meta-cachelib-kangaroo-tiered-cache/" data-link-title="2.C4 Meta：CacheLib / Kangaroo 分層快取" data-link-desc="快取從 DRAM-only 轉向分層快取架構的實務案例。">2.C4 Meta CacheLib + Kangaroo</a></td>
          <td>分層 cache 議題對照、DragonflyDB 強調 memory efficiency 取代 flash tier 的部分需求</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/meta-cache-consistency-upgrade/" data-link-title="2.C1 Meta：Cache Consistency 升級" data-link-desc="快取 invalidation 一致性如何從常見錯誤演進到高可信治理。">2.C1 Meta cache consistency</a></td>
          <td>一致性治理框架通用、但 DragonflyDB 無 Cluster mode、shard move 議題不同（單 instance scope）</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游概念：<a href="/blog/backend/02-cache-redis/cache-aside/" data-link-title="2.2 cache aside 與失效策略" data-link-desc="整理 read-through 思路、cache miss 與 invalidation">2.2 Cache Aside</a>、<a href="/blog/backend/02-cache-redis/ttl-eviction/" data-link-title="2.3 TTL 與 eviction" data-link-desc="整理過期策略、容量控制與熱點資料">2.3 TTL eviction</a></li>
<li>平行 vendor：<a href="/blog/backend/02-cache-redis/vendors/redis/" data-link-title="Redis" data-link-desc="OSS in-memory data structure store、cache 主流">Redis</a>、<a href="/blog/backend/02-cache-redis/vendors/valkey/" data-link-title="Valkey" data-link-desc="Redis fork、Linux Foundation 託管、BSD 授權">Valkey</a></li>
<li>下游能力：<a href="/blog/backend/02-cache-redis/high-concurrency-access/" data-link-title="2.1 高併發下的 Redis 讀寫邊界" data-link-desc="說明高併發服務如何共用 Redis client、控制 pipeline 與避免 cache stampede">2.6 high concurrency</a></li>
<li>回退路徑：<a href="/blog/backend/02-cache-redis/vendors/dragonflydb/migrate-to-redis/" data-link-title="DragonflyDB → Redis / Valkey：回退到標準生態的遷移路徑" data-link-desc="從 DragonflyDB 遷回 Redis 或 Valkey，處理 snapshotting → RDB/AOF 差異、HA 架構切換與 Cluster mode 重建的階段化流程">DragonflyDB → Redis/Valkey</a></li>
</ul>
]]></content:encoded></item><item><title>Gatling</title><link>https://tarrragon.github.io/blog/backend/06-reliability/vendors/gatling/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/06-reliability/vendors/gatling/</guid><description>&lt;p>Gatling 是 JVM 生態的 load test 工具、承擔三個責任：code-first 強型別 scenario DSL（Scala / Java / Kotlin、編譯期就抓 script bug）、async / non-blocking 引擎（單機高 VU 不靠 thread-per-VU）、Gatling Enterprise 分散式負載與企業 dashboard。設計取捨偏向「強型別 + 高單機 throughput + JVM 既有資產」、跟 k6（JS DX）跟 JMeter（GUI + plugins）的取捨在 dev workflow 跟團隊既有技能。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>用 Scala / Java / Kotlin DSL 寫 simulation（scenario + injection profile）&lt;/li>
&lt;li>設計 assertion + threshold 接 CI&lt;/li>
&lt;li>用 HAR-driven recording 從瀏覽器抓真實 user flow 起 script&lt;/li>
&lt;li>評估 Gatling Enterprise 分散式 vs OSS 單機高 VU 的取捨&lt;/li>
&lt;li>評估 Gatling vs k6 / JMeter / Locust 的選用條件&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑5-分鐘把-gatling-跑起來">最短路徑：5 分鐘把 Gatling 跑起來&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 1. 安裝&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: brew install gatling / 下載 bundle / Maven / sbt plugin&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="c1"># 2. 寫 simulation&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: class MySim extends Simulation {&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="c1"># val httpProtocol = http.baseUrl(&amp;#34;...&amp;#34;)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="c1"># val scn = scenario(&amp;#34;...&amp;#34;).exec(http(&amp;#34;get&amp;#34;).get(&amp;#34;/&amp;#34;))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="c1"># setUp(scn.inject(rampUsersPerSec(1).to(50).during(60))).protocols(httpProtocol)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="c1"># }&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">&lt;span class="c1"># 3. 跑&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: gatling.sh -s MySim / mvn gatling:test / sbt Gatling/test&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="日常操作與決策形狀">日常操作與決策形狀&lt;/h2>
&lt;h3 id="simulation-結構">Simulation 結構&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>&lt;code>Simulation&lt;/code> class（一個檔一個 simulation、整個 test 的根）&lt;/li>
&lt;li>&lt;code>scenario(...).exec(...)&lt;/code>（一條 user journey 的步驟序列）&lt;/li>
&lt;li>&lt;code>httpProtocol&lt;/code>（baseUrl / header / acceptedContent / proxy 共用配置）&lt;/li>
&lt;li>&lt;code>feeder&lt;/code>（CSV / JSON / JDBC 餵 data、配合 &lt;code>randomFeeder&lt;/code> / &lt;code>circular&lt;/code>）&lt;/li>
&lt;/ul>
&lt;h3 id="injection-profilevu-注入節奏">Injection profile（VU 注入節奏）&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>&lt;code>atOnceUsers(n)&lt;/code>、&lt;code>rampUsers(n).during(t)&lt;/code>、&lt;code>constantUsersPerSec(rate).during(t)&lt;/code>、&lt;code>rampUsersPerSec(a).to(b).during(t)&lt;/code>、&lt;code>heavisideUsers(n).during(t)&lt;/code>&lt;/li>
&lt;li>跟 k6 stages 對照：Gatling 用 injection step composition、k6 用 stages array — 概念近、語法不同&lt;/li>
&lt;li>Closed model（固定 VU）vs Open model（固定 rate）— Gatling 兩者都支援、production 流量多半 open model 更貼近&lt;/li>
&lt;/ul>
&lt;h3 id="assertion--threshold--ci">Assertion + threshold + CI&lt;/h3>
&lt;p>子議題：&lt;/p></description><content:encoded><![CDATA[<p>Gatling 是 JVM 生態的 load test 工具、承擔三個責任：code-first 強型別 scenario DSL（Scala / Java / Kotlin、編譯期就抓 script bug）、async / non-blocking 引擎（單機高 VU 不靠 thread-per-VU）、Gatling Enterprise 分散式負載與企業 dashboard。設計取捨偏向「強型別 + 高單機 throughput + JVM 既有資產」、跟 k6（JS DX）跟 JMeter（GUI + plugins）的取捨在 dev workflow 跟團隊既有技能。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>用 Scala / Java / Kotlin DSL 寫 simulation（scenario + injection profile）</li>
<li>設計 assertion + threshold 接 CI</li>
<li>用 HAR-driven recording 從瀏覽器抓真實 user flow 起 script</li>
<li>評估 Gatling Enterprise 分散式 vs OSS 單機高 VU 的取捨</li>
<li>評估 Gatling vs k6 / JMeter / Locust 的選用條件</li>
</ol>
<h2 id="最短路徑5-分鐘把-gatling-跑起來">最短路徑：5 分鐘把 Gatling 跑起來</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># 1. 安裝</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="c1"># TODO: brew install gatling / 下載 bundle / Maven / sbt plugin</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c1"># 2. 寫 simulation</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="c1"># TODO: class MySim extends Simulation {</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="c1">#         val httpProtocol = http.baseUrl(&#34;...&#34;)</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="c1">#         val scn = scenario(&#34;...&#34;).exec(http(&#34;get&#34;).get(&#34;/&#34;))</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="c1">#         setUp(scn.inject(rampUsersPerSec(1).to(50).during(60))).protocols(httpProtocol)</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="c1">#       }</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="c1"># 3. 跑</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="c1"># TODO: gatling.sh -s MySim / mvn gatling:test / sbt Gatling/test</span></span></span></code></pre></div><h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="simulation-結構">Simulation 結構</h3>
<p>子議題：</p>
<ul>
<li><code>Simulation</code> class（一個檔一個 simulation、整個 test 的根）</li>
<li><code>scenario(...).exec(...)</code>（一條 user journey 的步驟序列）</li>
<li><code>httpProtocol</code>（baseUrl / header / acceptedContent / proxy 共用配置）</li>
<li><code>feeder</code>（CSV / JSON / JDBC 餵 data、配合 <code>randomFeeder</code> / <code>circular</code>）</li>
</ul>
<h3 id="injection-profilevu-注入節奏">Injection profile（VU 注入節奏）</h3>
<p>子議題：</p>
<ul>
<li><code>atOnceUsers(n)</code>、<code>rampUsers(n).during(t)</code>、<code>constantUsersPerSec(rate).during(t)</code>、<code>rampUsersPerSec(a).to(b).during(t)</code>、<code>heavisideUsers(n).during(t)</code></li>
<li>跟 k6 stages 對照：Gatling 用 injection step composition、k6 用 stages array — 概念近、語法不同</li>
<li>Closed model（固定 VU）vs Open model（固定 rate）— Gatling 兩者都支援、production 流量多半 open model 更貼近</li>
</ul>
<h3 id="assertion--threshold--ci">Assertion + threshold + CI</h3>
<p>子議題：</p>
<ul>
<li><code>setUp(...).assertions(global.responseTime.percentile3.lt(500), global.successfulRequests.percent.gt(95))</code></li>
<li>Assertion 失敗時 process exit code 非 0、直接接 CI pass/fail gate</li>
<li>對應 <a href="/blog/backend/06-reliability/performance-regression-gate/" data-link-title="6.13 Performance Regression Gate" data-link-desc="把效能 baseline 從一次性壓測變成持續對齊的 release gate，涵蓋 baseline 設定、判讀方法、variance 控制與退化定位">6.13 Performance Regression Gate</a></li>
</ul>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<h3 id="har-driven-recording">HAR-driven recording</h3>
<p>子議題：</p>
<ul>
<li>Chrome DevTools 匯出 HAR、<code>gatling-recorder</code> 從 HAR 產 simulation skeleton</li>
<li>適合：複雜 user flow（multi-step checkout / form / login redirect）懶得手寫 script</li>
<li>邊界：recording 出來是 baseline、需手動補 dynamic correlation（CSRF token / session id / form state）</li>
</ul>
<h3 id="gatling-enterprise前-frontline">Gatling Enterprise（前 FrontLine）</h3>
<p>子議題：</p>
<ul>
<li>分散式 load（多 injector node 模擬 100k+ VU）、跨 region traffic source</li>
<li>Web UI 跑 test、看 dashboard、開 trend analysis</li>
<li>接 Git repo 自動 build simulation、跟 CI / Jenkins / GitLab 整合</li>
<li>對應 <a href="/blog/backend/05-deployment-platform/vendors/kubernetes/" data-link-title="Kubernetes" data-link-desc="Container orchestration 主流、GKE / EKS / AKS / 自管">Kubernetes vendor 頁</a> 的 on-K8s 部署</li>
</ul>
<h3 id="async-engine-跟單機高-vu">Async engine 跟單機高 VU</h3>
<p>子議題：</p>
<ul>
<li>引擎基於 Akka / Netty、non-blocking IO、單 thread 可驅動上千 VU</li>
<li>對比 JMeter thread-per-VU 模型、Gatling 單機 VU 上限可高 10x 起跳</li>
<li>邊界：target service 才是瓶頸時、單機更高 VU 也壓不出更多訊號、要走分散式</li>
</ul>
<h3 id="jvm-tuning">JVM tuning</h3>
<p>子議題：</p>
<ul>
<li>Heap size（<code>-Xms / -Xmx</code>）跟 GC 策略（G1 / ZGC）影響高 VU 穩定性</li>
<li>Connection pool / file descriptor ulimit 是常見卡關點</li>
<li>Container 跑 Gatling 要注意 CPU / memory request 給足</li>
</ul>
<h3 id="從-jmeter-遷移">從 JMeter 遷移</h3>
<p>子議題：</p>
<ul>
<li>JMeter <code>.jmx</code> 沒官方 converter、要人工 port</li>
<li>適合切點：新 simulation 寫 Gatling、舊 <code>.jmx</code> 維護收斂後再評估</li>
<li>對應 <a href="/blog/backend/06-reliability/vendors/jmeter/" data-link-title="Apache JMeter" data-link-desc="老牌 load test 工具、GUI &#43; plugins">JMeter</a> 「既有 .jmx 資產治理」段</li>
</ul>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<h3 id="單機-vu-上不去">單機 VU 上不去</h3>
<p>操作原則：JVM heap / ulimit / connection pool 三層先排、再看是不是 target service 已是瓶頸（latency 漲、VU 卻沒滿）。</p>
<h3 id="response-time-p99-不穩">Response time p99 不穩</h3>
<p>操作原則：GC pause（看 GC log）/ network jitter / target service warmup 沒做完。Steady-state 量測前要先 ramp-up + soak 5-10 分鐘。</p>
<h3 id="assertion-偶發-fail">Assertion 偶發 fail</h3>
<p>操作原則：threshold 設在 noise level 附近、把 baseline 重跑 3 次抓 p95 區間、再設 threshold 留 buffer。</p>
<h3 id="recording-出來的-script-跑不通">Recording 出來的 script 跑不通</h3>
<p>操作原則：HAR 沒抓到 dynamic value（CSRF / session）、要手動加 <code>check(regex(...).saveAs(...))</code> 把 response 抓出來餵後續 request。</p>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>非 JVM 團隊 / JS DX</td>
          <td><a href="/blog/backend/06-reliability/vendors/k6/" data-link-title="k6" data-link-desc="現代 load test、JS scripting、Grafana Labs">k6</a></td>
      </tr>
      <tr>
          <td>Python + 動態 user behavior</td>
          <td><a href="/blog/backend/06-reliability/vendors/locust/" data-link-title="Locust" data-link-desc="Python-based load test、distributed、易擴展">Locust</a></td>
      </tr>
      <tr>
          <td>GUI 設計 / 既有資產</td>
          <td><a href="/blog/backend/06-reliability/vendors/jmeter/" data-link-title="Apache JMeter" data-link-desc="老牌 load test 工具、GUI &#43; plugins">JMeter</a></td>
      </tr>
      <tr>
          <td>Browser flow load</td>
          <td>k6 browser / Playwright + 自製 load harness</td>
      </tr>
      <tr>
          <td>Cloud managed</td>
          <td>Gatling Enterprise / BlazeMeter / k6 Cloud</td>
      </tr>
      <tr>
          <td>Capacity planning（非 CI）</td>
          <td><a href="/blog/backend/09-performance-capacity/" data-link-title="模組九：效能工程與容量規劃" data-link-desc="把『目前配置能撐多少、要加多少機器』變成可量化、可驗證、可改進的工程流程">09 performance capacity</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Scala / Kotlin 語言基礎</li>
<li>Gatling DSL 完整 API reference</li>
<li>Gatling Enterprise pricing 跟 deployment model 細節</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<table>
  <thead>
      <tr>
          <th>案例方向</th>
          <th>對應主題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/06-reliability/cases/linkedin/capacity-headroom-and-oncall-tiering/" data-link-title="LinkedIn：Capacity Headroom 與 On-call 分層" data-link-desc="把容量預測與值班分層綁在一起，降低高峰時段的升級混亂與恢復延遲。">LinkedIn：Capacity 與 On-call 分層</a></td>
          <td>JVM 服務的 capacity headroom 與 automated load test</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/06-reliability/cases/shopify/bfcm-capacity-and-game-day/" data-link-title="Shopify：BFCM 容量治理與 Game Day 驗證節奏" data-link-desc="把季節性流量峰值轉成年度可靠性流程，透過容量模型、演練與隔離策略提前吸收風險。">Shopify：BFCM 容量治理與 Game Day</a></td>
          <td>峰值準備期 scenario-driven load test 的對照組</td>
      </tr>
  </tbody>
</table>
<p><strong>待補 Gatling customer case</strong>：金融 / e-commerce 重度 JVM 生態採用 Gatling Enterprise、HAR-driven scenario recording 在 multi-step checkout flow 的實踐。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游概念：<a href="/blog/backend/06-reliability/performance-regression-gate/" data-link-title="6.13 Performance Regression Gate" data-link-desc="把效能 baseline 從一次性壓測變成持續對齊的 release gate，涵蓋 baseline 設定、判讀方法、variance 控制與退化定位">6.13 Performance Regression Gate</a></li>
<li>平行 vendor：<a href="/blog/backend/06-reliability/vendors/k6/" data-link-title="k6" data-link-desc="現代 load test、JS scripting、Grafana Labs">k6</a>、<a href="/blog/backend/06-reliability/vendors/locust/" data-link-title="Locust" data-link-desc="Python-based load test、distributed、易擴展">Locust</a>、<a href="/blog/backend/06-reliability/vendors/jmeter/" data-link-title="Apache JMeter" data-link-desc="老牌 load test 工具、GUI &#43; plugins">JMeter</a></li>
<li>下游能力：<a href="/blog/backend/09-performance-capacity/" data-link-title="模組九：效能工程與容量規劃" data-link-desc="把『目前配置能撐多少、要加多少機器』變成可量化、可驗證、可改進的工程流程">09 performance capacity</a> load test 模組</li>
</ul>
]]></content:encoded></item><item><title>incident.io</title><link>https://tarrragon.github.io/blog/backend/08-incident-response/vendors/incident-io/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/08-incident-response/vendors/incident-io/</guid><description>&lt;p>incident.io 是 Slack-native IR 平台、承擔三個責任：把 incident lifecycle 整合在 Slack 內（declare / respond / update / close / postmortem）、自動 timeline + action item tracking、後加 on-call 模組整合 paging。設計取捨偏向「Slack-first + lifecycle automation + 一站式」。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>incident.io 設計上把 &lt;em>Slack 當成 IR 工作台&lt;/em>、不需要在事故中切換 dashboard：宣告、角色指派、status update、stakeholder comms、timeline、action item、postmortem 全部在 Slack channel 完成、PM / leadership / customer-facing team 看 Slack 就能跟上節奏。2023 年起加上 incident.io On-call（取代 PagerDuty 的 alerting / schedule / escalation layer），從純 &lt;em>response orchestration&lt;/em> 變成完整 &lt;em>IR + on-call 平台&lt;/em>、減少 PagerDuty + Slack bot 雙系統的 state drift。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/vendors/pagerduty/" data-link-title="PagerDuty" data-link-desc="On-call / alerting 主流 SaaS、IR 平台演化">PagerDuty&lt;/a> 比、incident.io 是 &lt;em>response-first&lt;/em>、PagerDuty 是 &lt;em>paging-first&lt;/em>；組合使用時 PagerDuty 觸發 → incident.io 開 channel 跑 response、現在 On-call 模組讓 incident.io 也能獨立扛 paging layer。跟 &lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/vendors/firehydrant/" data-link-title="FireHydrant" data-link-desc="IR &amp;#43; retrospective 平台、Slack / Teams 整合、service catalog &amp;#43; runbook automation 為核心">FireHydrant&lt;/a> 比、兩者定位接近、差別在 incident.io 偏 &lt;em>opinionated workflow&lt;/em>（流程預設嚴謹、custom 餘地小）、FireHydrant 偏 &lt;em>customizable + Microsoft Teams 友善&lt;/em>。跟 &lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/vendors/rootly/" data-link-title="Rootly" data-link-desc="IR 自動化平台、no-code workflow &amp;#43; AI investigation、Slack-native &amp;#43; 200&amp;#43; integration">Rootly&lt;/a> 比、Rootly 強調 no-code workflow builder 跟 AI 補助、incident.io 強調 &lt;em>catalog-driven service ownership&lt;/em> 跟 learning review 結構化。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;ol>
&lt;li>整合 incident.io 到 Slack workspace&lt;/li>
&lt;li>配置 incident severity / role / status workflow&lt;/li>
&lt;li>設計 catalog（service / team metadata）&lt;/li>
&lt;li>用 post-incident flow 自動產 postmortem template&lt;/li>
&lt;li>評估 incident.io vs FireHydrant / Rootly、判斷是否要走 On-call 模組合併 PagerDuty&lt;/li>
&lt;/ol>
&lt;h2 id="最短判讀路徑">最短判讀路徑&lt;/h2>
&lt;p>判斷 incident.io deployment 是否健康、最少看四件事：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Slack workflow 完整度&lt;/strong>：&lt;code>/incident&lt;/code> declare 後是否自動開 channel、role bot prompt 是否觸發、status update reminder 是否進 Slack（不靠人記憶 cadence）、stakeholder 是否能在不進 incident channel 的前提下追進度（broadcast channel / status page mirror）&lt;/li>
&lt;li>&lt;strong>Incident type 設計&lt;/strong>：severity（SEV1-4）+ incident type（infra / security / customer-facing）+ role 三者是否清楚、severity 定義有沒有歧義（這條是大型 org 最常翻車的地方）&lt;/li>
&lt;li>&lt;strong>Role assignment 跟交接&lt;/strong>：commander / scribe / comms / SME 的角色定義、handoff 時 bot 是否 prompt、長 incident（&amp;gt;4hr）的 commander rotation 是否有 fallback&lt;/li>
&lt;li>&lt;strong>Post-incident learning&lt;/strong>：close 後是否自動產 postmortem skeleton、action item 是否 sync 到 Jira / Linear 並追完成率、learning review 是否在 N 天內走完（不是寫完 postmortem 就結案）&lt;/li>
&lt;/ul>
&lt;p>四件事任一缺失、就是 &lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/drills-and-oncall-readiness/" data-link-title="8.6 演練與值班能力建設" data-link-desc="用演練與值班訓練提升事故反應品質">Drills and On-call Readiness&lt;/a> 的待補項目。&lt;/p></description><content:encoded><![CDATA[<p>incident.io 是 Slack-native IR 平台、承擔三個責任：把 incident lifecycle 整合在 Slack 內（declare / respond / update / close / postmortem）、自動 timeline + action item tracking、後加 on-call 模組整合 paging。設計取捨偏向「Slack-first + lifecycle automation + 一站式」。</p>
<h2 id="服務定位">服務定位</h2>
<p>incident.io 設計上把 <em>Slack 當成 IR 工作台</em>、不需要在事故中切換 dashboard：宣告、角色指派、status update、stakeholder comms、timeline、action item、postmortem 全部在 Slack channel 完成、PM / leadership / customer-facing team 看 Slack 就能跟上節奏。2023 年起加上 incident.io On-call（取代 PagerDuty 的 alerting / schedule / escalation layer），從純 <em>response orchestration</em> 變成完整 <em>IR + on-call 平台</em>、減少 PagerDuty + Slack bot 雙系統的 state drift。</p>
<p>跟 <a href="/blog/backend/08-incident-response/vendors/pagerduty/" data-link-title="PagerDuty" data-link-desc="On-call / alerting 主流 SaaS、IR 平台演化">PagerDuty</a> 比、incident.io 是 <em>response-first</em>、PagerDuty 是 <em>paging-first</em>；組合使用時 PagerDuty 觸發 → incident.io 開 channel 跑 response、現在 On-call 模組讓 incident.io 也能獨立扛 paging layer。跟 <a href="/blog/backend/08-incident-response/vendors/firehydrant/" data-link-title="FireHydrant" data-link-desc="IR &#43; retrospective 平台、Slack / Teams 整合、service catalog &#43; runbook automation 為核心">FireHydrant</a> 比、兩者定位接近、差別在 incident.io 偏 <em>opinionated workflow</em>（流程預設嚴謹、custom 餘地小）、FireHydrant 偏 <em>customizable + Microsoft Teams 友善</em>。跟 <a href="/blog/backend/08-incident-response/vendors/rootly/" data-link-title="Rootly" data-link-desc="IR 自動化平台、no-code workflow &#43; AI investigation、Slack-native &#43; 200&#43; integration">Rootly</a> 比、Rootly 強調 no-code workflow builder 跟 AI 補助、incident.io 強調 <em>catalog-driven service ownership</em> 跟 learning review 結構化。</p>
<h2 id="本章目標">本章目標</h2>
<ol>
<li>整合 incident.io 到 Slack workspace</li>
<li>配置 incident severity / role / status workflow</li>
<li>設計 catalog（service / team metadata）</li>
<li>用 post-incident flow 自動產 postmortem template</li>
<li>評估 incident.io vs FireHydrant / Rootly、判斷是否要走 On-call 模組合併 PagerDuty</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 incident.io deployment 是否健康、最少看四件事：</p>
<ul>
<li><strong>Slack workflow 完整度</strong>：<code>/incident</code> declare 後是否自動開 channel、role bot prompt 是否觸發、status update reminder 是否進 Slack（不靠人記憶 cadence）、stakeholder 是否能在不進 incident channel 的前提下追進度（broadcast channel / status page mirror）</li>
<li><strong>Incident type 設計</strong>：severity（SEV1-4）+ incident type（infra / security / customer-facing）+ role 三者是否清楚、severity 定義有沒有歧義（這條是大型 org 最常翻車的地方）</li>
<li><strong>Role assignment 跟交接</strong>：commander / scribe / comms / SME 的角色定義、handoff 時 bot 是否 prompt、長 incident（&gt;4hr）的 commander rotation 是否有 fallback</li>
<li><strong>Post-incident learning</strong>：close 後是否自動產 postmortem skeleton、action item 是否 sync 到 Jira / Linear 並追完成率、learning review 是否在 N 天內走完（不是寫完 postmortem 就結案）</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/08-incident-response/drills-and-oncall-readiness/" data-link-title="8.6 演練與值班能力建設" data-link-desc="用演練與值班訓練提升事故反應品質">Drills and On-call Readiness</a> 的待補項目。</p>
<h2 id="最短路徑">最短路徑</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 1. Slack install incident.io app</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># 2. /incident declare 建第一個 incident</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="c1"># 3. 配置 severity / role</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 4. close + retrospective</span></span></span></code></pre></div><h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="slack-workflow">Slack workflow</h3>
<p>子議題：</p>
<ul>
<li><code>/incident</code> slash command</li>
<li>Auto-created channel（#inc-&hellip;）</li>
<li>Role assignment（commander / scribe / comms）</li>
<li>Bot prompts</li>
</ul>
<h3 id="catalog--post-incident-flow">Catalog + Post-incident flow</h3>
<p>子議題：</p>
<ul>
<li>Service / team / customer metadata</li>
<li>跟 <a href="/blog/backend/05-deployment-platform/" data-link-title="模組五：部署平台與網路入口" data-link-desc="整理 Kubernetes、systemd、load balancer、container 與服務生命週期合約">5 deployment service ownership</a> 對齊</li>
<li>Auto timeline from Slack</li>
<li>Action item sync 到 Jira / Linear</li>
<li>Postmortem template + learning review</li>
</ul>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>incident.io</th>
          <th>PagerDuty</th>
          <th>FireHydrant</th>
          <th>Rootly</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>主要 surface</td>
          <td>Slack-native</td>
          <td>Web / mobile app + 通知</td>
          <td>Slack + Microsoft Teams</td>
          <td>Slack 為主</td>
      </tr>
      <tr>
          <td>設計取向</td>
          <td>Opinionated workflow、流程預設嚴謹</td>
          <td>Paging-first、response 較淺</td>
          <td>Customizable workflow、Teams 友善</td>
          <td>No-code workflow builder + AI 補助</td>
      </tr>
      <tr>
          <td>Paging layer</td>
          <td>自家 On-call 模組（2023+）</td>
          <td>業界 paging 標準</td>
          <td>整合 PagerDuty / Opsgenie</td>
          <td>整合 PagerDuty / Opsgenie</td>
      </tr>
      <tr>
          <td>Catalog</td>
          <td>First-class、service ownership 強</td>
          <td>Service directory 較淺</td>
          <td>Functionality + service catalog</td>
          <td>Service catalog 中等</td>
      </tr>
      <tr>
          <td>Learning review</td>
          <td>Structured（內建 review cadence）</td>
          <td>Postmortems by PagerDuty（需另外 enable）</td>
          <td>Retrospectives 工作流</td>
          <td>Retrospectives + AI summary</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>Slack-heavy 中型 SaaS、流程要嚴謹</td>
          <td>大型 enterprise、paging-critical</td>
          <td>多 surface（Slack + Teams）、需要 custom 流程</td>
          <td>Slack-heavy、想用 AI 加速 retro / comms 撰寫</td>
      </tr>
  </tbody>
</table>
<p>選 incident.io 的核心訴求：<em>團隊已 Slack-heavy</em>、想要一套 <em>opinionated workflow</em> 把 IR 從「靠經驗」變成「靠流程」、且願意接受 catalog 維護成本換取 ownership clarity。</p>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<h3 id="workflowscustom-automation">Workflows（custom automation）</h3>
<p>子議題：trigger → condition → action 的低代碼自動化、severity-based auto-page、approval gate、跟外部 API 串接（呼叫 Jira / Linear / Statuspage）。重點是 workflow 進 Git 版控、change review 走 PR、不在 console 直改。</p>
<h3 id="catalogueservice-ownership--dependency">Catalogue（service ownership + dependency）</h3>
<p>子議題：incident.io Catalog 把 service / team / customer / region 等實體建模、incident 宣告時自動帶出 owner team + on-call 名單 + dependent service。對應 <a href="/blog/backend/05-deployment-platform/" data-link-title="模組五：部署平台與網路入口" data-link-desc="整理 Kubernetes、systemd、load balancer、container 與服務生命週期合約">5 deployment service ownership</a> 的 service catalog 概念；catalog stale 是常見 anti-pattern、要設 sync source（Backstage / Terraform / IdP group）+ stale alert。</p>
<h3 id="on-call-layer-integration2023">On-call layer integration（2023+）</h3>
<p>子議題：incident.io On-call 取代 PagerDuty 的 schedule + escalation + paging。優勢是 <em>single source of truth</em>（不需要 PagerDuty incident ↔ Slack channel state sync）、缺點是 paging reliability 還在追 PagerDuty 的 multi-region failover 成熟度。遷移時走 <em>parallel run</em>（兩邊都 page）2-4 週再切。</p>
<h3 id="status-page-integration">Status Page integration</h3>
<p>子議題：跟 <a href="/blog/backend/08-incident-response/vendors/atlassian-statuspage/" data-link-title="Atlassian Statuspage" data-link-desc="公開狀態頁 SaaS、Atlassian 出品、enterprise polish &#43; Atlassian 生態整合、subscriber notification &#43; component dependency 是核心責任">Atlassian Statuspage</a> / <a href="/blog/backend/08-incident-response/vendors/instatus/" data-link-title="Instatus" data-link-desc="輕量 status page SaaS、現代 UI、價格敏感替代">Instatus</a> 整合、auto-sync incident status 到 public page、避免 SRE 手動雙寫造成 stakeholder 看到的狀態跟內部不一致。</p>
<h3 id="ai-investigation-features2024">AI investigation features（2024+）</h3>
<p>子議題：AI summarizer（自動產 incident summary 給 leadership）、suggested actions、postmortem draft。要當 <em>first draft</em> 不是 <em>source of truth</em>、commander 仍負責最終敘事。</p>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<ul>
<li><strong>Slack outage 時 fallback</strong>：incident.io 重度依賴 Slack、Slack 自身 outage 時 IR 工作台會跟著掛 — 要預先準備 <em>out-of-band channel</em>（Zoom war room / Google Meet / 手機群組）、commander handoff 流程要寫進 runbook、不能假設 Slack 永遠在</li>
<li><strong>Slack app 沒回應</strong>：bot offline / permission scope 不足 / workspace admin 改了 app 權限 — 檢查 incident.io admin console 的 health status</li>
<li><strong>Incident type 設計過細</strong>：SEV 1-5 + 10 種 type + 20 個 role 結果沒人記得選哪個、宣告時 friction 太高反而延遲 declare — 收斂到 3-4 種 type、severity 限 4 級、role 預設帶入</li>
<li><strong>Incident type 設計過粗</strong>：所有事故都 SEV2、escalation criteria 不明 — 要寫 <em>severity definition doc</em>、附判讀範例（customer-facing impact / data loss risk / blast radius）</li>
<li><strong>Severity 沒對齊</strong>：team severity definition 不一致、設 catalog default + 在 Slack 宣告時 bot 自動 quote 定義</li>
<li><strong>Catalog stale</strong>：service owner 離職沒更新、dependency 改了沒同步 — 要從 IdP group / Terraform / Backstage sync、設 <em>stale threshold</em>（&gt;90 天沒更新就 alert owner team）</li>
<li><strong>Action item drift</strong>：sync to Jira 失敗 / ownership 不明 — 在 close incident 前 bot 強制要求每個 action item 都有 owner + due date + Jira ticket</li>
<li><strong>Postmortem 沒做</strong>：close 後 prompt 沒觸發 / template 太複雜 — 把 template 縮到 5 個必填欄位、其餘 optional、用 AI draft 降低 friction</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Microsoft Teams</td>
          <td><a href="/blog/backend/08-incident-response/vendors/firehydrant/" data-link-title="FireHydrant" data-link-desc="IR &#43; retrospective 平台、Slack / Teams 整合、service catalog &#43; runbook automation 為核心">FireHydrant</a></td>
      </tr>
      <tr>
          <td>No-code workflow / AI</td>
          <td><a href="/blog/backend/08-incident-response/vendors/rootly/" data-link-title="Rootly" data-link-desc="IR 自動化平台、no-code workflow &#43; AI investigation、Slack-native &#43; 200&#43; integration">Rootly</a></td>
      </tr>
      <tr>
          <td>Paging-first</td>
          <td><a href="/blog/backend/08-incident-response/vendors/pagerduty/" data-link-title="PagerDuty" data-link-desc="On-call / alerting 主流 SaaS、IR 平台演化">PagerDuty</a></td>
      </tr>
      <tr>
          <td>自建 Slack workflow</td>
          <td>Slack workflow + GitHub Issues / Linear</td>
      </tr>
      <tr>
          <td>Learning-focused</td>
          <td><a href="/blog/backend/08-incident-response/vendors/jeli/" data-link-title="Jeli" data-link-desc="Post-incident learning 平台、2023 被 PagerDuty 收購、強調 interview-driven narrative 而非 timeline-only retro">Jeli</a>（PagerDuty 整合）</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Slack app 完整 spec / Custom workflow 細節 / Pricing</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p><strong>incident.io 主打 Slack-native IR</strong>：本案例庫尚無直接揭露 incident.io 使用細節的事故；可參照的閱讀脈絡是「以 Slack 為主要協作通道、事故 channel + 公開 status 同步運作」的服務、典型客戶側 profile 是 <em>Slack-heavy 中型 SaaS organization</em>、IR 流程強調 collaboration 跟 learning 而非單純 paging。</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>對應主題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/08-incident-response/cases/slack/" data-link-title="Slack" data-link-desc="Slack 通訊服務事故與外部狀態頁設計">Slack cases</a></td>
          <td>通訊平台失效時 IR channel 的退路設計</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/08-incident-response/cases/discord/" data-link-title="Discord" data-link-desc="Discord Gateway scale-out 事故與容量驚奇">Discord cases</a></td>
          <td>即時通訊產品事故的多通道協作節奏（對照素材）</td>
      </tr>
  </tbody>
</table>
<p>待補 candidate：Lightspeed / Linear / Etsy 等 incident.io 公開 customer story。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/08-incident-response/drills-and-oncall-readiness/" data-link-title="8.6 演練與值班能力建設" data-link-desc="用演練與值班訓練提升事故反應品質">Drills and On-call Readiness</a></li>
<li>平行：<a href="/blog/backend/08-incident-response/vendors/firehydrant/" data-link-title="FireHydrant" data-link-desc="IR &#43; retrospective 平台、Slack / Teams 整合、service catalog &#43; runbook automation 為核心">FireHydrant</a>、<a href="/blog/backend/08-incident-response/vendors/rootly/" data-link-title="Rootly" data-link-desc="IR 自動化平台、no-code workflow &#43; AI investigation、Slack-native &#43; 200&#43; integration">Rootly</a></li>
<li>下游：<a href="/blog/backend/08-incident-response/incident-evidence-write-back/" data-link-title="8.22 Incident Evidence Write-back" data-link-desc="把事故證據、決策與復盤結論回寫到 observability、reliability 與 runbook">8.22 Incident Evidence Write-back</a></li>
</ul>
]]></content:encoded></item><item><title>nginx</title><link>https://tarrragon.github.io/blog/backend/05-deployment-platform/vendors/nginx/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/05-deployment-platform/vendors/nginx/</guid><description>&lt;p>nginx 是 HTTP server / reverse proxy / load balancer 的事實標準之一、承擔三個責任：HTTP 7 層處理（reverse proxy / TLS termination / static content）、L4 / L7 load balancing、Kubernetes ingress controller（ingress-nginx）。設計取捨偏向「配置簡單 + 效能穩定 + reload 機制成熟」、跟 envoy 比是靜態 config-driven（無 dynamic xDS）。F5 收購後 nginx Plus 是商業版、社群 fork 有 Freenginx / angie。&lt;/p>
&lt;p>對「HTTP reverse proxy / LB、TLS termination、K8s ingress、API gateway 入門」這條路徑、nginx 是穩定首選。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>寫 nginx config（server / location / upstream）&lt;/li>
&lt;li>配置 TLS / mTLS + SNI&lt;/li>
&lt;li>設計 rate limiting + connection limit&lt;/li>
&lt;li>部署 ingress-nginx 到 Kubernetes&lt;/li>
&lt;li>評估 nginx vs nginx Plus / OSS fork（Freenginx / angie）&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑5-分鐘把-nginx-跑起來">最短路徑：5 分鐘把 nginx 跑起來&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 1. 啟動 nginx（docker）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">docker run -d --name nginx-demo -p 80:80 &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> -v &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>&lt;span class="nb">pwd&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">/nginx.conf:/etc/nginx/nginx.conf:ro&amp;#34;&lt;/span> nginx:stable-alpine
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">&lt;span class="c1"># 2. 寫 reverse proxy config（nginx.conf 範例）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">cat &lt;span class="s">&amp;lt;&amp;lt;&amp;#39;CONF&amp;#39; &amp;gt; nginx.conf
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="s">events { worker_connections 1024; }
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="s">http {
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="s"> upstream backend {
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="s"> server app:8080;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">&lt;span class="s"> }
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">&lt;span class="s"> server {
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">&lt;span class="s"> listen 80;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">&lt;span class="s"> location / {
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl">&lt;span class="s"> proxy_pass http://backend;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl">&lt;span class="s"> proxy_set_header Host $host;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl">&lt;span class="s"> proxy_set_header X-Real-IP $remote_addr;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl">&lt;span class="s"> }
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl">&lt;span class="s"> }
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl">&lt;span class="s">}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl">&lt;span class="s">CONF&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">22&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">23&lt;/span>&lt;span class="cl">&lt;span class="c1"># 3. reload + 驗證&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">24&lt;/span>&lt;span class="cl">nginx -t &lt;span class="c1"># test config syntax&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">25&lt;/span>&lt;span class="cl">nginx -s reload &lt;span class="c1"># reload without restart（zero-downtime config update）&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="日常操作與決策形狀">日常操作與決策形狀&lt;/h2>
&lt;h3 id="nginx-config-設計">nginx config 設計&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>階層：events / http / server / location / upstream&lt;/li>
&lt;li>變數：$host / $remote_addr / $http_&lt;name>&lt;/li>
&lt;li>Include 拆分大 config&lt;/li>
&lt;li>對應指令：&lt;code>nginx -T&lt;/code>（dump full config）、&lt;code>nginx -t&lt;/code>（test）、&lt;code>nginx -s reload&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="reverse-proxy-配置">Reverse proxy 配置&lt;/h3>
&lt;p>子議題：&lt;/p></description><content:encoded><![CDATA[<p>nginx 是 HTTP server / reverse proxy / load balancer 的事實標準之一、承擔三個責任：HTTP 7 層處理（reverse proxy / TLS termination / static content）、L4 / L7 load balancing、Kubernetes ingress controller（ingress-nginx）。設計取捨偏向「配置簡單 + 效能穩定 + reload 機制成熟」、跟 envoy 比是靜態 config-driven（無 dynamic xDS）。F5 收購後 nginx Plus 是商業版、社群 fork 有 Freenginx / angie。</p>
<p>對「HTTP reverse proxy / LB、TLS termination、K8s ingress、API gateway 入門」這條路徑、nginx 是穩定首選。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>寫 nginx config（server / location / upstream）</li>
<li>配置 TLS / mTLS + SNI</li>
<li>設計 rate limiting + connection limit</li>
<li>部署 ingress-nginx 到 Kubernetes</li>
<li>評估 nginx vs nginx Plus / OSS fork（Freenginx / angie）</li>
</ol>
<h2 id="最短路徑5-分鐘把-nginx-跑起來">最短路徑：5 分鐘把 nginx 跑起來</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># 1. 啟動 nginx（docker）</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">docker run -d --name nginx-demo -p 80:80 <span class="se">\
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="se"></span>  -v <span class="s2">&#34;</span><span class="k">$(</span><span class="nb">pwd</span><span class="k">)</span><span class="s2">/nginx.conf:/etc/nginx/nginx.conf:ro&#34;</span> nginx:stable-alpine
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="c1"># 2. 寫 reverse proxy config（nginx.conf 範例）</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">cat <span class="s">&lt;&lt;&#39;CONF&#39; &gt; nginx.conf
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="s">events { worker_connections 1024; }
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="s">http {
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="s">  upstream backend {
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="s">    server app:8080;
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="s">  }
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="s">  server {
</span></span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="s">    listen 80;
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="s">    location / {
</span></span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="s">      proxy_pass http://backend;
</span></span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="s">      proxy_set_header Host $host;
</span></span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="s">      proxy_set_header X-Real-IP $remote_addr;
</span></span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="s">    }
</span></span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="s">  }
</span></span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="s">}
</span></span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="s">CONF</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">
</span></span><span class="line"><span class="ln">23</span><span class="cl"><span class="c1"># 3. reload + 驗證</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">nginx -t            <span class="c1"># test config syntax</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">nginx -s reload     <span class="c1"># reload without restart（zero-downtime config update）</span></span></span></code></pre></div><h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="nginx-config-設計">nginx config 設計</h3>
<p>子議題：</p>
<ul>
<li>階層：events / http / server / location / upstream</li>
<li>變數：$host / $remote_addr / $http_<name></li>
<li>Include 拆分大 config</li>
<li>對應指令：<code>nginx -T</code>（dump full config）、<code>nginx -t</code>（test）、<code>nginx -s reload</code></li>
</ul>
<h3 id="reverse-proxy-配置">Reverse proxy 配置</h3>
<p>子議題：</p>
<ul>
<li>proxy_pass / proxy_set_header / proxy_http_version</li>
<li>proxy_buffering / proxy_request_buffering</li>
<li>upstream load balancing（round_robin / least_conn / ip_hash）</li>
<li>對應 <a href="/blog/backend/05-deployment-platform/load-balancer-contract/" data-link-title="5.3 load balancer 合約" data-link-desc="整理 idle timeout、draining 與 health check">5.3 LB contract</a></li>
</ul>
<h3 id="tls-termination">TLS termination</h3>
<p>子議題：</p>
<ul>
<li>ssl_certificate / ssl_certificate_key / ssl_protocols</li>
<li>SNI（server_name + listen 443 ssl）</li>
<li>mTLS：ssl_client_certificate + ssl_verify_client</li>
<li>對應 <a href="/blog/backend/07-security-data-protection/" data-link-title="模組七：資安與資料保護" data-link-desc="以問題驅動方式擴充資安知識網：先定義服務環節問題，再以案例作為觸發式參考">07 security</a> TLS 章</li>
</ul>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<h3 id="rate-limiting--connection-limit">Rate limiting / connection limit</h3>
<p>子議題：</p>
<ul>
<li>limit_req_zone + limit_req（leaky bucket）</li>
<li>limit_conn_zone + limit_conn</li>
<li>跟 <a href="/blog/backend/knowledge-cards/rate-limit/" data-link-title="Rate Limit" data-link-desc="說明限流如何保護服務入口、下游依賴與租戶公平性">knowledge cards rate-limit</a> 對照</li>
<li>對應威脅建模: <a href="/blog/backend/02-cache-redis/attacker-view-cache-risks/" data-link-title="2.6 快取威脅建模（Threat Modeling）" data-link-desc="從快取污染、一致性偏移與流量放大風險，盤點 cache/redis 的主要弱點">2.6 快取威脅建模</a></li>
</ul>
<h3 id="ingress-nginx-for-kubernetes">ingress-nginx for Kubernetes</h3>
<p>子議題：</p>
<ul>
<li>Helm chart 部署</li>
<li>Ingress resource + Annotations 配置</li>
<li>ConfigMap + Snippets（power users）</li>
<li>跟 <a href="/blog/backend/05-deployment-platform/vendors/traefik/" data-link-title="Traefik" data-link-desc="Cloud-native ingress / reverse proxy、auto-discovery">Traefik</a> / Gateway API 對比</li>
</ul>
<h3 id="openresty--lua-extension">OpenResty / Lua extension</h3>
<p>子議題：</p>
<ul>
<li>OpenResty：nginx + LuaJIT、可寫 Lua handler</li>
<li>ngx_lua: access / content / log phase handler</li>
<li>適合：自訂 auth / dynamic routing</li>
<li>對應 envoy WASM extension 對比</li>
</ul>
<h3 id="nginx-vs-nginx-plus--freenginx--angie">nginx vs nginx Plus / Freenginx / angie</h3>
<p>子議題：</p>
<ul>
<li>nginx OSS（F5 維護）：basic feature</li>
<li>nginx Plus（商業）：active health check / dynamic config API / DNS upstream</li>
<li>Freenginx：2024 社群 fork（不滿 F5 治理）</li>
<li>angie：另一個 fork、多 commercial extension</li>
<li>選擇判讀：dynamic config 重要 → 看 Envoy / Plus；OSS 純社群 → Freenginx / angie</li>
</ul>
<h3 id="performance-tuning">Performance tuning</h3>
<p>子議題：</p>
<ul>
<li>worker_processes / worker_connections</li>
<li>keepalive_timeout / keepalive_requests</li>
<li>sendfile / tcp_nopush / tcp_nodelay</li>
<li>跟 <a href="/blog/backend/09-performance-capacity/" data-link-title="模組九：效能工程與容量規劃" data-link-desc="把『目前配置能撐多少、要加多少機器』變成可量化、可驗證、可改進的工程流程">09 performance capacity</a> 對照</li>
</ul>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<h3 id="502-bad-gateway">502 Bad Gateway</h3>
<p>操作原則：upstream 不可達 / 回應錯。判讀：<code>error.log</code> + upstream health。</p>
<h3 id="504-gateway-timeout">504 Gateway Timeout</h3>
<p>操作原則：proxy_read_timeout / proxy_send_timeout 超過。判讀：upstream 處理時間 vs timeout 配置。</p>
<h3 id="connection-limit--502-under-load">Connection limit / 502 under load</h3>
<p>操作原則：worker_connections 不夠、ephemeral port 耗盡、upstream keepalive 不對。判讀：<code>netstat</code> + nginx stub_status。</p>
<h3 id="ssl-handshake-failure">SSL handshake failure</h3>
<p>操作原則：cipher / protocol mismatch、cert chain incomplete、SNI 不對。判讀：<code>openssl s_client -connect host:443 -servername host</code>。</p>
<h3 id="reload-不生效">Reload 不生效</h3>
<p>操作原則：<code>nginx -t</code> 先 test、新 worker 起來舊 worker drain。若行為怪、檢查是否拿到舊 listening socket。</p>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Dynamic config / xDS</td>
          <td><a href="/blog/backend/05-deployment-platform/vendors/envoy/" data-link-title="Envoy" data-link-desc="Cloud-native service proxy、xDS dynamic config、Istio / Gateway 底層">Envoy</a></td>
      </tr>
      <tr>
          <td>Cloud-native auto-discovery</td>
          <td><a href="/blog/backend/05-deployment-platform/vendors/traefik/" data-link-title="Traefik" data-link-desc="Cloud-native ingress / reverse proxy、auto-discovery">Traefik</a></td>
      </tr>
      <tr>
          <td>AWS managed</td>
          <td><a href="/blog/backend/05-deployment-platform/vendors/aws-elb/" data-link-title="AWS ELB（ALB / NLB / CLB）" data-link-desc="AWS managed load balancer、ALB（L7）/ NLB（L4）/ CLB（legacy）">AWS ELB</a>（ALB / NLB）</td>
      </tr>
      <tr>
          <td>L4 為主 / 高吞吐</td>
          <td>HAProxy / NLB</td>
      </tr>
      <tr>
          <td>Service mesh</td>
          <td>Istio / Linkerd / Consul Connect</td>
      </tr>
      <tr>
          <td>API Gateway 進階</td>
          <td>Kong / Tyk / Apigee</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>完整 nginx directive reference</li>
<li>ngx_lua / OpenResty 完整教學</li>
<li>各 distro nginx 版本差異</li>
<li>nginx internal architecture</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<h3 id="跨-vendor-對照">跨 vendor 對照</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>對 nginx 的對應</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/05-deployment-platform/cases/failure-platform-cutover-without-drain/" data-link-title="5.C9 反例：平台切流未先 Draining" data-link-desc="切流時忽略連線清退造成請求錯誤與重試風暴。">5.C9 cutover without drain</a></td>
          <td>切流時 nginx upstream / ingress-nginx 沒做 graceful drain、長連線跟 5xx 一起放大</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/05-deployment-platform/cases/contrast-platform-migration-by-scale/" data-link-title="5.C10 對照：規模差異下的平台遷移" data-link-desc="平台遷移策略在小中大型組織下的差異。">5.C10 規模對照</a></td>
          <td>小型直接 nginx reverse proxy、中型走 ingress-nginx、大型才考慮 envoy 或 service mesh</td>
      </tr>
  </tbody>
</table>
<p><strong>待補 nginx 案例</strong>：Cloudflare 為何 fork（freenginx）、大規模 ingress-nginx 客戶案例、OpenResty 在 production 的擴展案例。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游概念：<a href="/blog/backend/05-deployment-platform/load-balancer-contract/" data-link-title="5.3 load balancer 合約" data-link-desc="整理 idle timeout、draining 與 health check">5.3 LB Contract</a></li>
<li>平行 vendor：<a href="/blog/backend/05-deployment-platform/vendors/envoy/" data-link-title="Envoy" data-link-desc="Cloud-native service proxy、xDS dynamic config、Istio / Gateway 底層">Envoy</a>、<a href="/blog/backend/05-deployment-platform/vendors/traefik/" data-link-title="Traefik" data-link-desc="Cloud-native ingress / reverse proxy、auto-discovery">Traefik</a>、<a href="/blog/backend/05-deployment-platform/vendors/aws-elb/" data-link-title="AWS ELB（ALB / NLB / CLB）" data-link-desc="AWS managed load balancer、ALB（L7）/ NLB（L4）/ CLB（legacy）">AWS ELB</a></li>
<li>下游能力：<a href="/blog/backend/07-security-data-protection/" data-link-title="模組七：資安與資料保護" data-link-desc="以問題驅動方式擴充資安知識網：先定義服務環節問題，再以案例作為觸發式參考">07 security</a>（TLS / WAF）、<a href="/blog/backend/09-performance-capacity/" data-link-title="模組九：效能工程與容量規劃" data-link-desc="把『目前配置能撐多少、要加多少機器』變成可量化、可驗證、可改進的工程流程">09 performance</a></li>
</ul>
]]></content:encoded></item><item><title>Redis Streams</title><link>https://tarrragon.github.io/blog/backend/03-message-queue/vendors/redis-streams/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/03-message-queue/vendors/redis-streams/</guid><description>&lt;p>Redis Streams 是 Redis 5.0 引入的 append-only log data type、承擔三個責任：輕量 event stream（XADD / XREAD）、consumer group 與 pending entries list（XREADGROUP / XACK）、Redis 生態內整合（避免額外引入 Kafka）。設計取捨偏向「跟 Redis 本體生命週期綁定、低延遲 + 記憶體成本、適合中等規模」。Redis vendor 細節見 &lt;a href="https://tarrragon.github.io/blog/backend/02-cache-redis/vendors/redis/" data-link-title="Redis" data-link-desc="OSS in-memory data structure store、cache 主流">02 redis&lt;/a>。&lt;/p>
&lt;p>對「已用 Redis、需要輕量 stream、不想引入額外基礎設施」這條路徑、Redis Streams 是務實選擇。本頁先給最短路徑、再展開日常 XADD/XREAD 操作與 consumer group 設計、最後進階治理（PEL、retention、Cluster 影響）跟排錯。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>用 redis-cli XADD / XREAD 操作 stream&lt;/li>
&lt;li>設計 consumer group + XCLAIM 處理 consumer 失敗的訊息接管&lt;/li>
&lt;li>看懂 pending entries list（PEL）累積訊號、定位 consumer 健康&lt;/li>
&lt;li>設計 MAXLEN / MINID retention 對齊記憶體預算&lt;/li>
&lt;li>評估 Redis Cluster 對 Streams 的影響與限制&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑5-分鐘把-redis-streams-跑起來">最短路徑：5 分鐘把 Redis Streams 跑起來&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 1. 啟動 Redis（已有 Redis 跳過）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">docker run -d --name redis -p 6379:6379 redis:7
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="c1"># 2. XADD 寫入 stream（&amp;#39;*&amp;#39; 由 Redis 產生遞增 entry ID）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">docker &lt;span class="nb">exec&lt;/span> redis redis-cli XADD mystream &lt;span class="s1">&amp;#39;*&amp;#39;&lt;/span> field1 value1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="c1"># 3. XREAD 讀取（從 0 起讀、最多 10 筆）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">docker &lt;span class="nb">exec&lt;/span> redis redis-cli XREAD COUNT &lt;span class="m">10&lt;/span> STREAMS mystream &lt;span class="m">0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="c1"># 4. 建 consumer group 後用 group 模式讀（&amp;#39;&amp;gt;&amp;#39; 取未投遞訊息、進 PEL 等 ack）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">docker &lt;span class="nb">exec&lt;/span> redis redis-cli XGROUP CREATE mystream mygroup &lt;span class="m">0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">docker &lt;span class="nb">exec&lt;/span> redis redis-cli XREADGROUP GROUP mygroup consumer1 COUNT &lt;span class="m">10&lt;/span> STREAMS mystream &lt;span class="s1">&amp;#39;&amp;gt;&amp;#39;&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>最短路徑驗證「Redis 起來、stream 能寫能讀」。實際用 consumer group 場景見&lt;a href="#%e6%97%a5%e5%b8%b8%e6%93%8d%e4%bd%9c%e8%88%87%e6%b1%ba%e7%ad%96%e5%bd%a2%e7%8b%80">日常操作&lt;/a>。&lt;/p>
&lt;h2 id="日常操作與決策形狀">日常操作與決策形狀&lt;/h2>
&lt;h3 id="xadd--xread--xreadgroup">XADD / XREAD / XREADGROUP&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>XADD：寫入 entry、&lt;code>*&lt;/code> 自動 ID vs 手動 ID&lt;/li>
&lt;li>XREAD：簡單讀取（無 consumer group、適合單 consumer）&lt;/li>
&lt;li>XREADGROUP：consumer group 模式、配合 ACK&lt;/li>
&lt;li>對應指令範例：&lt;code>XADD&lt;/code>、&lt;code>XREAD&lt;/code>、&lt;code>XREADGROUP&lt;/code>、&lt;code>XACK&lt;/code>、&lt;code>XPENDING&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="consumer-group-與-pel">Consumer group 與 PEL&lt;/h3>
&lt;p>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/consumer-group/" data-link-title="Consumer Group" data-link-desc="說明一組 consumer 如何共同分攤 stream 或 topic 的處理責任">Consumer group&lt;/a> 是 Streams 的核心抽象、配合 Pending Entries List（PEL）追蹤未 ack 訊息。子議題：&lt;/p></description><content:encoded><![CDATA[<p>Redis Streams 是 Redis 5.0 引入的 append-only log data type、承擔三個責任：輕量 event stream（XADD / XREAD）、consumer group 與 pending entries list（XREADGROUP / XACK）、Redis 生態內整合（避免額外引入 Kafka）。設計取捨偏向「跟 Redis 本體生命週期綁定、低延遲 + 記憶體成本、適合中等規模」。Redis vendor 細節見 <a href="/blog/backend/02-cache-redis/vendors/redis/" data-link-title="Redis" data-link-desc="OSS in-memory data structure store、cache 主流">02 redis</a>。</p>
<p>對「已用 Redis、需要輕量 stream、不想引入額外基礎設施」這條路徑、Redis Streams 是務實選擇。本頁先給最短路徑、再展開日常 XADD/XREAD 操作與 consumer group 設計、最後進階治理（PEL、retention、Cluster 影響）跟排錯。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>用 redis-cli XADD / XREAD 操作 stream</li>
<li>設計 consumer group + XCLAIM 處理 consumer 失敗的訊息接管</li>
<li>看懂 pending entries list（PEL）累積訊號、定位 consumer 健康</li>
<li>設計 MAXLEN / MINID retention 對齊記憶體預算</li>
<li>評估 Redis Cluster 對 Streams 的影響與限制</li>
</ol>
<h2 id="最短路徑5-分鐘把-redis-streams-跑起來">最短路徑：5 分鐘把 Redis Streams 跑起來</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># 1. 啟動 Redis（已有 Redis 跳過）</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">docker run -d --name redis -p 6379:6379 redis:7
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c1"># 2. XADD 寫入 stream（&#39;*&#39; 由 Redis 產生遞增 entry ID）</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">docker <span class="nb">exec</span> redis redis-cli XADD mystream <span class="s1">&#39;*&#39;</span> field1 value1
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="c1"># 3. XREAD 讀取（從 0 起讀、最多 10 筆）</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">docker <span class="nb">exec</span> redis redis-cli XREAD COUNT <span class="m">10</span> STREAMS mystream <span class="m">0</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="c1"># 4. 建 consumer group 後用 group 模式讀（&#39;&gt;&#39; 取未投遞訊息、進 PEL 等 ack）</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">docker <span class="nb">exec</span> redis redis-cli XGROUP CREATE mystream mygroup <span class="m">0</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">docker <span class="nb">exec</span> redis redis-cli XREADGROUP GROUP mygroup consumer1 COUNT <span class="m">10</span> STREAMS mystream <span class="s1">&#39;&gt;&#39;</span></span></span></code></pre></div><p>最短路徑驗證「Redis 起來、stream 能寫能讀」。實際用 consumer group 場景見<a href="#%e6%97%a5%e5%b8%b8%e6%93%8d%e4%bd%9c%e8%88%87%e6%b1%ba%e7%ad%96%e5%bd%a2%e7%8b%80">日常操作</a>。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="xadd--xread--xreadgroup">XADD / XREAD / XREADGROUP</h3>
<p>子議題：</p>
<ul>
<li>XADD：寫入 entry、<code>*</code> 自動 ID vs 手動 ID</li>
<li>XREAD：簡單讀取（無 consumer group、適合單 consumer）</li>
<li>XREADGROUP：consumer group 模式、配合 ACK</li>
<li>對應指令範例：<code>XADD</code>、<code>XREAD</code>、<code>XREADGROUP</code>、<code>XACK</code>、<code>XPENDING</code></li>
</ul>
<h3 id="consumer-group-與-pel">Consumer group 與 PEL</h3>
<p><a href="/blog/backend/knowledge-cards/consumer-group/" data-link-title="Consumer Group" data-link-desc="說明一組 consumer 如何共同分攤 stream 或 topic 的處理責任">Consumer group</a> 是 Streams 的核心抽象、配合 Pending Entries List（PEL）追蹤未 ack 訊息。子議題：</p>
<ul>
<li>XGROUP CREATE / SETID / DESTROY</li>
<li>XACK：明確 ack</li>
<li>XPENDING：查 PEL 狀態</li>
<li>XCLAIM / XAUTOCLAIM：consumer 失敗時接管訊息</li>
</ul>
<h3 id="retentionmaxlen--minid">Retention：MAXLEN / MINID</h3>
<p>子議題：</p>
<ul>
<li>MAXLEN：保留最近 N 個 entry（近似或精確）</li>
<li>MINID：保留 ID 大於某值的 entry</li>
<li>XADD 寫入時帶 MAXLEN（最常用）</li>
<li>XTRIM 手動修剪</li>
</ul>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<p>PEL 失敗接管、retention 與 cluster 影響已展開為 deep article：<a href="xclaim-pel-recovery/">XCLAIM/PEL 失敗接管與 cluster 影響</a>。下列子議題段保留選題判讀入口。</p>
<h3 id="xclaim-與-consumer-失敗接管">XCLAIM 與 consumer 失敗接管</h3>
<p>子議題：</p>
<ul>
<li>Idle time 判讀（min-idle-time 參數）</li>
<li>XAUTOCLAIM（Redis 6.2+、自動接管）</li>
<li>接管後的去重責任（仍需 <a href="/blog/backend/knowledge-cards/idempotency/" data-link-title="Idempotency" data-link-desc="說明同一操作執行多次時如何保持結果一致">idempotency</a>）</li>
</ul>
<h3 id="memory-與-retention-取捨">Memory 與 retention 取捨</h3>
<p>子議題：</p>
<ul>
<li>Stream 佔用 Redis 記憶體、MAXLEN 是主要旋鈕</li>
<li>近似修剪（<code>~</code> 標記）vs 精確修剪的性能差異</li>
<li>配合 <code>maxmemory-policy</code> 與 eviction（注意 stream 不會被 eviction）</li>
</ul>
<h3 id="redis-cluster-對-streams-的影響">Redis Cluster 對 Streams 的影響</h3>
<p>子議題：</p>
<ul>
<li>Stream key 只在單一 shard（無 partition 概念）</li>
<li>多 stream 跨 shard 的設計（用 hash tag 控制分布）</li>
<li>Cluster failover 對 PEL 一致性的影響</li>
</ul>
<h3 id="stream--functionsredis-7">Stream + Functions（Redis 7+）</h3>
<p>子議題：</p>
<ul>
<li>Redis Functions（取代 Lua scripting）</li>
<li>Stream 處理寫成 Redis-side function</li>
<li>適用 / 不適用場景</li>
</ul>
<h3 id="redis-sentinel--cluster-對可靠性的影響">Redis Sentinel / Cluster 對可靠性的影響</h3>
<p>子議題：</p>
<ul>
<li>Replication lag 對 Streams 一致性的影響</li>
<li>AOF 與 RDB 對 Stream 持久化的差異</li>
<li>Failover 期間 PEL 是否完整</li>
</ul>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<h3 id="pel-累積xpending-數字持續增長">PEL 累積（XPENDING 數字持續增長）</h3>
<p>操作原則：先看是單一 consumer 還是整 group 都累積、再定位 consumer 失敗 vs ACK 漏寫。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">redis-cli XPENDING mystream mygroup
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># 回傳 PEL 總數 + 每個 consumer 的待 ack 數、定位累積集中在哪個 consumer</span></span></span></code></pre></div><p>判讀路徑：consumer crash 沒 ACK → consumer 慢 → ACK 程式碼漏寫。</p>
<h3 id="memory-pressurestream-佔用過大">Memory pressure（stream 佔用過大）</h3>
<p>操作原則：MAXLEN 沒設或設太大、stream 持續增長。判讀：用 <code>MEMORY USAGE</code> 看 stream 佔用、調整 MAXLEN。</p>
<h3 id="跨-shard-stream-限制">跨 shard stream 限制</h3>
<p>操作原則：Streams 不支援 partition、單 stream 受單 shard 容量限制。設計：用 hash tag 強制分散到多 stream。</p>
<h3 id="consumer-重平衡無原生機制">Consumer 重平衡（無原生機制）</h3>
<p>操作原則：consumer group 沒有自動 rebalance、要手動 XCLAIM 接管。看 idle time 與 XPENDING 判斷該接管哪些。</p>
<h3 id="failover-後-pel-不一致">Failover 後 PEL 不一致</h3>
<p>操作原則：Sentinel / Cluster failover 後、replica 升 primary、PEL 可能不完整。對應 <a href="/blog/backend/03-message-queue/cases/failure-queue-semantics-mismatch-cutover/" data-link-title="3.C9 反例：Queue 語義切換誤配" data-link-desc="at-least-once / exactly-once 語義誤配導致資料重複與遺漏。">3.C9 語義誤配</a> 的思路。</p>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>高吞吐 / 長期 retention</td>
          <td><a href="/blog/backend/03-message-queue/vendors/kafka/" data-link-title="Apache Kafka" data-link-desc="Distributed event streaming platform、log-based 模型">Kafka</a></td>
      </tr>
      <tr>
          <td>複雜 routing</td>
          <td><a href="/blog/backend/03-message-queue/vendors/rabbitmq/" data-link-title="RabbitMQ" data-link-desc="Classic message broker、AMQP routing 為主">RabbitMQ</a></td>
      </tr>
      <tr>
          <td>跨節點 stream（partition + replication）</td>
          <td><a href="/blog/backend/03-message-queue/vendors/kafka/" data-link-title="Apache Kafka" data-link-desc="Distributed event streaming platform、log-based 模型">Kafka</a> / Pulsar</td>
      </tr>
      <tr>
          <td>輕量 messaging（不需 Redis）</td>
          <td><a href="/blog/backend/03-message-queue/vendors/nats/" data-link-title="NATS" data-link-desc="Lightweight messaging、JetStream 加持久化與 streams">NATS</a></td>
      </tr>
      <tr>
          <td>Managed queue</td>
          <td><a href="/blog/backend/03-message-queue/vendors/aws-sqs/" data-link-title="AWS SQS" data-link-desc="AWS managed queue、簡單可靠、無 ordering（standard）">SQS</a> / <a href="/blog/backend/03-message-queue/vendors/google-pubsub/" data-link-title="Google Cloud Pub/Sub" data-link-desc="GCP managed pub/sub、global routing、push/pull">Pub/Sub</a></td>
      </tr>
      <tr>
          <td>Redis Pub/Sub（fire-and-forget）</td>
          <td>Redis Pub/Sub（同 Redis、不持久化）</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Redis 本體運維（見 <a href="/blog/backend/02-cache-redis/vendors/redis/" data-link-title="Redis" data-link-desc="OSS in-memory data structure store、cache 主流">02 cache 模組 redis vendor</a>）</li>
<li>各語言 Redis client 完整 API</li>
<li>Redis Pub/Sub 細節（不是 Streams、語意不同）</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<h3 id="redis-streams-專屬案例c42-c47">Redis Streams 專屬案例（C42-C47）</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>主討論議題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/redis-streams-bitso-reliable-streams/" data-link-title="3.C42 Bitso：Reliable Redis Streams 抽象 &#43; 自建 DLQ" data-link-desc="Bitso 加密交易所、千 msg/sec/stream &#43; 亞毫秒延遲、自建 Reliable Streams 封裝 PEL &#43; retry &#43; DLQ、idempotent processing。">3.C42 Bitso Reliable Streams</a></td>
          <td>自建抽象層 + DLQ + idempotency</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/redis-streams-arcjet-replace-kafka/" data-link-title="3.C43 Arcjet：Redis Streams 取代 Kafka 省 6 位數 $" data-link-desc="Arcjet security 平台、Kafka managed 6 位數 $/yr、用 Redis Streams 約 $1k/yr、自寫 Janitor 監控 retention。">3.C43 Arcjet 取代 Kafka</a></td>
          <td>Janitor 自寫 retention / 6 位數 → $1k</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/redis-streams-harness-event-driven-state/" data-link-title="3.C44 Harness：CD 微服務 async state transfer" data-link-desc="Harness CD 平台用 Redis Streams 解 brittle HTTP、揭露監控缺口 / MAXLEN truncation / head-of-line blocking 三類問題。">3.C44 Harness event-driven</a></td>
          <td>XAUTOCLAIM head-of-line / 監控缺口</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/redis-streams-klaxit-rust-log-pipeline/" data-link-title="3.C45 Klaxit：Rust &#43; Redis Streams 處理 Heroku Logplex" data-link-desc="Klaxit carpool 用 Redis Streams 處理 Heroku Logplex 匯流、自動偵測修復平台 perf 問題、6 個月 production Rust。">3.C45 Klaxit Rust + Logplex</a></td>
          <td>High-throughput log ingestion / consumer group</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/redis-streams-learning-com-event-source-retreat/" data-link-title="3.C46 Learning.com：Redis 事件源退場（反例）" data-link-desc="Learning.com 把 microservice event store 放 Redis、1 年累積 GB/週、AOF&#43;EBS 變 latency 痛點、退到 PostgreSQL。">3.C46 Learning.com 退場</a></td>
          <td>（反例）長期事件儲存因成本與延遲退場</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/redis-streams-mateusz-php-microservices/" data-link-title="3.C47 PHP 微服務：Redis Streams &#43; S3 hybrid storage" data-link-desc="PHP 雙微服務通訊、Kafka 在 PHP 生態工具薄弱、用 Redis Streams &#43; payload compression &#43; S3 hybrid 處理大訊息。">3.C47 PHP + S3 hybrid</a></td>
          <td>Payload 大小限制 / hybrid storage</td>
      </tr>
  </tbody>
</table>
<h3 id="跨-vendor-對照">跨 vendor 對照</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>對 Redis Streams 的對應</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/slack-job-queue-kafka-redis/" data-link-title="3.C5 Slack：Job Queue 演進到 Kafka &#43; Redis" data-link-desc="背景工作通道在成長期如何從單一路徑演進成組合式架構。">3.C5 Slack Kafka+Redis</a></td>
          <td>多 broker 組合：Kafka 處理量、Redis 處理即時性</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/contrast-queue-model-by-scale/" data-link-title="3.C10 對照：規模差異下的佇列模型" data-link-desc="同一 queue 模型在不同規模下的治理與失敗邊界差異。">3.C10 規模對照</a></td>
          <td>中等規模 / Redis 生態內 / 不跨 shard</td>
      </tr>
  </tbody>
</table>
<p><strong>Stream + Functions / Redis Cluster on Streams 缺直接 customer case</strong>：公開資料多在 single-instance / Sentinel 規模、Cluster 跟 Functions 案例稀薄、撰寫該段時要明示。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游概念：<a href="/blog/backend/00-service-selection/async-delivery-selection/" data-link-title="0.3 非同步與事件傳遞選型" data-link-desc="區分背景工作、durable queue、stream、pub/sub 與 outbox 的選型邊界">0.3 非同步選型</a>、<a href="/blog/backend/03-message-queue/broker-basics/" data-link-title="3.1 broker 基礎與投遞模型" data-link-desc="先理解 broker、queue、consumer 與 delivery semantics">3.1 broker basics</a></li>
<li>Redis 本體：<a href="/blog/backend/02-cache-redis/" data-link-title="模組二：快取與 Redis" data-link-desc="整理快取策略、Redis 資料型別與分散式狀態輔助能力">02 cache 模組</a></li>
<li>平行 vendor：<a href="/blog/backend/03-message-queue/vendors/kafka/" data-link-title="Apache Kafka" data-link-desc="Distributed event streaming platform、log-based 模型">Kafka</a>、<a href="/blog/backend/03-message-queue/vendors/nats/" data-link-title="NATS" data-link-desc="Lightweight messaging、JetStream 加持久化與 streams">NATS</a></li>
<li>下游能力：<a href="/blog/backend/03-message-queue/consumer-design/" data-link-title="3.4 consumer 設計與去重" data-link-desc="整理 consumer、checkpoint 與 replay safety">3.4 consumer 設計</a></li>
</ul>
]]></content:encoded></item><item><title>AWS IAM</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-iam/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-iam/</guid><description>&lt;p>AWS IAM 是 AWS 的 cloud resource permission engine — 它回答的問題是「這個身份能對哪一個 AWS resource 做哪一個 API call」。它不是 workforce IdP、也不負責「這個人類是誰」的判定。所有 AWS API 流量（無論來自 console 操作、CI pipeline、Lambda、EC2、跨帳號 partner）最終都要經過 IAM 的 policy 評估、IAM 是 AWS 安全模型的根。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>AWS IAM 是 &lt;em>cloud resource permission engine&lt;/em>、人類 workforce 的 SSO 與 lifecycle 應該走 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-iam-identity-center/" data-link-title="AWS IAM Identity Center" data-link-desc="AWS 原生 workforce SSO、前 AWS SSO、Permission Set 跨帳號 access、可串外部 IdP federation">AWS IAM Identity Center&lt;/a> 或外部 IdP（&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/keycloak/" data-link-title="Keycloak" data-link-desc="Open source self-hosted Identity Provider、Red Hat 主導、Realm-based multi-tenancy、適合資料主權與自訂 flow 需求">Keycloak&lt;/a>）。Identity Center 把人類映射到 &lt;em>Permission Set&lt;/em>、Permission Set 在每個目標帳號裡實際上是 AWS-Reserved IAM Role — 也就是說：人類登入走 Identity Center、實際的 API 授權判斷一定回到 IAM。兩層責任分清楚、policy 才不會錯放在「誰是誰」的地方。&lt;/p>
&lt;p>AWS IAM 跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google Cloud IAM&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/azure-rbac/" data-link-title="Azure RBAC &amp;#43; Entra ID" data-link-desc="Azure 雙層身份/權限體系、Entra ID（IdP）&amp;#43; Azure RBAC（resource permission）、Conditional Access、PIM、Managed Identity">Azure RBAC&lt;/a> 在 policy model 上設計差異很大。AWS 的表達力最強 — identity-based policy、resource-based policy、Service Control Policy（SCP）、Permission Boundary、Session Policy 是五個獨立的層、最終結果由 &lt;em>Explicit Deny &amp;gt; Org SCP &amp;gt; Resource-based &amp;gt; Identity-based &amp;gt; Permission Boundary &amp;gt; Session Policy&lt;/em> 的評估順序決定。表達力換來的代價是 &lt;em>最容易設定錯&lt;/em>：S3 bucket policy 設錯 = public、KMS key policy 漏一個 condition = 跨帳號可以解密、Trust Policy 沒設 ExternalID = confused deputy 攻擊面。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本頁、讀者能判斷：&lt;/p>
&lt;ol>
&lt;li>哪些 IAM first-class concept（User / Group / Role / Policy / STS）對應到自己的場景、哪些要避免（例如：給人類發 IAM User access key）&lt;/li>
&lt;li>跨帳號信任、CI / 第三方 SaaS 連進 AWS、service-to-service 認證該走 Role assumption / OIDC trust 還是 Roles Anywhere&lt;/li>
&lt;li>SCP、Permission Boundary、resource-based policy 三層上限的疊加方式、何時用哪一層&lt;/li>
&lt;li>CloudTrail + Access Analyzer 的稽核 baseline、出事時的最短取證路徑&lt;/li>
&lt;/ol>
&lt;h2 id="最短判讀路徑">最短判讀路徑&lt;/h2>
&lt;p>判斷一個 AWS 帳號的 IAM 配置是否健康、最少看四件事：&lt;/p></description><content:encoded><![CDATA[<p>AWS IAM 是 AWS 的 cloud resource permission engine — 它回答的問題是「這個身份能對哪一個 AWS resource 做哪一個 API call」。它不是 workforce IdP、也不負責「這個人類是誰」的判定。所有 AWS API 流量（無論來自 console 操作、CI pipeline、Lambda、EC2、跨帳號 partner）最終都要經過 IAM 的 policy 評估、IAM 是 AWS 安全模型的根。</p>
<h2 id="服務定位">服務定位</h2>
<p>AWS IAM 是 <em>cloud resource permission engine</em>、人類 workforce 的 SSO 與 lifecycle 應該走 <a href="/blog/backend/07-security-data-protection/vendors/aws-iam-identity-center/" data-link-title="AWS IAM Identity Center" data-link-desc="AWS 原生 workforce SSO、前 AWS SSO、Permission Set 跨帳號 access、可串外部 IdP federation">AWS IAM Identity Center</a> 或外部 IdP（<a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a> / <a href="/blog/backend/07-security-data-protection/vendors/keycloak/" data-link-title="Keycloak" data-link-desc="Open source self-hosted Identity Provider、Red Hat 主導、Realm-based multi-tenancy、適合資料主權與自訂 flow 需求">Keycloak</a>）。Identity Center 把人類映射到 <em>Permission Set</em>、Permission Set 在每個目標帳號裡實際上是 AWS-Reserved IAM Role — 也就是說：人類登入走 Identity Center、實際的 API 授權判斷一定回到 IAM。兩層責任分清楚、policy 才不會錯放在「誰是誰」的地方。</p>
<p>AWS IAM 跟 <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google Cloud IAM</a> / <a href="/blog/backend/07-security-data-protection/vendors/azure-rbac/" data-link-title="Azure RBAC &#43; Entra ID" data-link-desc="Azure 雙層身份/權限體系、Entra ID（IdP）&#43; Azure RBAC（resource permission）、Conditional Access、PIM、Managed Identity">Azure RBAC</a> 在 policy model 上設計差異很大。AWS 的表達力最強 — identity-based policy、resource-based policy、Service Control Policy（SCP）、Permission Boundary、Session Policy 是五個獨立的層、最終結果由 <em>Explicit Deny &gt; Org SCP &gt; Resource-based &gt; Identity-based &gt; Permission Boundary &gt; Session Policy</em> 的評估順序決定。表達力換來的代價是 <em>最容易設定錯</em>：S3 bucket policy 設錯 = public、KMS key policy 漏一個 condition = 跨帳號可以解密、Trust Policy 沒設 ExternalID = confused deputy 攻擊面。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>哪些 IAM first-class concept（User / Group / Role / Policy / STS）對應到自己的場景、哪些要避免（例如：給人類發 IAM User access key）</li>
<li>跨帳號信任、CI / 第三方 SaaS 連進 AWS、service-to-service 認證該走 Role assumption / OIDC trust 還是 Roles Anywhere</li>
<li>SCP、Permission Boundary、resource-based policy 三層上限的疊加方式、何時用哪一層</li>
<li>CloudTrail + Access Analyzer 的稽核 baseline、出事時的最短取證路徑</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷一個 AWS 帳號的 IAM 配置是否健康、最少看四件事：</p>
<ul>
<li><strong>誰能 assume 哪個 Role</strong>：所有 Role 的 Trust Policy（誰能呼叫 <code>sts:AssumeRole</code>）、有沒有跨帳號 trust、跨帳號 trust 是否帶 ExternalID、有沒有 <code>*</code> 在 Principal 裡</li>
<li><strong>Resource-based policy 暴露面</strong>：S3 bucket policy、KMS key policy、Lambda function policy、SNS / SQS policy 是否有 <code>Principal: *</code> 或來自非預期帳號；用 <a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/what-is-access-analyzer.html">IAM Access Analyzer</a> 找 <em>unintended external access</em></li>
<li><strong>Permission Boundary 與 SCP 是否生效</strong>：開發者建的 Role 是否 attach Permission Boundary（防止 admin 自己給自己升權）、Organization 是否 attach SCP 做整個 OU 的上限</li>
<li><strong>CloudTrail 是否完整、是否進 SIEM</strong>：management event 跟 data event 都開、跨 region、跨帳號、保留期符合稽核要求、特定事件（<code>AssumeRole</code> 失敗、root login、<code>CreateAccessKey</code>）接 <a href="/blog/backend/knowledge-cards/alert-runbook/" data-link-title="Alert Runbook" data-link-desc="說明告警如何連到可執行的排障與恢復流程">alert runbook</a></li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/knowledge-cards/authorization/" data-link-title="Authorization" data-link-desc="說明授權如何判斷誰能對哪些資源執行哪些操作">Authorization</a> 與 <a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">Audit Log</a> 邊界的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>Role 設計（cross-account / service / OIDC trust）</strong>：所有 <em>持續性</em> 的身份都應該是 Role、不是 IAM User。Service Role（給 EC2 / Lambda / ECS task）是 AWS 內部 service-to-service；Cross-account Role 給 partner 帳號或自家其他帳號用 <code>sts:AssumeRole</code> 進來；OIDC trust 是現代 CI 必備路徑（GitHub Actions / GitLab / 自管 K8s 用短期 OIDC token 換 AWS STS 短期憑證、不在 secret store 存 long-lived access key）。</p>
<p><strong>Policy 種類分工</strong>：identity-based policy attach 在 User / Group / Role 上、回答「這個身份能做什麼」。Resource-based policy attach 在 resource 上（S3 bucket、KMS key、SNS topic、Lambda function）、回答「誰能對這個 resource 做什麼」— 同帳號內 identity-based 跟 resource-based 任一個 allow 就通過、跨帳號 <em>兩邊都要 allow</em>。SCP 是 Organization 層級的上限、不是 grant — SCP allow 不會給任何權限、SCP deny 會擋掉整個 OU 的所有 identity。Permission Boundary 是 <em>user 角度的上限</em>、給 admin 用來限制「我把 admin 權限委派給 developer 後、developer 自己建的 role 不能超過這條線」。</p>
<p><strong>STS 與臨時憑證</strong>：所有 cross-account、service-to-service、人類 console federation 都應該走 STS — <code>sts:AssumeRole</code>（跨帳號 / 跨 role）、<code>sts:AssumeRoleWithSAML</code>（SAML IdP）、<code>sts:AssumeRoleWithWebIdentity</code>（OIDC）、<code>sts:GetFederationToken</code>（外部 broker）。Session 預設 1 小時、最長可設 12 小時（依 Role 設定）。Debug 起手式：<code>aws sts get-caller-identity</code> 確認當前 caller 是誰、是 User、Role 還是 federated session。</p>
<p><strong>Access Key 治理</strong>：IAM User 的 long-lived access key 是 <em>最後手段</em>、用於 break-glass 或無法跑 IMDS / Roles Anywhere 的 legacy。所有 access key 走 <a href="/blog/backend/knowledge-cards/secret-management/" data-link-title="Secret Management" data-link-desc="說明 token、key、password 與憑證如何保存、輪替與撤銷">Secret Management</a>、定期 rotation、IAM Access Analyzer 的 unused access finding 找閒置 key。</p>
<p><strong>CloudTrail / Access Analyzer baseline</strong>：CloudTrail organization trail 開到所有帳號、management event 必開、data event（S3 object level、Lambda invoke）依資料敏感度開。Access Analyzer 至少跑 <em>external access</em>（找 resource-based policy 把資源暴露給外部帳號）跟 <em>unused access</em>（找閒置 Role、user、permission）。</p>
<p><strong>Trust Policy / ExternalID</strong>：第三方 SaaS（監控、CSPM、備份服務）要進你的 AWS 帳號時、其 Trust Policy 必須要求 ExternalID — 否則攻擊者只要知道 Role ARN 就能假冒第三方 SaaS 的呼叫端、走 confused deputy 攻擊面（<a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/confused-deputy.html">AWS confused deputy 官方說明</a>）。自家跨帳號 trust 不一定要 ExternalID、第三方一定要。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>AWS IAM</th>
          <th>Google Cloud IAM</th>
          <th>Azure RBAC</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>基本單位</td>
          <td>Policy（attach 到 identity 或 resource）</td>
          <td>Role Binding（principal + role + resource）</td>
          <td>Role Assignment（scope + principal + role）</td>
      </tr>
      <tr>
          <td>隔離邊界</td>
          <td>Account（root）+ Organization SCP</td>
          <td>Project / Folder / Org（階層 inherit）</td>
          <td>Subscription / Management Group（階層 inherit）</td>
      </tr>
      <tr>
          <td>Policy 表達力</td>
          <td>高 — identity / resource / SCP / boundary / session 五層</td>
          <td>中 — Conditional IAM + Organization Policy</td>
          <td>中 — RBAC + Azure Policy 兩層</td>
      </tr>
      <tr>
          <td>Resource-based</td>
          <td>多 service 支援（S3 / KMS / SNS / SQS / Lambda&hellip;）</td>
          <td>較少（GCS / Pub/Sub / KMS 等）</td>
          <td>較少、多走 RBAC 統一</td>
      </tr>
      <tr>
          <td>設定錯誤代價</td>
          <td>高 — bucket / key policy 設錯就 public</td>
          <td>中 — 較統一但精細度也較低</td>
          <td>中 — 階層 inherit 容易誤放</td>
      </tr>
  </tbody>
</table>
<p>AWS IAM 是 <em>表達力最強、最容易設定錯</em> 的雲端 IAM。Google Cloud IAM 設計較統一、policy model 易讀但精細度有限。Azure RBAC 走 inheritance + scope、靠 Management Group 結構治理。三家都不能直接互換、跨雲環境需要在每家自己的 IAM 模型裡建等價的 least-privilege baseline。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Service Control Policy（SCP）</strong>：Organization 層級的上限、用來宣告「整個 OU 永遠不能做什麼」 — 例如禁止 root user 操作、禁止關閉 CloudTrail、禁止在非允許 region 建 resource。SCP 是 <em>deny-list 防護網</em>、不是日常授權；日常授權交給 identity-based policy。SCP 過嚴會擋住合法操作、過鬆等於沒設、設計時要對齊 organization 的安全政策骨幹。</p>
<p><strong>Permission Boundary</strong>：用在 <em>委派 admin</em> 場景 — 公司想讓 platform team 自己建 IAM Role 給應用、但又不想讓他們建出 admin role。Admin 給 platform team 一個 Permission Boundary policy、platform team 建的所有 Role 都會被這個 boundary 限制 <em>上限</em>、就算 attach 了 <code>AdministratorAccess</code> 也只能在 boundary 範圍內生效。</p>
<p><strong>ABAC（attribute-based / tag-based access control）</strong>：大規模 multi-account 環境、每個 service 一個 Role 會 Role 爆炸。ABAC 用 <em>tag</em>（principal tag、resource tag、request tag）做 policy condition — 例如「Role 上有 <code>team=payments</code> tag 的人能操作 <code>team=payments</code> tag 的 resource」。設計成立的前提是 tag 來源可信、不能讓使用者自己改 principal tag。</p>
<p><strong>IAM Roles Anywhere</strong>：給 AWS 之外的 workload（地端 K8s、其他雲、邊緣設備）用 X.509 憑證換 STS 短期憑證。前提是有一個可信的 PKI（自管 CA 或公開 CA）跟 trust anchor。比起把 IAM User access key 放在地端 secret store、Roles Anywhere 是更安全的設計。</p>
<p><strong>OIDC trust（GitHub Actions / GitLab CI / 第三方 CI）</strong>：CI / CD 連 AWS 的標準做法。在 AWS 建一個 OIDC identity provider 指向 CI 的 OIDC issuer、Role 的 Trust Policy condition 限制 <code>repo:org/repo:ref:refs/heads/main</code>、CI workflow 直接 <code>aws sts assume-role-with-web-identity</code>。完全不需要在 CI secret store 存 long-lived AWS access key、token TTL 隨 job 結束自動失效。</p>
<p><strong>Resource-based policy 跨帳號設計</strong>：S3 bucket policy、KMS key policy、SNS / SQS / Lambda policy 都支援跨帳號授權。設計時兩件事必查：Principal 是否包含預期的帳號 / Role ARN、condition 是否限制來源（<code>aws:SourceAccount</code>、<code>aws:SourceArn</code>、<code>aws:PrincipalOrgID</code>）。漏了 condition、就可能讓任何拿到「假裝是某個 service」身份的人都能呼叫 — Capital One 2019 事件本質就是 SSRF 取得 EC2 IMDS 的 Role credential、再用該 Role 的權限去 S3 列舉跟讀取資料、揭示 <em>resource-based policy + identity-based policy 沒有最小化、就會在事故時最大化</em>。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong><code>AccessDenied</code> 但 policy 看起來 allow</strong>：先用 <a href="https://policysim.aws.amazon.com/">IAM Policy Simulator</a> 或 <code>aws iam simulate-principal-policy</code> 重算、確認是 SCP 擋、Permission Boundary 擋、resource-based policy 沒 allow、還是 condition key 不匹配。Explicit Deny 永遠贏。</li>
<li><strong>跨帳號 <code>sts:AssumeRole</code> 失敗</strong>：兩邊都要設 — caller 帳號的 identity-based policy 要 allow <code>sts:AssumeRole</code> 到目標 Role ARN、目標 Role 的 Trust Policy 要 allow caller 的 Principal。漏其一就失敗。</li>
<li><strong>S3 bucket 不小心 public</strong>：用 Access Analyzer 的 external access finding 找、用 <em>Block Public Access</em> 帳號級別開關擋掉（即使 bucket policy 寫了 public、Block Public Access 也會擋）。常見根因：bucket policy 寫 <code>Principal: *</code> 沒加 condition、或 ACL 殘留歷史設定。</li>
<li><strong>Role / access key 殘留</strong>：用 Access Analyzer 的 unused access finding、或 IAM credential report 找超過 90 天沒用的 user / role、配 <a href="/blog/backend/07-security-data-protection/cases/failure-credential-rotation-without-scope/" data-link-title="7.C9 反例：憑證輪替未分 Scope" data-link-desc="憑證輪替若未分域分批，容易造成跨系統連鎖中斷。">Failure: Credential Rotation Without Scope</a> 的分域分批 rotation 流程清理</li>
<li><strong>第三方 SaaS Role 缺 ExternalID</strong>：稽核第三方 vendor 的 onboarding 文件、若沒要求 ExternalID 是 vendor 自己安全模型有破口、自己這邊也要拒絕這種 onboarding</li>
<li><strong>CloudTrail 落地不全</strong>：Organization trail 沒覆蓋新建帳號、data event 沒開、log 沒進 SIEM、保留期不足 — 這四件事都會讓事故發生時拿不到證據</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>人類員工 SSO 進 AWS</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/aws-iam-identity-center/" data-link-title="AWS IAM Identity Center" data-link-desc="AWS 原生 workforce SSO、前 AWS SSO、Permission Set 跨帳號 access、可串外部 IdP federation">AWS IAM Identity Center</a></td>
      </tr>
      <tr>
          <td>多雲 / SaaS app 統一 SSO</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a> / <a href="/blog/backend/07-security-data-protection/vendors/keycloak/" data-link-title="Keycloak" data-link-desc="Open source self-hosted Identity Provider、Red Hat 主導、Realm-based multi-tenancy、適合資料主權與自訂 flow 需求">Keycloak</a></td>
      </tr>
      <tr>
          <td>Customer / B2C identity</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/auth0/" data-link-title="Auth0" data-link-desc="B2C / B2B Customer Identity Provider、Universal Login、Action / Rule hook、屬 Okta 旗下 Customer Identity Cloud">Auth0</a></td>
      </tr>
      <tr>
          <td>Google Cloud resource 權限</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google Cloud IAM</a></td>
      </tr>
      <tr>
          <td>Azure resource 權限</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/azure-rbac/" data-link-title="Azure RBAC &#43; Entra ID" data-link-desc="Azure 雙層身份/權限體系、Entra ID（IdP）&#43; Azure RBAC（resource permission）、Conditional Access、PIM、Managed Identity">Azure RBAC</a></td>
      </tr>
      <tr>
          <td>Secret / API key 治理</td>
          <td><a href="/blog/backend/07-security-data-protection/secrets-and-machine-credential-governance/" data-link-title="7.6 秘密管理與機器憑證治理" data-link-desc="以問題驅動方式整理 secret、token、key 與機器身份治理">7.6 秘密管理與機器憑證治理</a></td>
      </tr>
      <tr>
          <td>Key lifecycle / envelope encryption</td>
          <td>AWS KMS vendor 頁（S2 批次撰寫中）+ <a href="/blog/backend/07-security-data-protection/secrets-and-machine-credential-governance/" data-link-title="7.6 秘密管理與機器憑證治理" data-link-desc="以問題驅動方式整理 secret、token、key 與機器身份治理">7.6 秘密管理與機器憑證治理</a></td>
      </tr>
      <tr>
          <td>事件偵測（CloudTrail 以外）</td>
          <td>04 SIEM / detection 工具與 07 SIEM 章節</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>IAM policy JSON 語法完整 reference 與所有 condition key 清單</li>
<li>每個 AWS service 的細部 IAM 動作對照</li>
<li>AWS Organization、Control Tower、Landing Zone 完整建置流程</li>
<li>KMS / Secrets Manager / Certificate Manager 的內部細節（見對應 vendor 頁）</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 AWS IAM 的關係</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/cases/microsoft-storm-0558-signing-key-2023/" data-link-title="7.C4 Microsoft：Storm-0558 簽章金鑰事件" data-link-desc="簽章金鑰事件如何回寫 identity 信任邊界與觀測證據鏈。">Microsoft Storm-0558 Signing Key 2023</a></td>
          <td>雖是 Microsoft Entra / Exchange Online 事件、對 AWS <em>cross-account role assumption signing chain</em> 提供對照：ExternalID 設計、HSM-bound key、跨帳號 token 驗證一致性</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/cases/failure-credential-rotation-without-scope/" data-link-title="7.C9 反例：憑證輪替未分 Scope" data-link-desc="憑證輪替若未分域分批，容易造成跨系統連鎖中斷。">Failure: Credential Rotation Without Scope</a></td>
          <td>IAM User access key、STS session、Role trust 的 rotation 必須分域分批、不能單一指令打全部</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/microsoft-storm-0558-2023-signing-key-chain/" data-link-title="7.R7.1.5 Microsoft Storm-0558 2023：簽章金鑰鏈與郵件存取" data-link-desc="從簽章金鑰保護失效到雲端郵件存取，拆解身分信任鏈的關鍵控制點">Microsoft Storm-0558 Signing Key Chain (red-team)</a></td>
          <td>對 IAM Roles Anywhere / OIDC trust 的 signing material 治理啟示：trust anchor、key custody、跨環境驗證</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/identity-access-boundary/" data-link-title="7.2 身分與授權邊界" data-link-desc="以問題驅動方式整理身分、授權、會話與供應商身分鏈">7.2 身分與授權邊界</a>、<a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">7.13 偵測覆蓋率與訊號治理</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/aws-iam-identity-center/" data-link-title="AWS IAM Identity Center" data-link-desc="AWS 原生 workforce SSO、前 AWS SSO、Permission Set 跨帳號 access、可串外部 IdP federation">AWS IAM Identity Center</a>、<a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google Cloud IAM</a>、<a href="/blog/backend/07-security-data-protection/vendors/azure-rbac/" data-link-title="Azure RBAC &#43; Entra ID" data-link-desc="Azure 雙層身份/權限體系、Entra ID（IdP）&#43; Azure RBAC（resource permission）、Conditional Access、PIM、Managed Identity">Azure RBAC</a></li>
<li>下游：<a href="/blog/backend/07-security-data-protection/secrets-and-machine-credential-governance/" data-link-title="7.6 秘密管理與機器憑證治理" data-link-desc="以問題驅動方式整理 secret、token、key 與機器身份治理">7.6 秘密管理與機器憑證治理</a>（AWS KMS vendor 頁 S2 批次撰寫中）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（CloudTrail / Access Analyzer 訊號如何 routing 進 IR 流程）</li>
<li>官方：<a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/">AWS IAM User Guide</a>、<a href="https://docs.aws.amazon.com/singlesignon/latest/userguide/">AWS IAM Identity Center User Guide</a></li>
</ul>
]]></content:encoded></item><item><title>Google Cloud KMS</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/google-cloud-kms/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/google-cloud-kms/</guid><description>&lt;p>Google Cloud KMS 是 GCP 原生的 key management service、把 envelope encryption、asymmetric signing 與 MAC 等密碼運算集中在受控的 key custodian 內、key material 不離保護邊界。應用端只持 &lt;em>KMS resource name + IAM 權限&lt;/em>、用 &lt;code>Encrypt&lt;/code> / &lt;code>Decrypt&lt;/code> / &lt;code>AsymmetricSign&lt;/code> API 把 plaintext 或 hash 送進 Cloud KMS、key 永遠在 Google 管理的 software 模組或 HSM 內運算完才把結果送回。整個 GCP 的 CMEK（Customer Managed Encryption Key）生態都以 Cloud KMS 為錨點 — GCS bucket、BigQuery dataset、Persistent Disk、Cloud SQL、GKE etcd 都可指定一把 Cloud KMS key 做加密、跟 cloud-native 預設加密（GCP 自管 key、客戶看不到）拉出邊界。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Cloud KMS 的核心定位是 &lt;em>GCP-native envelope encryption + signing 控制面&lt;/em>、用 KeyRing 作為 organizational + locational grouping、CryptoKey + CryptoKeyVersion 作為 key material 的版本軸。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-kms/" data-link-title="AWS KMS" data-link-desc="AWS 原生 key management service、envelope encryption / digital signing / Multi-Region Key、Key Policy &amp;#43; Grant 雙軌授權">AWS KMS&lt;/a> 相比、最大差異是 &lt;em>沒有獨立的 Key Policy&lt;/em>：權限完全走 GCP IAM（Role Binding 綁到 KeyRing 或 CryptoKey resource）、好處是跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google Cloud IAM&lt;/a> 統一治理（同一份 IAM audit、同一套 conditional binding）、代價是少了 AWS KMS Key Policy 那種 &lt;em>key-level 的獨立 deny override&lt;/em>。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/azure-key-vault/" data-link-title="Azure Key Vault" data-link-desc="Azure 三合一 service（Secret &amp;#43; Key &amp;#43; Certificate）、整合 Managed Identity &amp;#43; Entra ID RBAC、Premium tier 走 HSM">Azure Key Vault&lt;/a> 相比、Cloud KMS 拆得更細：Azure 把 secret + key + certificate 合在同一個 Key Vault service、Google 拆成 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/google-secret-manager/" data-link-title="Google Secret Manager" data-link-desc="GCP 原生 secret store、CMEK &amp;#43; Workload Identity Federation 整合、rotation 走自寫 Cloud Function 而非 built-in Lambda">Google Secret Manager&lt;/a>（secret）+ Cloud KMS（key）+ Certificate Authority Service（PKI），各 service IAM、quota、audit 獨立。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/cloudhsm/" data-link-title="AWS CloudHSM" data-link-desc="Single-tenant dedicated HSM（FIPS 140-2 Level 3）、AWS 不持 Crypto User credential、合規 &amp;#43; 資料主權場景的 key custody">CloudHSM&lt;/a> 相比、Cloud KMS Protection Level=HSM 是 &lt;em>managed HSM&lt;/em>（FIPS 140-2 Level 3、Google 顧 cluster）、CloudHSM 是 &lt;em>single-tenant 專屬 HSM&lt;/em>（客戶顧 cluster、合規隔離更強）。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault transit&lt;/a> 相比、Cloud KMS 綁 GCP、Vault transit 可跨雲；但 Vault 自己常用 Cloud KMS 當 auto-unseal master key custodian。&lt;/p></description><content:encoded><![CDATA[<p>Google Cloud KMS 是 GCP 原生的 key management service、把 envelope encryption、asymmetric signing 與 MAC 等密碼運算集中在受控的 key custodian 內、key material 不離保護邊界。應用端只持 <em>KMS resource name + IAM 權限</em>、用 <code>Encrypt</code> / <code>Decrypt</code> / <code>AsymmetricSign</code> API 把 plaintext 或 hash 送進 Cloud KMS、key 永遠在 Google 管理的 software 模組或 HSM 內運算完才把結果送回。整個 GCP 的 CMEK（Customer Managed Encryption Key）生態都以 Cloud KMS 為錨點 — GCS bucket、BigQuery dataset、Persistent Disk、Cloud SQL、GKE etcd 都可指定一把 Cloud KMS key 做加密、跟 cloud-native 預設加密（GCP 自管 key、客戶看不到）拉出邊界。</p>
<h2 id="服務定位">服務定位</h2>
<p>Cloud KMS 的核心定位是 <em>GCP-native envelope encryption + signing 控制面</em>、用 KeyRing 作為 organizational + locational grouping、CryptoKey + CryptoKeyVersion 作為 key material 的版本軸。跟 <a href="/blog/backend/07-security-data-protection/vendors/aws-kms/" data-link-title="AWS KMS" data-link-desc="AWS 原生 key management service、envelope encryption / digital signing / Multi-Region Key、Key Policy &#43; Grant 雙軌授權">AWS KMS</a> 相比、最大差異是 <em>沒有獨立的 Key Policy</em>：權限完全走 GCP IAM（Role Binding 綁到 KeyRing 或 CryptoKey resource）、好處是跟 <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google Cloud IAM</a> 統一治理（同一份 IAM audit、同一套 conditional binding）、代價是少了 AWS KMS Key Policy 那種 <em>key-level 的獨立 deny override</em>。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/azure-key-vault/" data-link-title="Azure Key Vault" data-link-desc="Azure 三合一 service（Secret &#43; Key &#43; Certificate）、整合 Managed Identity &#43; Entra ID RBAC、Premium tier 走 HSM">Azure Key Vault</a> 相比、Cloud KMS 拆得更細：Azure 把 secret + key + certificate 合在同一個 Key Vault service、Google 拆成 <a href="/blog/backend/07-security-data-protection/vendors/google-secret-manager/" data-link-title="Google Secret Manager" data-link-desc="GCP 原生 secret store、CMEK &#43; Workload Identity Federation 整合、rotation 走自寫 Cloud Function 而非 built-in Lambda">Google Secret Manager</a>（secret）+ Cloud KMS（key）+ Certificate Authority Service（PKI），各 service IAM、quota、audit 獨立。跟 <a href="/blog/backend/07-security-data-protection/vendors/cloudhsm/" data-link-title="AWS CloudHSM" data-link-desc="Single-tenant dedicated HSM（FIPS 140-2 Level 3）、AWS 不持 Crypto User credential、合規 &#43; 資料主權場景的 key custody">CloudHSM</a> 相比、Cloud KMS Protection Level=HSM 是 <em>managed HSM</em>（FIPS 140-2 Level 3、Google 顧 cluster）、CloudHSM 是 <em>single-tenant 專屬 HSM</em>（客戶顧 cluster、合規隔離更強）。跟 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault transit</a> 相比、Cloud KMS 綁 GCP、Vault transit 可跨雲；但 Vault 自己常用 Cloud KMS 當 auto-unseal master key custodian。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>KeyRing 該放哪個 location（global / regional / dual-regional / multi-regional）、為何一旦決定無法搬遷</li>
<li>CryptoKey Version + Primary 版本軸怎麼支撐 rotation、何時該 disable / destroy 舊 version</li>
<li>Protection Level（SOFTWARE / HSM / EXTERNAL）跟 Cloud HSM、External Key Manager 的取捨</li>
<li>CMEK 整合 GCS / BigQuery / Persistent Disk 跟 cloud-native default encryption 的邊界差異</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷一份 Cloud KMS 部署是否健康、最少看四件事：</p>
<ul>
<li><strong>KeyRing location 對不對</strong>：production sensitive key 用 region / multi-region、避免不必要的 <code>global</code> KeyRing；location 一旦設定 <em>不能改</em>、key 也搬不出原 KeyRing — 設錯只能建新 KeyRing + 重新加密所有 ciphertext</li>
<li><strong>IAM Conditions 跟 least privilege</strong>：<code>roles/cloudkms.cryptoKeyEncrypterDecrypter</code> 不該綁到 KeyRing level（會放大爆炸半徑）、應綁到具體 CryptoKey；admin 跟 use 角色分離（<code>roles/cloudkms.admin</code> ≠ <code>roles/cloudkms.signer</code>）；敏感 key 加 IAM Condition（時間窗、resource attribute）</li>
<li><strong>Cloud Audit Logs 開到對的層級</strong>：Admin Activity（建 key、改 IAM、destroy version）預設開、Data Access（每次 Encrypt / Decrypt / Sign）<em>預設關</em> — production sensitive key 必須在 IAM audit config 把 Data Access 開、否則「誰用 key 做了什麼」查不到</li>
<li><strong>Protection Level 對齊合規</strong>：production 跟 PII / 金融 / 醫療資料的 key 應走 HSM 或 EXTERNAL、SOFTWARE 只給 dev / 低敏感場景；EKM 對應 <em>資料主權</em>（key 物理上不在 GCP）</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">Audit Log</a> 與 KMS 邊界的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>KeyRing 設計</strong>：KeyRing 是 <em>組織單位 + 位置鎖</em>。建議切法：依 <em>環境 + 用途</em> 拆（<code>prod-data-encryption-asia-east1</code>、<code>prod-signing-global</code>、<code>dev-data-encryption-asia-east1</code>），不要全公司一個 KeyRing。Location 選擇：跟資料 colocate（GCS bucket 在 <code>asia-east1</code> 的 key 也放 <code>asia-east1</code> KeyRing、避免跨區延遲與資料主權問題）；signing key 多半放 <code>global</code> 或 multi-region 提高可用性；CMEK 給 BigQuery 時 KeyRing location 必須跟 dataset location 一致、否則綁不上。一個原則：<em>KeyRing location 是一次性決策</em>、上線前確認跟 cloud resource location + 法規要求對齊。</p>
<p><strong>CryptoKey Version 與 Primary</strong>：CryptoKey 有多個 version（<code>projects/.../cryptoKeys/k/cryptoKeyVersions/1</code>、<code>v2</code>、<code>v3</code>）、其中一個是 Primary — 所有 <code>Encrypt</code> API 預設用 Primary version 加密、<code>Decrypt</code> 自動依 ciphertext 內嵌的 version ID 找對應 version 解。Rotation 不是「換 key」、是 <em>建立新 version 並 promote 為 Primary</em>；舊 version 仍可 decrypt 既有 ciphertext（除非手動 disable / destroy）。Destroy 是 24 小時延遲（可在期內 restore）、destroy 之後 ciphertext 永久不可解 — 排程 destroy 前必須確認沒有遺留 ciphertext 還在用該 version。</p>
<p><strong>Auto Rotation</strong>：CryptoKey 可設 <code>rotationPeriod</code>（最短 1 天、預設 90 天）、KMS 在到期時自動建立新 version + promote 為 Primary、app 不需要改 code。Auto rotation 只對 <em>symmetric encryption key</em> 有效；asymmetric key（signing / decryption）不支援 auto rotation、需要手動建 version + 通知 consumer 更新 public key。注意 auto rotation 是 <em>key version 換</em>、不會 re-encrypt 既有資料 — 真正的 <em>資料 re-encryption</em> 是另一條工作流（讀回 ciphertext + 用新 Primary 重加密寫回）、要依 CMEK-integrated resource 各自規劃。</p>
<p><strong>Protection Level</strong>：SOFTWARE（軟體運算、最便宜、FIPS 140-2 Level 1）/ HSM（Cloud HSM 後端、FIPS 140-2 Level 3、key 物理上在 Google 管理的 HSM cluster）/ EXTERNAL（External Key Manager、key 在客戶自管的外部 HSM、Cloud KMS 把運算委派出去）。Production sensitive key 應走 HSM、SOFTWARE 給 dev / 低敏感場景。Protection Level 是 <em>CryptoKey 建立時決定</em>、不能改 — 要升等只能建新 CryptoKey + 遷移 ciphertext。</p>
<p><strong>CMEK 整合</strong>：CMEK 把 Cloud KMS key 綁到 GCS bucket / BigQuery dataset / Persistent Disk / Cloud SQL / GKE etcd / Pub/Sub topic / Dataflow job 等 resource。設定方式：cloud service 的 service account（如 <code>service-PROJECT_NUMBER@gs-project-accounts.iam.gserviceaccount.com</code>）取得該 CryptoKey 的 <code>cryptoKeyEncrypterDecrypter</code> 權限、resource 在加密時自動呼叫 KMS。跟 cloud-native default encryption（GCP 自己管 key）的差異：CMEK 下 <em>客戶可隨時 disable key 讓整個 bucket / dataset 立刻無法解</em>（compliance kill switch）、default encryption 沒這個能力。代價是 KMS 故障 = CMEK-integrated resource 全部讀寫卡住、所以 production KMS 自身 SLA 跟 monitoring 是 cluster-level dependency。</p>
<p><strong>External Key Manager (EKM)</strong>：GCP 把 encryption / decryption operation <em>委派</em> 給客戶自管的外部 HSM（Thales、Equinix SmartKey、Fortanix 等）、key 物理上不在 GCP、Cloud KMS 只是個 proxy。適合 <em>資料主權</em> 嚴格的場景（歐盟金融、政府機密、跨境法規）— 客戶撤銷外部 HSM 的存取、GCP 立刻無法解密、達成「Google 看不到資料」的合規承諾。代價：每次 Encrypt / Decrypt 都打外部 HSM、延遲跟可用性受外部 HSM 影響、運維複雜度大幅上升。</p>
<p><strong>IAM 整合</strong>：用 Role Binding 控制存取（綁在 KeyRing 或 CryptoKey resource）— <code>roles/cloudkms.cryptoKeyEncrypterDecrypter</code>（Encrypt + Decrypt）/ <code>roles/cloudkms.signer</code>（AsymmetricSign）/ <code>roles/cloudkms.signerVerifier</code>（含 public key 取得）/ <code>roles/cloudkms.admin</code>（建 key、改 IAM）。對應 <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google Cloud IAM</a> 的 conditional binding、可加時間窗、resource attribute、access level 條件。跟 AWS KMS 的關鍵差異：<em>沒有 Key Policy</em> — 所有授權都在 IAM、好處是統一治理、代價是少了 key-level 的獨立 deny override（AWS KMS Key Policy 可寫「即使 IAM 給了 admin、仍 deny destroy」、Cloud KMS 要用 Organization Policy 或 IAM Deny 達成類似效果）。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Google Cloud KMS</th>
          <th>AWS KMS</th>
          <th>Azure Key Vault</th>
          <th>Vault transit</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>部署模型</td>
          <td>GCP managed</td>
          <td>AWS managed</td>
          <td>Azure managed</td>
          <td>self-hosted 或 HCP</td>
      </tr>
      <tr>
          <td>跨雲</td>
          <td>弱 — 綁 GCP</td>
          <td>弱 — 綁 AWS</td>
          <td>弱 — 綁 Azure</td>
          <td>強 — 同介面跨雲</td>
      </tr>
      <tr>
          <td>Multi-region key</td>
          <td>用 multi-region KeyRing（key material 在多 region 鏡像）</td>
          <td>Multi-Region Key 較直接（單一 key ID、跨 region 自動同步）</td>
          <td>支援 geo-replication</td>
          <td>跨雲、需自行設計 replication</td>
      </tr>
      <tr>
          <td>Key 權限模型</td>
          <td>純 IAM Role Binding、無 Key Policy</td>
          <td>IAM + 獨立 Key Policy（雙層授權）</td>
          <td>RBAC + Access Policy 雙模式</td>
          <td>Vault policy（path-based）</td>
      </tr>
      <tr>
          <td>HSM 選項</td>
          <td>Protection Level=HSM（managed、FIPS 140-2 L3）</td>
          <td>AWS KMS HSM-backed（預設）+ CloudHSM（專屬）</td>
          <td>Premium tier + Managed HSM</td>
          <td>依賴後端 KMS / HSM</td>
      </tr>
      <tr>
          <td>外部 key 託管</td>
          <td>External Key Manager (EKM)</td>
          <td>XKS (External Key Store)</td>
          <td>BYOK + Managed HSM</td>
          <td>自管 HSM unseal</td>
      </tr>
      <tr>
          <td>Audit</td>
          <td>Cloud Audit Logs（Data Access 需手動開）</td>
          <td>CloudTrail（KMS event 自動進）</td>
          <td>Azure Monitor / Activity Log</td>
          <td>Vault audit device</td>
      </tr>
      <tr>
          <td>CMEK 整合廣度</td>
          <td>GCS / BQ / PD / Cloud SQL / GKE etcd / Pub/Sub / Dataflow</td>
          <td>S3 / EBS / RDS / DynamoDB / Lambda env</td>
          <td>Storage / SQL / Cosmos / Disk</td>
          <td>不適用（app-level）</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>GCP-heavy、需 CMEK 整合、Workload Identity Federation 已主導</td>
          <td>AWS-heavy、需 Multi-Region Key + Key Policy 精細控制</td>
          <td>Azure-heavy、需要 secret + key 統一治理</td>
          <td>跨雲、需要 app-level encryption-as-a-service</td>
      </tr>
  </tbody>
</table>
<p>選 Cloud KMS 的核心訴求：<em>GCP 是主力雲</em> + 需要 CMEK 把 GCS / BigQuery / PD / Cloud SQL 的加密 key custody 拉回客戶手上 + 接受 IAM-only 授權模型。需要 <em>跨雲統一 key custody</em> 走 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault transit</a> 或 EKM；需要 <em>單一專屬 HSM 隔離</em> 走 <a href="/blog/backend/07-security-data-protection/vendors/cloudhsm/" data-link-title="AWS CloudHSM" data-link-desc="Single-tenant dedicated HSM（FIPS 140-2 Level 3）、AWS 不持 Crypto User credential、合規 &#43; 資料主權場景的 key custody">CloudHSM</a> 或 EKM 接 on-prem HSM。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>External Key Manager (EKM) 與資料主權</strong>：EKM 讓 key 物理上不在 GCP、Cloud KMS 變成 proxy 把 cryptographic operation 委派給客戶自管 HSM。常見部署：金融 / 政府用 <em>EKM via VPC</em>（外部 HSM 在客戶 VPC 內、Cloud KMS 走 PSC 連線、延遲較低）、跨境合規用 <em>EKM via Internet</em>（HSM 在第三方 KMS provider、延遲較高但治理邊界更乾淨）。代價：每次 Encrypt / Decrypt = 一次外部呼叫、CMEK-integrated resource 的讀寫吞吐量受外部 HSM 限制、外部 HSM 故障 = 整個 GCP 端讀寫卡住。</p>
<p><strong>Cloud HSM（Protection Level=HSM）</strong>：把 CryptoKey 物理上鎖在 Google 託管的 FIPS 140-2 Level 3 HSM cluster 內、key 不可 export、所有 cryptographic operation 在 HSM 邊界內完成。對應 <a href="/blog/backend/07-security-data-protection/cases/microsoft-storm-0558-signing-key-2023/" data-link-title="7.C4 Microsoft：Storm-0558 簽章金鑰事件" data-link-desc="簽章金鑰事件如何回寫 identity 信任邊界與觀測證據鏈。">Microsoft Storm-0558 Signing Key 2023</a> 的對照啟示：signing key 一旦能被 export 或從 memory crash dump 撈出、整個信任鏈崩 — HSM-bound key 從設計上斷掉這條路徑。代價：HSM 後端比 SOFTWARE 貴、operation 延遲略高（典型多 &lt; 10ms）、quota 也獨立計算。</p>
<p><strong>Asymmetric Key 做 JWT signing</strong>：CryptoKey purpose=<code>ASYMMETRIC_SIGN</code> 配 algorithm（RSA / EC）、app 透過 <code>AsymmetricSign</code> API 把 JWT header+payload 的 hash 送進 KMS、KMS 回 signature。Public key 走 <code>GetPublicKey</code> API 取得、給 JWKS endpoint 對外發布。優勢：private key 不離 KMS、即使 app server compromise 也無法搬走 signing key；劣勢：每次簽名都 round-trip 一次 KMS、高 QPS 場景要算 quota 跟延遲（典型 ~10-30ms / sign）。</p>
<p><strong>跟 Google Secret Manager 的 CMEK 整合</strong>：<a href="/blog/backend/07-security-data-protection/vendors/google-secret-manager/" data-link-title="Google Secret Manager" data-link-desc="GCP 原生 secret store、CMEK &#43; Workload Identity Federation 整合、rotation 走自寫 Cloud Function 而非 built-in Lambda">Google Secret Manager</a> 預設用 GCP 管的 key 加密 secret、若要 <em>客戶管 key</em>、可設 CMEK 把 GSM 的 secret 用客戶 Cloud KMS key 加密。意義：disable Cloud KMS key 立刻讓 GSM secret 不可讀（compliance kill switch）— 但代價是 KMS 故障 = GSM 也卡住、是強耦合 dependency。</p>
<p><strong>Multi-region key</strong>：Cloud KMS 的 multi-region KeyRing（如 <code>us</code>、<code>europe</code>、<code>asia</code>）讓 key material 在多 region 鏡像、提高可用性但加密 / 解密延遲較高。AWS KMS 的 Multi-Region Key 設計不同（單一 key ID 跨 region 同步、有獨立的 primary / replica 角色）— 跨雲遷移 / 多雲 active-active 設計時要留意這個差異、Cloud KMS multi-region 比較像 <em>單一邏輯 key 多 region 可用</em>、不是 <em>多 region 各自獨立可寫</em>。</p>
<p><strong>Import 自有 key material（BYOK）</strong>：Cloud KMS 可 import 客戶自產的 key material（透過 wrapping key 包覆後上傳）、適合需要 <em>客戶端 key generation 證據鏈</em> 的合規場景。代價：import 的 key 不能 auto rotate（rotation 必須客戶端重新產 key 再 import），且 SOFTWARE / HSM Protection Level 都支援、EXTERNAL 不適用（EXTERNAL 本來就在外部 HSM、不走 import 路徑）。</p>
<p><strong>Organization Policy 與防護欄</strong>：跟 <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google Cloud IAM</a> 整合的 Org Policy 可在 organization-level 強制 <em>只允許 HSM / EXTERNAL key</em>（<code>constraints/gcp.restrictNonCmekServices</code>）、防止工程師建出 SOFTWARE key 處理敏感資料。這層防護欄比依賴 reviewer 紀律有效、屬於 <a href="/blog/backend/07-security-data-protection/cases/failure-credential-rotation-without-scope/" data-link-title="7.C9 反例：憑證輪替未分 Scope" data-link-desc="憑證輪替若未分域分批，容易造成跨系統連鎖中斷。">Failure: Credential Rotation Without Scope</a> 同類「規約靠系統而非紀律」的設計。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>KeyRing location 設錯</strong>：KeyRing 建在 <code>global</code>、要綁 <code>asia-east1</code> 的 BigQuery dataset CMEK — 綁不上、location 不能改、只能建新 KeyRing + 重新加密 — 上線前 review KeyRing location 跟 resource location 對齊</li>
<li><strong>Data Access audit 沒開</strong>：production 用 Cloud KMS 做 signing、事故時要查 <em>誰用 key 簽了什麼</em>、發現只有 Admin Activity log、沒有 Decrypt / Sign 記錄 — IAM audit config 加 <code>dataAccess</code> log type、留意 audit log 自己會增加成本與 quota</li>
<li><strong>CMEK key disable 後 resource 全卡</strong>：disable CryptoKey 想做 compliance 演練、整個 GCS bucket 讀寫立刻 503 — disable 是 <em>全或無</em>、要演練得排維護窗、有 rollback 計畫（re-enable 後恢復）</li>
<li><strong>Auto rotation 設定 + asymmetric key</strong>：以為 asymmetric signing key 也會 auto rotate、上線數月後發現 version 1 還在用 — asymmetric key 不支援 auto rotation、要手動建 version + 通知 JWKS consumer</li>
<li><strong>IAM Role 過寬</strong>：給整個 KeyRing <code>cryptoKeyEncrypterDecrypter</code>、單一 service account 可以解所有 key — 改綁到具體 CryptoKey、加 IAM Condition</li>
<li><strong>EKM 外部 HSM 故障</strong>：外部 HSM 連線中斷、Cloud KMS 端 Encrypt / Decrypt 全 fail、所有 CMEK-integrated resource 讀寫卡住 — EKM 需要 dual HSM redundancy + Cloud KMS 端 monitoring alert</li>
<li><strong>Destroy 後資料不可解</strong>：CryptoKeyVersion destroy 後 24 小時 grace period 過了、發現某個 backup 還是用該 version 加密 — destroy 前必須跑 inventory 確認沒有 ciphertext 還掛在該 version</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>AWS-only 加密 + 需 Key Policy 精細控制</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/aws-kms/" data-link-title="AWS KMS" data-link-desc="AWS 原生 key management service、envelope encryption / digital signing / Multi-Region Key、Key Policy &#43; Grant 雙軌授權">AWS KMS</a></td>
      </tr>
      <tr>
          <td>Azure-only 加密 + 需 secret + key 同治理</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/azure-key-vault/" data-link-title="Azure Key Vault" data-link-desc="Azure 三合一 service（Secret &#43; Key &#43; Certificate）、整合 Managed Identity &#43; Entra ID RBAC、Premium tier 走 HSM">Azure Key Vault</a></td>
      </tr>
      <tr>
          <td>跨雲統一 encryption-as-a-service</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a> transit engine</td>
      </tr>
      <tr>
          <td>單一專屬 HSM 隔離 / 跨雲合規</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/cloudhsm/" data-link-title="AWS CloudHSM" data-link-desc="Single-tenant dedicated HSM（FIPS 140-2 Level 3）、AWS 不持 Crypto User credential、合規 &#43; 資料主權場景的 key custody">CloudHSM</a></td>
      </tr>
      <tr>
          <td>GCP secret 管理（非 key）</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/google-secret-manager/" data-link-title="Google Secret Manager" data-link-desc="GCP 原生 secret store、CMEK &#43; Workload Identity Federation 整合、rotation 走自寫 Cloud Function 而非 built-in Lambda">Google Secret Manager</a></td>
      </tr>
      <tr>
          <td>GCP IAM 治理基底</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google Cloud IAM</a></td>
      </tr>
      <tr>
          <td>公開憑證 / PKI</td>
          <td>Certificate Authority Service（GCP）或 <a href="/blog/backend/07-security-data-protection/vendors/letsencrypt/" data-link-title="Let&#39;s Encrypt" data-link-desc="免費 &#43; 自動化的公共 ACME CA、90 天 TTL 強制自動化、跨雲跨平台 public TLS cert 的事實基礎">Let&rsquo;s Encrypt</a></td>
      </tr>
      <tr>
          <td>Secret rotation 證據鏈</td>
          <td><a href="/blog/backend/07-security-data-protection/credential-rotation-scoped-evidence/" data-link-title="7.27 Credential Rotation with Scoped Evidence 實作示範" data-link-desc="以 webhook/API credential 輪替示範 scope map、證據欄位與回退窗口如何一起設計。">7.5 Credential Rotation Scoped Evidence</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Cloud KMS 完整 API reference 跟 <code>gcloud kms</code> CLI 詳盡用法</li>
<li>Cloud HSM partition 內部架構、FIPS 140-2 Level 3 驗證細節</li>
<li>EKM 各 partner（Thales / Fortanix / Equinix）的整合步驟與 API 對照</li>
<li>BigQuery / GCS / Cloud SQL 各自 CMEK 設定的完整教學</li>
<li>Cloud KMS pricing 詳盡計算（key version 數、operation 次數、HSM 加成）</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>Cloud KMS 在 07 案例庫沒有直接 vendor-level 事件、以下案例採對照引用：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 Cloud KMS 的關係（對照）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/cases/microsoft-storm-0558-signing-key-2023/" data-link-title="7.C4 Microsoft：Storm-0558 簽章金鑰事件" data-link-desc="簽章金鑰事件如何回寫 identity 信任邊界與觀測證據鏈。">Microsoft Storm-0558 Signing Key 2023</a></td>
          <td>Cloud KMS Protection Level=HSM 把 signing key 鎖在硬體、不可 export、跟 HSM-bound mindset 同源 — signing key 一旦能 export 整條信任鏈崩</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/microsoft-storm-0558-2023-signing-key-chain/" data-link-title="7.R7.1.5 Microsoft Storm-0558 2023：簽章金鑰鏈與郵件存取" data-link-desc="從簽章金鑰保護失效到雲端郵件存取，拆解身分信任鏈的關鍵控制點">Microsoft Storm-0558 Signing Key Chain (red-team)</a></td>
          <td>Asymmetric Key + Cloud Audit Data Access 是 <em>誰用 key 簽什麼</em> 的稽核基礎、預設關閉的 Data Access log 在 production 必須開、否則事故時無證據</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/cases/failure-credential-rotation-without-scope/" data-link-title="7.C9 反例：憑證輪替未分 Scope" data-link-desc="憑證輪替若未分域分批，容易造成跨系統連鎖中斷。">Failure: Credential Rotation Without Scope</a></td>
          <td>Auto Rotation 是 vendor-controlled、但 CMEK 整合的 GCS bucket / BQ dataset 的 <em>re-encryption schedule</em> 還是要自己管、否則 rotation 只換 key version、舊資料還是用舊 version</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/secrets-and-machine-credential-governance/" data-link-title="7.6 秘密管理與機器憑證治理" data-link-desc="以問題驅動方式整理 secret、token、key 與機器身份治理">7.6 秘密管理與機器憑證治理</a>、<a href="/blog/backend/07-security-data-protection/transport-trust-and-certificate-lifecycle/" data-link-title="7.5 傳輸信任與憑證生命週期" data-link-desc="以問題驅動方式整理傳輸信任鏈、會話完整性與憑證節奏">7.5 傳輸信任與憑證生命週期</a>（KMS 為 TLS / signing key 的 root custodian）、<a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">7.13 偵測覆蓋率與訊號治理</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/aws-kms/" data-link-title="AWS KMS" data-link-desc="AWS 原生 key management service、envelope encryption / digital signing / Multi-Region Key、Key Policy &#43; Grant 雙軌授權">AWS KMS</a>、<a href="/blog/backend/07-security-data-protection/vendors/azure-key-vault/" data-link-title="Azure Key Vault" data-link-desc="Azure 三合一 service（Secret &#43; Key &#43; Certificate）、整合 Managed Identity &#43; Entra ID RBAC、Premium tier 走 HSM">Azure Key Vault</a>、<a href="/blog/backend/07-security-data-protection/vendors/cloudhsm/" data-link-title="AWS CloudHSM" data-link-desc="Single-tenant dedicated HSM（FIPS 140-2 Level 3）、AWS 不持 Crypto User credential、合規 &#43; 資料主權場景的 key custody">CloudHSM</a></li>
<li>平行（secret）：<a href="/blog/backend/07-security-data-protection/vendors/google-secret-manager/" data-link-title="Google Secret Manager" data-link-desc="GCP 原生 secret store、CMEK &#43; Workload Identity Federation 整合、rotation 走自寫 Cloud Function 而非 built-in Lambda">Google Secret Manager</a>、<a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a></li>
<li>上游（IAM）：<a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google Cloud IAM</a>（Cloud KMS 權限完全走 IAM Role Binding）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（KMS 事件如何 routing 進 IR 流程）</li>
<li>官方：<a href="https://cloud.google.com/kms/docs">Cloud KMS Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>Google DLP</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/google-dlp/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/google-dlp/</guid><description>&lt;p>Google DLP（Data Loss Prevention、2023 重新命名為 &lt;em>Sensitive Data Protection / SDP&lt;/em>）是 GCP 原生的敏感資料 &lt;em>discovery + classification + transformation&lt;/em> 服務。它跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/microsoft-purview/" data-link-title="Microsoft Purview" data-link-desc="Microsoft 跨 M365 / Azure / endpoint 的 data governance &amp;#43; information protection &amp;#43; DLP &amp;#43; insider risk 統合平台、label-driven">Microsoft Purview&lt;/a> / AWS Macie / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/cloud-data-policy/" data-link-title="Cloud-native Data Policy (BigQuery &amp;#43; S3)" data-link-desc="BigQuery column / row-level security &amp;#43; S3 bucket policy &amp;#43; Access Points &amp;#43; Macie、雲端原生資料層 access control、跟 DLP / Purview 互補">Cloud-native data policy&lt;/a> 的差異不在「能不能發現 PII」、而在 &lt;em>發現之後能做多少事&lt;/em> — Google DLP 的核心優勢是 transformation 層（masking / Format-Preserving Encryption / tokenization / k-anonymity / differential privacy），不只是 detection。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Google DLP 的核心定位是 &lt;em>infrastructure-level 敏感資料治理&lt;/em>、跨 GCS / BigQuery / Cloud SQL / 任意 Inspect API input 的 PII 發現與去識別化。三層能力堆疊：&lt;em>Discovery&lt;/em>（背景 scan GCS bucket / BigQuery table / Cloud SQL instance 找 PII / payment / credential）、&lt;em>Classification&lt;/em>（150+ 預定義 infoType + custom infoType 組合）、&lt;em>Transformation&lt;/em>（redact / mask / replace / pseudonymize / Format-Preserving Encryption / k-anonymity / differential privacy）。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/microsoft-purview/" data-link-title="Microsoft Purview" data-link-desc="Microsoft 跨 M365 / Azure / endpoint 的 data governance &amp;#43; information protection &amp;#43; DLP &amp;#43; insider risk 統合平台、label-driven">Microsoft Purview&lt;/a> 比、Purview 走 &lt;em>information protection&lt;/em>（sensitivity label + Office docs + Microsoft 365）+ DLP、Google DLP 走 &lt;em>infrastructure-level data scan + transformation&lt;/em>；兩者解不同層、企業若 Office docs / SharePoint 為主走 Purview、cloud data warehouse / object storage 為主走 Google DLP。跟 AWS Macie 比、Macie 限 S3 + EBS / RDS snapshot、Google DLP 跨 GCS + BigQuery + Cloud SQL + 任意 Inspect API content（含 streaming / on-prem 透過 API call）。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/cloud-data-policy/" data-link-title="Cloud-native Data Policy (BigQuery &amp;#43; S3)" data-link-desc="BigQuery column / row-level security &amp;#43; S3 bucket policy &amp;#43; Access Points &amp;#43; Macie、雲端原生資料層 access control、跟 DLP / Purview 互補">Cloud-native data policy&lt;/a> 比、Google DLP 是 &lt;em>detection + transformation&lt;/em>、Cloud-native policy 是 &lt;em>access control&lt;/em>；production 常組合使用 — DLP 發現敏感欄位 → policy 限制誰能 access → 必要時 DLP transformation 在 query time 自動 redact。&lt;/p></description><content:encoded><![CDATA[<p>Google DLP（Data Loss Prevention、2023 重新命名為 <em>Sensitive Data Protection / SDP</em>）是 GCP 原生的敏感資料 <em>discovery + classification + transformation</em> 服務。它跟 <a href="/blog/backend/07-security-data-protection/vendors/microsoft-purview/" data-link-title="Microsoft Purview" data-link-desc="Microsoft 跨 M365 / Azure / endpoint 的 data governance &#43; information protection &#43; DLP &#43; insider risk 統合平台、label-driven">Microsoft Purview</a> / AWS Macie / <a href="/blog/backend/07-security-data-protection/vendors/cloud-data-policy/" data-link-title="Cloud-native Data Policy (BigQuery &#43; S3)" data-link-desc="BigQuery column / row-level security &#43; S3 bucket policy &#43; Access Points &#43; Macie、雲端原生資料層 access control、跟 DLP / Purview 互補">Cloud-native data policy</a> 的差異不在「能不能發現 PII」、而在 <em>發現之後能做多少事</em> — Google DLP 的核心優勢是 transformation 層（masking / Format-Preserving Encryption / tokenization / k-anonymity / differential privacy），不只是 detection。</p>
<h2 id="服務定位">服務定位</h2>
<p>Google DLP 的核心定位是 <em>infrastructure-level 敏感資料治理</em>、跨 GCS / BigQuery / Cloud SQL / 任意 Inspect API input 的 PII 發現與去識別化。三層能力堆疊：<em>Discovery</em>（背景 scan GCS bucket / BigQuery table / Cloud SQL instance 找 PII / payment / credential）、<em>Classification</em>（150+ 預定義 infoType + custom infoType 組合）、<em>Transformation</em>（redact / mask / replace / pseudonymize / Format-Preserving Encryption / k-anonymity / differential privacy）。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/microsoft-purview/" data-link-title="Microsoft Purview" data-link-desc="Microsoft 跨 M365 / Azure / endpoint 的 data governance &#43; information protection &#43; DLP &#43; insider risk 統合平台、label-driven">Microsoft Purview</a> 比、Purview 走 <em>information protection</em>（sensitivity label + Office docs + Microsoft 365）+ DLP、Google DLP 走 <em>infrastructure-level data scan + transformation</em>；兩者解不同層、企業若 Office docs / SharePoint 為主走 Purview、cloud data warehouse / object storage 為主走 Google DLP。跟 AWS Macie 比、Macie 限 S3 + EBS / RDS snapshot、Google DLP 跨 GCS + BigQuery + Cloud SQL + 任意 Inspect API content（含 streaming / on-prem 透過 API call）。跟 <a href="/blog/backend/07-security-data-protection/vendors/cloud-data-policy/" data-link-title="Cloud-native Data Policy (BigQuery &#43; S3)" data-link-desc="BigQuery column / row-level security &#43; S3 bucket policy &#43; Access Points &#43; Macie、雲端原生資料層 access control、跟 DLP / Purview 互補">Cloud-native data policy</a> 比、Google DLP 是 <em>detection + transformation</em>、Cloud-native policy 是 <em>access control</em>；production 常組合使用 — DLP 發現敏感欄位 → policy 限制誰能 access → 必要時 DLP transformation 在 query time 自動 redact。</p>
<p>關鍵張力：<em>content scanned 計費</em> ↔ <em>偵測覆蓋率</em>。DLP API 按 scanned bytes 計費、整 BigQuery dataset full scan 在 PB-scale 跟 SIEM ingestion 同類痛點。實務應該分 <em>sample scan</em>（每 dataset 抽 1% 找 infoType 分布）+ <em>full scan</em>（高敏感 dataset 才完整 scan）+ <em>streaming scan</em>（write path 即時擋）三層。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>Google DLP 在 GCP 資料保護 stack 中承擔哪一段（discovery / classification / transformation）、哪些要外接（<a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google Cloud IAM</a> 管 DLP service account、BigQuery column-level security 補 access control）</li>
<li>infoType / Inspection Job / transformation 種類的選用判準（什麼場景 mask、什麼場景 FPE、什麼場景 k-anonymity）</li>
<li>計費 trap 的應對（sample scan + full scan 分層、Pub/Sub trigger 避免重複 scan）</li>
<li>何時用 Google DLP、何時走 Purview / Macie / Cloud-native policy 的取捨</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Google DLP deployment 是否健康、最少看四件事：</p>
<ul>
<li><strong>誰跑 Inspection Job</strong>：DLP service account 的 IAM role（<code>roles/dlp.user</code> / <code>roles/dlp.jobsEditor</code>）、能 scan 哪些 project / bucket / dataset、findings 寫進哪個 BigQuery table、誰能讀 findings</li>
<li><strong>infoType coverage</strong>：是否覆蓋 organization-specific PII（員工 ID / 客戶 ID 用 custom infoType + dictionary）、預定義 infoType 是否 enable 對應業務的（PCI 場景需 CREDIT_CARD_NUMBER + Luhn check、HIPAA 場景需 healthcare infoType）</li>
<li><strong>Transformation lifecycle</strong>：發現 PII 後做什麼（自動 quarantine bucket / 自動 redact view / Pub/Sub trigger Cloud Function）、transformation 是 <em>one-way</em>（mask / redact）還是 <em>reversible</em>（FPE / tokenization 需 key management 走 <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-kms/" data-link-title="Google Cloud KMS" data-link-desc="GCP 原生 key management service、KeyRing / CryptoKey Version 設計、CMEK 整合 &#43; Cloud HSM &#43; External Key Manager">Cloud KMS</a>）</li>
<li><strong>Cost 治理</strong>：scan 頻率 vs scan scope 的策略、是否分 sample / full / streaming 三層、findings retention policy（findings table 本身也是敏感資料、不該無限保留）</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/07-security-data-protection/data-protection-and-masking-governance/" data-link-title="7.4 資料保護與遮罩治理" data-link-desc="以問題驅動方式整理資料分級、遮罩、匯出與備份治理">Data Protection and Masking Governance</a> 邊界的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>使用模式：Inspect API vs Inspection Job</strong>：DLP 有兩種呼叫模式 — <em>Inspect API</em> 走同步單次 scan（小 payload、即時 mask、API 寫入前的 streaming gate）、<em>Inspection Job</em> 走非同步批次 scan（大 dataset、結果存 BigQuery findings table、Pub/Sub trigger 後續 workflow）。production 通常混用：write path（Cloud Function / API gateway）走 Inspect API 即時擋住敏感資料寫進儲存、背景 Inspection Job 對既有 dataset 跑覆盤。</p>
<p><strong>infoType 是 first-class concept</strong>：infoType 不是 regex、是 <em>PII 分類單位</em>。預定義 150+ 種（CREDIT_CARD_NUMBER / EMAIL_ADDRESS / US_SOCIAL_SECURITY_NUMBER / IP_ADDRESS / GENERIC_ID / PERSON_NAME 等）、各帶內建驗證邏輯（CREDIT_CARD_NUMBER 內建 Luhn check 比純 regex 精準、減少 FP）。Custom infoType 三種：<em>regex pattern</em>（自訂 regex）、<em>dictionary</em>（明確 token list、例員工 ID 全集）、<em>hotword rule</em>（context-aware、附近出現特定字才認、例「身分證」附近的數字才認 ID）。FP rate 直接由 infoType 精度決定、production rule 應該優先用預定義 infoType + hotword 限縮。</p>
<p><strong>Transformation 種類遠不只 mask</strong>：DLP 的 transformation 是它跟其他 discovery-only 工具的核心差異。<em>Redact</em> 完全刪除（query result 看不到欄位）；<em>Mask</em> 保留長度替換字元（<code>****1234</code>）；<em>Replace</em> 替換成固定字串（<code>[REDACTED]</code>）；<em>Pseudonymize / Tokenization</em> 一致性 token（同樣 input 給同樣 output、可做 join 但不可逆）；<em>Format-Preserving Encryption (FPE)</em> 保留長度 / format 的可逆加密（key 在 <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-kms/" data-link-title="Google Cloud KMS" data-link-desc="GCP 原生 key management service、KeyRing / CryptoKey Version 設計、CMEK 整合 &#43; Cloud HSM &#43; External Key Manager">Cloud KMS</a>、analyst 查 anonymized data + 必要時授權 reverse）；<em>k-anonymity / l-diversity</em> aggregate 到至少 k 個 record 才公開（防止 quasi-identifier re-identification）；<em>Differential privacy</em> 加 noise 保證 statistical privacy（aggregated analytics 用）。後三項是 production analytics 場景的關鍵 — 不是「藏起來」而是「可用但保護」。</p>
<p><strong>跟 BigQuery 深度整合</strong>：DLP 可 inline scan BigQuery column、findings 自動寫回 metadata。配合 BigQuery <em>column-level security</em>（policy tag）+ <em>authorized view</em> 做「敏感 column 只給特定 role + 自動 redact 給其他 role」。Production 模式：DLP Inspection Job 跑完後、自動 apply policy tag 到含 PII 的 column、無 tag access 的 query 自動失敗或 mask。</p>
<p><strong>跟 Cloud Storage 整合</strong>：可 schedule 掃 bucket 整批檔案、發現後可自動 <em>quarantine</em>（移到隔離 bucket、不同 IAM、警告 owner）。對應 <a href="/blog/backend/07-security-data-protection/red-team/cases/data-exfiltration/lastpass-2022-backup-chain/" data-link-title="7.R7.4.1 LastPass 2022：備份路徑與鏈式入侵" data-link-desc="開發環境資訊外流如何沿著備份路徑擴大成資料風險">LastPass 2022 Backup Chain</a> 的對照：backup bucket 應該獨立 DLP scan、含 credential 的 backup 走獨立 quarantine bucket + 不同 IAM 邊界、不是放在跟 dev backup 同一個 bucket。</p>
<p><strong>Pub/Sub trigger workflow</strong>：Inspection Job 完成後可 publish 到 Pub/Sub topic、Cloud Function 訂閱後執行 — 自動 quarantine / 自動通知 owner / 自動寫進 <a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">SIEM</a> findings index / 觸發 BigQuery policy tag update。這是 detection → response 自動化的 first-class pattern、不是後加的 webhook。</p>
<p><strong>IAM 邊界</strong>：DLP service account 需要讀 source data（<code>roles/storage.objectViewer</code> / <code>roles/bigquery.dataViewer</code>）+ 寫 findings（<code>roles/bigquery.dataEditor</code> to findings dataset）+ 呼叫 DLP API（<code>roles/dlp.user</code>）。service account 本身是高敏感 — 它能讀整個 organization 的 PII、應該走 short-lived credential（<a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Workload Identity Federation</a>）+ 嚴格 audit。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Google DLP</th>
          <th>Microsoft Purview</th>
          <th>AWS Macie</th>
          <th>Cloud-native data policy</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>核心能力</td>
          <td>Discovery + classification + <strong>transformation</strong></td>
          <td>Sensitivity label + DLP + Office docs</td>
          <td>Discovery + classification（無 transform）</td>
          <td>Access control + column-level security</td>
      </tr>
      <tr>
          <td>Data source 範圍</td>
          <td>GCS + BigQuery + Cloud SQL + 任意 Inspect API</td>
          <td>Microsoft 365 + SharePoint + Azure data</td>
          <td>S3 + EBS / RDS snapshot 限定</td>
          <td>BigQuery / S3 / Snowflake 各自 native</td>
      </tr>
      <tr>
          <td>Transformation</td>
          <td>mask / FPE / tokenize / k-anonymity / DP（全套）</td>
          <td>redact + Office sensitivity label</td>
          <td>無 — 只 detection</td>
          <td>無 — 只 access control</td>
      </tr>
      <tr>
          <td>計費模型</td>
          <td>按 content scanned（GB）</td>
          <td>按 user / asset / 流量</td>
          <td>按 storage scanned（GB） + bucket count</td>
          <td>多半含在 cloud platform、policy 規模相關</td>
      </tr>
      <tr>
          <td>Custom 分類能力</td>
          <td>infoType (regex + dictionary + hotword)</td>
          <td>sensitive info type + classifier (ML)</td>
          <td>managed data identifier + custom</td>
          <td>tag-based / column-level、無 content scan</td>
      </tr>
      <tr>
          <td>Healthcare / PHI</td>
          <td>Cloud DLP for Healthcare（FHIR / DICOM）</td>
          <td>Purview Healthcare data + Microsoft 365 PHI</td>
          <td>有限</td>
          <td>無原生 PHI 認知</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>GCP-first + BigQuery / GCS 為 PII 儲存層</td>
          <td>Microsoft 365 / Office docs / SharePoint 為主</td>
          <td>AWS-only + S3 為 PII 儲存層</td>
          <td>已知敏感 column、想做 access control 不做 mask</td>
      </tr>
      <tr>
          <td>退場成本</td>
          <td>中 — transformation 邏輯耦合 DLP API</td>
          <td>高 — sensitivity label 跟 Microsoft 365 深綁</td>
          <td>低 — 只是 finding 跟 alert</td>
          <td>低 — policy 是 metadata</td>
      </tr>
  </tbody>
</table>
<p>選 Google DLP 的核心訴求：<em>GCP 為主資料平台 + BigQuery / GCS 有大量 PII + 需要 transformation（不只 detection）+ 合規（GDPR / HIPAA / PCI）需要 column-level redaction / tokenization</em>。on-prem 為主或 Office docs 為主走 Purview、AWS-only 走 Macie + S3 policy。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Custom infoType 三層組合</strong>：production 自家業務的 PII（員工 ID / 客戶 ID / 內部 case ID）需要 custom infoType。三種組合：<em>regex</em> 抓 pattern（員工 ID 格式 <code>EMP-\d{6}</code>）、<em>dictionary</em> 抓明確 token list（內部 case ID 全集、月更新）、<em>hotword</em> 限縮 context（附近出現「員工」「ID」才認、避免一般 6 位數字誤判）。三者組合的 FP rate 比單獨 regex 低一個量級。</p>
<p><strong>Format-Preserving Encryption (FPE) vs Tokenization</strong>：兩者都產生「外觀像原值但不是原值」的替換。<em>FPE</em> 是可逆加密、key 在 <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-kms/" data-link-title="Google Cloud KMS" data-link-desc="GCP 原生 key management service、KeyRing / CryptoKey Version 設計、CMEK 整合 &#43; Cloud HSM &#43; External Key Manager">Cloud KMS</a>、analyst 在 anonymized data 工作 + 必要時走授權流程 reverse（例：客服需要看完整信用卡號處理退款）。<em>Tokenization</em> 是 deterministic mapping、同樣 input 給同樣 output、可做 join 分析但 token table 不存（理論上不可逆、實務上看 implementation）。選擇判準：<em>需要分析 join 同一 user 跨 dataset</em> 用 tokenization、<em>需要授權 reverse</em> 用 FPE、<em>只要遮蔽不需要還原</em> 用 mask / redact。</p>
<p><strong>k-anonymity / l-diversity / differential privacy</strong>：解決 <em>quasi-identifier re-identification</em> 問題 — 即使欄位不是直接 PII（如 ZIP + 性別 + 年齡）、組合起來能反推個人。<em>k-anonymity</em> 保證每個 record 在 quasi-identifier 上至少跟 k-1 個其他 record 一樣（典型 k=5）。<em>l-diversity</em> 進一步保證 sensitive attribute 在每組內至少 l 個不同值（防止 homogeneity attack）。<em>Differential privacy</em> 加 calibrated noise 到 aggregate query 結果、保證個別 record 加入或刪除對結果影響有 bound。Risk Analysis API 可估算 dataset 的 k-anonymity / l-diversity 風險、不需要先 transform 才知道風險。</p>
<p><strong>跟 Cloud DLP for Healthcare 整合</strong>：FHIR / DICOM 格式的 PHI 有專屬 transformation pipeline。FHIR resource 的特定欄位（patient name / MRN / birth date）按 HIPAA Safe Harbor 自動遮罩、DICOM image 的 metadata 跟 burned-in text 都可 redact。Healthcare 場景的 PHI 治理跟一般 PII 不同 — 不能直接 mask 全部、要保留 clinical utility（年齡轉年齡段、ZIP 保留前三碼）。</p>
<p><strong>跟 BigQuery column-level encryption</strong>：BigQuery 原生支援 AEAD encryption function、可用 KMS-managed key 對 column 做 cell-level encryption。DLP 可在 ingestion 階段先 tokenize、BigQuery query 階段配合 column-level security 做 access-time decryption。是「detection（DLP）+ classification（policy tag）+ encryption（AEAD）+ access control（column-level security）」的完整 stack。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>DLP scan 找不到明顯 PII</strong>：infoType 沒 enable / 預定義 infoType 對 organization-specific 格式不認 — 加 custom infoType + hotword、跑 sample scan 驗證 coverage</li>
<li><strong>FP rate 太高 / findings 淹沒</strong>：infoType 太寬 / hotword 沒設 — 加 likelihood threshold（VERY_LIKELY / LIKELY）、custom infoType 加 hotword 限縮 context</li>
<li><strong>Scan cost 暴衝</strong>：每次都 full scan 整個 dataset / 沒分層 — 改 sample scan（每 dataset 1%）+ 高敏感 dataset 才 full scan + streaming scan 守 write path</li>
<li><strong>Inspection Job 跑超久 / timeout</strong>：dataset 過大 / 沒 partition — 切 partition by date、Job concurrency 提高、避免單 Job 跨整個 organization</li>
<li><strong>Transformation 後 analyst 無法工作</strong>：mask / redact 全部、保留不下 utility — 改 FPE / tokenization 保留 join 能力、k-anonymity 保留 statistical utility</li>
<li><strong>Findings table 自己變成 PII 洩漏面</strong>：findings 含 sample value（預設 quotable）、findings table 無獨立 IAM — 設定 <code>includeQuote: false</code>、findings table 走獨立 dataset + 嚴格 IAM</li>
<li><strong>DLP service account 權限太大 / 沒 audit</strong>：service account 能讀全 organization PII、用 long-lived key — 改 Workload Identity Federation + short-lived credential + Cloud Audit Log 監控 DLP API call</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Microsoft 365 / Office docs 為主</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/microsoft-purview/" data-link-title="Microsoft Purview" data-link-desc="Microsoft 跨 M365 / Azure / endpoint 的 data governance &#43; information protection &#43; DLP &#43; insider risk 統合平台、label-driven">Microsoft Purview</a></td>
      </tr>
      <tr>
          <td>AWS-only + S3 為 PII 儲存層</td>
          <td>AWS Macie</td>
      </tr>
      <tr>
          <td>只要 access control 不要 transformation</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/cloud-data-policy/" data-link-title="Cloud-native Data Policy (BigQuery &#43; S3)" data-link-desc="BigQuery column / row-level security &#43; S3 bucket policy &#43; Access Points &#43; Macie、雲端原生資料層 access control、跟 DLP / Purview 互補">Cloud-native data policy</a></td>
      </tr>
      <tr>
          <td>Secret / credential scanning（非 PII）</td>
          <td>GitGuardian / Gitleaks</td>
      </tr>
      <tr>
          <td>Data lineage / catalog</td>
          <td>Dataplex / Atlan / Collibra</td>
      </tr>
      <tr>
          <td>KMS / key management for FPE</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/google-cloud-kms/" data-link-title="Google Cloud KMS" data-link-desc="GCP 原生 key management service、KeyRing / CryptoKey Version 設計、CMEK 整合 &#43; Cloud HSM &#43; External Key Manager">Google Cloud KMS</a></td>
      </tr>
      <tr>
          <td>SIEM ingestion of DLP findings</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / Chronicle</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>預定義 infoType 完整 list 跟各自 detection 邏輯（150+ 種、見官方 <a href="https://cloud.google.com/dlp/docs/infotypes-reference">InfoType reference</a>）</li>
<li>Cloud DLP for Healthcare 的 FHIR / DICOM 完整 pipeline 細節</li>
<li>BigQuery column-level security / policy tag 的 policy 設計（屬 Data Governance 章節）</li>
<li>GDPR / HIPAA / PCI 合規逐條對應（屬 <a href="/blog/backend/07-security-data-protection/data-residency-deletion-and-evidence-chain/" data-link-title="7.11 資料駐留、刪除與證據鏈" data-link-desc="定義跨區資料駐留、刪除請求與可驗證證據鏈問題">7.8 資料駐留與刪除證據鏈</a> 跟 <a href="/blog/backend/07-security-data-protection/data-protection-and-masking-governance/" data-link-title="7.4 資料保護與遮罩治理" data-link-desc="以問題驅動方式整理資料分級、遮罩、匯出與備份治理">7.4 資料保護與遮罩治理</a> 章節）</li>
<li>Differential privacy 的數學定義跟 epsilon budget 設計</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>Google DLP 在 07 案例庫沒有直接 vendor-level 事件、但所有資料外洩 / 敏感資料治理 case 都是 DLP 控制覆蓋率的對照：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 Google DLP 的關係（對照啟示）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/data-exfiltration/snowflake-2024-credential-abuse/" data-link-title="7.R7.4.2 Snowflake 2024：憑證濫用與資料竊取" data-link-desc="外洩憑證與 MFA 缺口如何在資料平台形成高風險外送事件">Snowflake 2024 Credential Abuse</a></td>
          <td>資料平台 export 流程應該有 DLP scan gate — query result 含批量 PII / 整 table dump 直接 alert 或自動 redact、不是事後審 audit log</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/data-exfiltration/mailchimp-2023-support-tool-abuse/" data-link-title="7.R7.4.4 Mailchimp 2023：支援工具路徑與客戶資料風險" data-link-desc="社交工程進入客服工具後，如何形成特定客戶資料存取風險">Mailchimp 2023 Support Tool Abuse</a></td>
          <td>客服工具的客戶資料 export 應走 DLP Inspect API、單次 export 超過 N 筆 PII 或含 credential 直接擋住 + 觸發 alert、不靠 rate limit 一招</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/data-exfiltration/lastpass-2022-backup-chain/" data-link-title="7.R7.4.1 LastPass 2022：備份路徑與鏈式入侵" data-link-desc="開發環境資訊外流如何沿著備份路徑擴大成資料風險">LastPass 2022 Backup Chain</a></td>
          <td>Backup bucket 應該獨立 DLP scan、含 credential / token 的 backup 自動 quarantine 到獨立 bucket + 不同 IAM、不是跟 dev backup 同 bucket 同 IAM</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/data-protection-and-masking-governance/" data-link-title="7.4 資料保護與遮罩治理" data-link-desc="以問題驅動方式整理資料分級、遮罩、匯出與備份治理">Data Protection and Masking Governance (section)</a></td>
          <td>Google DLP 是 transformation 工具的代表、章節原則對應 mask / FPE / tokenization / k-anonymity 的選用判讀</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/data-residency-deletion-and-evidence-chain/" data-link-title="7.11 資料駐留、刪除與證據鏈" data-link-desc="定義跨區資料駐留、刪除請求與可驗證證據鏈問題">Data Residency Deletion and Evidence Chain (section)</a></td>
          <td>DLP findings 是 deletion 證據鏈的一部分 — 哪些 PII 在哪些 dataset、deletion 後是否 re-scan verified、findings history 是 GDPR right-to-erasure 的稽核證據</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/data-protection-and-masking-governance/" data-link-title="7.4 資料保護與遮罩治理" data-link-desc="以問題驅動方式整理資料分級、遮罩、匯出與備份治理">7.4 資料保護與遮罩治理</a>、<a href="/blog/backend/07-security-data-protection/data-residency-deletion-and-evidence-chain/" data-link-title="7.11 資料駐留、刪除與證據鏈" data-link-desc="定義跨區資料駐留、刪除請求與可驗證證據鏈問題">7.11 資料駐留、刪除與證據鏈</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/microsoft-purview/" data-link-title="Microsoft Purview" data-link-desc="Microsoft 跨 M365 / Azure / endpoint 的 data governance &#43; information protection &#43; DLP &#43; insider risk 統合平台、label-driven">Microsoft Purview</a>、<a href="/blog/backend/07-security-data-protection/vendors/cloud-data-policy/" data-link-title="Cloud-native Data Policy (BigQuery &#43; S3)" data-link-desc="BigQuery column / row-level security &#43; S3 bucket policy &#43; Access Points &#43; Macie、雲端原生資料層 access control、跟 DLP / Purview 互補">Cloud-native data policy</a></li>
<li>上下游 IAM：<a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google Cloud IAM</a>（DLP service account 治理）、<a href="/blog/backend/07-security-data-protection/vendors/google-cloud-kms/" data-link-title="Google Cloud KMS" data-link-desc="GCP 原生 key management service、KeyRing / CryptoKey Version 設計、CMEK 整合 &#43; Cloud HSM &#43; External Key Manager">Google Cloud KMS</a>（FPE / tokenization key）</li>
<li>SIEM 路由：<a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a>（DLP findings 進 SIEM correlation）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（DLP alert → IR handoff）</li>
<li>官方：<a href="https://cloud.google.com/sensitive-data-protection/docs">Google Cloud Sensitive Data Protection Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>Snyk</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/snyk/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/snyk/</guid><description>&lt;p>Snyk 是 &lt;em>developer-first&lt;/em> 的 &lt;em>跨 SCM 多模組 application security platform&lt;/em>、把 SCA、SAST、Container scan、IaC scan、CSPM 整合到一個 dashboard、五大模組共用同一套 Project / Issue / Fix 模型。流量打到 GitHub / GitLab / Bitbucket / Azure Repos 任一 SCM、Snyk 拉取 repo、按 manifest 建 Project、發現 Issue 後送 PR 修補。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &amp;#43; Secret Scanning &amp;#43; Dependency Review &amp;#43; Dependabot、跟 PR / Security tab 深度整合">GitHub Advanced Security&lt;/a> 比、Snyk &lt;em>跨 SCM&lt;/em> 跟 &lt;em>跨技術棧&lt;/em>；跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &amp;#43; Secret &amp;#43; License &amp;#43; SBOM、Apache 2.0、CI 友善">Trivy&lt;/a> 比、Snyk 是商業 SaaS、覆蓋面更廣、但年費按 Project 計價。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Snyk 的核心定位是 &lt;em>用一個工具一個 dashboard 同時管 SCA + SAST + IaC + Container + Cloud&lt;/em>。五大模組 — &lt;em>Snyk Open Source&lt;/em>（SCA、依賴漏洞）、&lt;em>Snyk Code&lt;/em>（SAST）、&lt;em>Snyk Container&lt;/em>（image scan）、&lt;em>Snyk IaC&lt;/em>（Terraform / CloudFormation / K8s manifest 安全）、&lt;em>Snyk Cloud&lt;/em>（CSPM、雲端配置 drift）— 共用 Project / Target / Organization / Issue 模型、Issue 跨模組可一起 prioritize。對 &lt;em>多 SCM + 多技術棧&lt;/em> 的組織、Snyk 比拼裝 GHAS + Trivy + Dependabot 更整合。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &amp;#43; Secret Scanning &amp;#43; Dependency Review &amp;#43; Dependabot、跟 PR / Security tab 深度整合">GitHub Advanced Security&lt;/a> 的核心差異是 &lt;em>部署模型跟 SCM 範圍&lt;/em>：GHAS 綁 GitHub、走 GitHub Actions、PR 整合更深（Code Scanning alert 直接顯示在 PR review）；Snyk 走 SaaS、SCM 中立、但需要 OAuth 連到每個 repo。組織用 GitLab / Bitbucket / Azure Repos 或同時用多種 SCM、Snyk 是天然選擇。&lt;/p></description><content:encoded><![CDATA[<p>Snyk 是 <em>developer-first</em> 的 <em>跨 SCM 多模組 application security platform</em>、把 SCA、SAST、Container scan、IaC scan、CSPM 整合到一個 dashboard、五大模組共用同一套 Project / Issue / Fix 模型。流量打到 GitHub / GitLab / Bitbucket / Azure Repos 任一 SCM、Snyk 拉取 repo、按 manifest 建 Project、發現 Issue 後送 PR 修補。跟 <a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GitHub Advanced Security</a> 比、Snyk <em>跨 SCM</em> 跟 <em>跨技術棧</em>；跟 <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> 比、Snyk 是商業 SaaS、覆蓋面更廣、但年費按 Project 計價。</p>
<h2 id="服務定位">服務定位</h2>
<p>Snyk 的核心定位是 <em>用一個工具一個 dashboard 同時管 SCA + SAST + IaC + Container + Cloud</em>。五大模組 — <em>Snyk Open Source</em>（SCA、依賴漏洞）、<em>Snyk Code</em>（SAST）、<em>Snyk Container</em>（image scan）、<em>Snyk IaC</em>（Terraform / CloudFormation / K8s manifest 安全）、<em>Snyk Cloud</em>（CSPM、雲端配置 drift）— 共用 Project / Target / Organization / Issue 模型、Issue 跨模組可一起 prioritize。對 <em>多 SCM + 多技術棧</em> 的組織、Snyk 比拼裝 GHAS + Trivy + Dependabot 更整合。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GitHub Advanced Security</a> 的核心差異是 <em>部署模型跟 SCM 範圍</em>：GHAS 綁 GitHub、走 GitHub Actions、PR 整合更深（Code Scanning alert 直接顯示在 PR review）；Snyk 走 SaaS、SCM 中立、但需要 OAuth 連到每個 repo。組織用 GitLab / Bitbucket / Azure Repos 或同時用多種 SCM、Snyk 是天然選擇。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> 比、Trivy 是 OSS、主 container + IaC、適合 CI 內 self-hosted；Snyk 商業 SaaS、覆蓋更廣（含 SAST 跟 Reachability）、適合 <em>組織級 governance + 跨團隊統一 dashboard</em>。Trivy 是 <em>跑工具</em>、Snyk 是 <em>買治理</em>。</p>
<p>關鍵張力：Snyk 的 <em>Project 是計費單位</em>。每個 manifest 算一個 Project（一個 repo 有 package.json + requirements.txt + Dockerfile = 3 Project）。大 monorepo 容易暴量、需要 <em>project filter / archive</em> 治理、否則年費失控。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>Snyk 五大模組在 application security stack 承擔哪一段、哪些靠其他工具</li>
<li>Project 計費模型、monorepo 跟 multi-manifest repo 的 Project 暴量風險跟治理路徑</li>
<li>Reachability analysis 的價值跟限制、何時減 noise、何時被誤判</li>
<li>何時用 Snyk、何時走 <a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GHAS</a> / <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> / <a href="/blog/backend/07-security-data-protection/vendors/dependabot/" data-link-title="Dependabot" data-link-desc="GitHub 原生依賴更新自動化、Version Update &#43; Security Update &#43; Alerts、Grouped Updates 減 PR noise、Auto-merge 配 branch protection">Dependabot</a> 的取捨</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Snyk 配置是否健康、最少看四件事：</p>
<ul>
<li><strong>誰能 enable Snyk</strong>：Organization 的 admin / collaborator role 配置、Service Account token scope（不要用 personal API token 跑 CI、用 Service Account + scoped token）、Audit Log 是否同步到 SIEM</li>
<li><strong>Project import 治理</strong>：每個 SCM target 自動 import 哪些 manifest、是否有 <em>project filter</em> 排除 test fixture / vendored dependency、archived project 是否真的不計費、monorepo 是否走 <em>.snyk policy file</em> 控制</li>
<li><strong>Reachability analysis 是否啟用</strong>：Snyk Code + Open Source 整合、call graph 分析「我的 code 真的呼叫到 vulnerable 函式嗎」— 大幅減少 <em>transitive dep 但 unreachable</em> 的 noise、production 應該啟用</li>
<li><strong>SBOM export 是否走 release pipeline</strong>：CycloneDX / SPDX 格式是否定期匯出、是否進 <a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">supply chain integrity</a> 流程、合規要求（EO 14028 / NIS2）是否覆蓋</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">Audit Log</a> 與 supply chain 治理邊界的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>Project / Target / Organization 模型</strong>：<em>Organization</em> 是計費跟 RBAC 邊界、對應一個團隊或一個 BU。<em>Target</em> 是一個 SCM 來源（一個 GitHub repo / 一個 container registry image / 一個 Terraform stack）。<em>Project</em> 是 Target 內的單一掃描單位（一個 manifest 或一個 image tag）。Issue 是發現的漏洞 / license / misconfig、有 severity（Critical / High / Medium / Low）、CVSS、exploit maturity、fix availability。Project 暴量的根因通常是 monorepo 內 nested manifest 全被 auto-import、用 <code>.snyk</code> 或 import filter 排除。</p>
<p><strong>五大模組分工</strong>：<em>Snyk Open Source</em>（SCA）掃 package manifest（npm、pip、Maven、Go modules、Composer、NuGet 等 20+ 生態）對 Snyk Vulnerability DB（自家維護、補強 NVD 延遲）。<em>Snyk Code</em>（SAST）掃源碼、symbolic execution + ML、覆蓋 OWASP Top 10 跟 CWE。<em>Snyk Container</em> 掃 image base layer + installed package、支援 Docker / OCI / ECR / GCR / Harbor。<em>Snyk IaC</em> 掃 Terraform / CloudFormation / K8s YAML / Helm chart 對 CIS Benchmark + custom policy。<em>Snyk Cloud</em>（2023 收購 Fugue 後加入）是 CSPM、scan AWS / Azure / GCP runtime 配置 + IaC drift detection（cloud 實際狀態 vs Terraform 狀態的差異）。</p>
<p><strong>Snyk Code (SAST) vs GHAS CodeQL</strong>：Snyk Code 走 <em>快速 inline scan</em>（秒級回饋、走 cloud inference）、適合 dev loop；CodeQL 走 <em>深度 dataflow query</em>（分鐘級、執行更慢但表達力更強）、適合 release gate。同時用兩者並不矛盾 — Snyk Code 在 IDE / PR 給快速訊號、CodeQL 在 release 前跑深度檢查。</p>
<p><strong>Reachability analysis</strong>：跟 <em>純 dependency list 比對 CVE</em> 不同、Snyk 結合 Snyk Code (SAST) 跟 Snyk Open Source (SCA)、做 <em>call graph 分析</em>、判斷「我的 code 是否真的呼叫到 vulnerable 函式」。實務影響：多數 transitive dependency 的 CVE 在你的 app 內 <em>不 reachable</em>（你引入的 lib 沒呼叫到那條 path）— Reachability 過濾後、可以從 <em>幾百個 Critical / High</em> 降到 <em>幾個真的 exploitable</em>。限制：只支援部分語言（Java / JS / Python / Go 較完整）、且 dynamic dispatch / reflection / runtime plugin load 會被當成 reachable（false positive）或 unreachable（false negative）— 不可全信、是 <em>prioritization signal</em> 不是 <em>binary verdict</em>。</p>
<p><strong>Fix advice / Auto PR</strong>：發現 vuln 後、Snyk 自動發 PR 升級到 <em>最小 fix version</em>（包含 transitive dep 的 root cause upgrade）。跟 <a href="/blog/backend/07-security-data-protection/vendors/dependabot/" data-link-title="Dependabot" data-link-desc="GitHub 原生依賴更新自動化、Version Update &#43; Security Update &#43; Alerts、Grouped Updates 減 PR noise、Auto-merge 配 branch protection">Dependabot</a> 功能重疊、差異是 Snyk 跨 SCM（不只 GitHub）、且 fix advice 含 Reachability 標註（reachable vuln 的 PR 優先級高）。重複用兩者要關掉其一、否則 PR 量翻倍。</p>
<p><strong>跟 CI 整合</strong>：<code>snyk</code> CLI（<code>snyk test</code> / <code>snyk monitor</code> / <code>snyk container test</code> / <code>snyk iac test</code>）走 SNYK_TOKEN 環境變數、可在任何 CI 跑。官方 Snyk Action（GitHub Actions）跟 Jenkins / GitLab CI / CircleCI plugin 是 wrapper。release gate 推薦在 build 後跑 <code>snyk test --severity-threshold=high --fail-on=upgradable</code>、只擋 <em>可升級</em> 的 high+ vuln（無 fix 的 vuln 阻塞 release 沒意義、走 <em>.snyk policy</em> 暫時 ignore + alert）。</p>
<p><strong>SBOM export</strong>：<code>snyk sbom --format=cyclonedx1.4+json</code> / <code>--format=spdx2.3+json</code> 產 SBOM、支援 Snyk attestation（signed SBOM）。近年 supply chain compliance（US EO 14028、EU NIS2 / CRA）要求 SBOM、Snyk 是自動產線之一。SBOM 應該在 <em>release artifact 旁</em> 一起發布、走 <a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">supply chain integrity</a> 流程。</p>
<p><strong>License compliance</strong>：除了漏洞、Snyk 也掃 dependency license（GPL / AGPL / LGPL / proprietary / unknown）、可設 <em>license policy</em>（allow / disallow / require-review）、PR 引入違規 license 直接 fail check。對需要避開 copyleft license 的商業產品、license scan 跟 vulnerability scan 一樣關鍵。</p>
<p><strong>API token 治理</strong>：CI / 第三方 integration 用 <em>Service Account + scoped token</em>（限 Organization、限 permission）、不要用個人 personal token（離職就失效）。Token 進 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a> / <a href="/blog/backend/07-security-data-protection/vendors/aws-secrets-manager/" data-link-title="AWS Secrets Manager" data-link-desc="AWS 原生 secret store &#43; 內建 RDS / Redshift rotation Lambda、Resource Policy 跨帳號共享、KMS 加密">AWS Secrets Manager</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-secret-manager/" data-link-title="Google Secret Manager" data-link-desc="GCP 原生 secret store、CMEK &#43; Workload Identity Federation 整合、rotation 走自寫 Cloud Function 而非 built-in Lambda">Google Secret Manager</a>、定期 rotate。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Snyk</th>
          <th>GitHub Advanced Security</th>
          <th>Trivy</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>部署模型</td>
          <td>商業 SaaS</td>
          <td>GitHub 整合 SaaS</td>
          <td>OSS、self-hosted CLI</td>
      </tr>
      <tr>
          <td>SCM 範圍</td>
          <td>跨 SCM（GitHub / GitLab / Bitbucket / Azure Repos）</td>
          <td>GitHub only</td>
          <td>SCM 無關（CI / local 跑）</td>
      </tr>
      <tr>
          <td>SCA</td>
          <td>Snyk Open Source（含 Reachability）</td>
          <td>Dependabot（純 manifest 比對）</td>
          <td>是、限 OS package + language package</td>
      </tr>
      <tr>
          <td>SAST</td>
          <td>Snyk Code（fast inline）</td>
          <td>CodeQL（dataflow query）</td>
          <td>否</td>
      </tr>
      <tr>
          <td>Container scan</td>
          <td>Snyk Container</td>
          <td>透過 Dependabot + 第三方</td>
          <td>Trivy Container（主打）</td>
      </tr>
      <tr>
          <td>IaC scan</td>
          <td>Snyk IaC</td>
          <td>透過 Code Scanning + KICS / Checkov</td>
          <td>Trivy Config（主打）</td>
      </tr>
      <tr>
          <td>CSPM</td>
          <td>Snyk Cloud</td>
          <td>無</td>
          <td>無</td>
      </tr>
      <tr>
          <td>Reachability</td>
          <td>有（限部分語言）</td>
          <td>部分 CodeQL query 有</td>
          <td>無</td>
      </tr>
      <tr>
          <td>Auto-fix PR</td>
          <td>Snyk PR + fix advice</td>
          <td>Dependabot PR</td>
          <td>無</td>
      </tr>
      <tr>
          <td>計費模型</td>
          <td>按 Project（manifest）數</td>
          <td>GitHub seat-based</td>
          <td>免費</td>
      </tr>
      <tr>
          <td>學習曲線</td>
          <td>中 — UI 友善、CLI 直觀</td>
          <td>低 — 跟 GitHub 一體</td>
          <td>低 — 單一 binary、CLI 為主</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>多 SCM + 多 stack + 想統一 dashboard</td>
          <td>純 GitHub + 想跟 PR 深整合</td>
          <td>純 container / IaC + 想 OSS + 預算敏感</td>
      </tr>
  </tbody>
</table>
<p>選 Snyk 的核心訴求：<em>組織用多個 SCM 或多技術棧（後端 + 前端 + container + Terraform + cloud）</em> + 需要 <em>統一 dashboard + 跨團隊 prioritization</em> + 接受按 Project 計費的成本。純 GitHub 組織用 GHAS 更整合、純 container CI 用 Trivy 免費、極大型 monorepo 用 Snyk 容易爆 Project 數要小心。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Snyk Cloud (CSPM) 跟 IaC drift detection</strong>：Snyk Cloud 連 AWS / Azure / GCP read-only role、掃 runtime 配置（S3 bucket public、IAM over-permission、security group 0.0.0.0/0）對 CIS Benchmark + custom policy。跟 <em>Snyk IaC</em> 結合做 <em>drift detection</em> — Terraform 內定義是 private bucket、但 cloud 實際是 public（有人 console 手改）、Snyk 報 drift。對標 <a href="https://www.wiz.io/">Wiz</a> / Prisma Cloud / Lacework、Snyk Cloud 是 <em>跟 Snyk IaC 同源治理</em> 的優勢（同個 dashboard 看 IaC + runtime）。</p>
<p><strong>Custom Rule（Snyk IaC custom policy）</strong>：Snyk IaC 預設規則庫覆蓋 CIS Benchmark + AWS / GCP / Azure 最佳實踐、可寫 <em>custom policy</em>（Rego-like / SnykIQL）擴展。例：禁止 RDS 沒開 encryption-at-rest、禁止 S3 沒 versioning、禁止 K8s pod 跑 hostNetwork。Custom policy 走版控（git）跟 PR review、避免在 console 直接改。</p>
<p><strong>Reachability vs 純 static SCA</strong>：純 SCA（如 Dependabot / Trivy）只看 <em>manifest 中聲明的版本是否有 CVE</em>、不分 reachable / unreachable。結果是 Critical / High alert 大量、開發者 <em>alert fatigue</em> 後直接 ignore。Snyk Reachability 用 SAST + SCA 整合做 call graph、過濾掉 <em>vulnerable lib 載入了但 vulnerable 函式從未被呼叫</em> 的案例。限制：dynamic dispatch / reflection / 動態載入 plugin / native binding 都會讓 reachability 判斷失準、不可當成 binary truth。</p>
<p><strong>Snyk Insights（風險優先級 prioritization）</strong>：除了 CVSS、Snyk 加入 <em>exploit maturity</em>（exploit in-the-wild / PoC / no known exploit）、<em>fix availability</em>（有無 fix version）、<em>social trend</em>（CVE 被討論度）、<em>Reachability</em> 綜合算 <em>Priority Score</em>。production 用 Priority Score 排 backlog、而非單純 CVSS — 一個 <em>Critical 但 unreachable + no fix</em> 的 vuln 不該擋 release。</p>
<p><strong>SBOM 流程整合</strong>：把 <code>snyk sbom</code> 接到 CI release step、SBOM artifact 跟 release binary 一起進 registry / object store、走 <a href="https://in-toto.io/">in-toto attestation</a> 或 <a href="https://slsa.dev/">SLSA</a> provenance 流程、合規時可回溯。跟 <a href="/blog/backend/07-security-data-protection/vendors/syft-grype/" data-link-title="Syft &#43; Grype" data-link-desc="Anchore 開源姐妹工具：Syft 產 SBOM (CycloneDX / SPDX) &#43; Grype scan 漏洞、Unix philosophy、cosign attestation 整合">Syft + Grype</a> 流程的差異：Syft + Grype 是 OSS local-first + Unix philosophy、Snyk 是 SaaS、SBOM 含 Snyk Issue ID 跟 fix advice link。</p>
<p><strong>License policy enforcement</strong>：除了 vulnerability、license 違規（GPL / AGPL 引入到 proprietary product、unknown license dep）走同套 policy / PR fail-check 機制、production 應該把 license policy 跟 vulnerability policy 並列當 release gate。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Project 暴量計費</strong>：monorepo 自動 import 把 test fixture / node_modules-vendored 全當 Project — 用 <em>.snyk</em> 跟 import filter 排除、archived project 確認真的不計費</li>
<li><strong>Reachability 漏判 / 誤判</strong>：dynamic dispatch / reflection / plugin load 讓 call graph 失準、Critical vuln 被標 unreachable 但實際 reachable — 對 framework-heavy code（Spring / Django middleware / Rails initializer）保守處理、不全信 Reachability</li>
<li><strong>PR noise</strong>：Snyk + Dependabot 同時開、依賴升級 PR 翻倍 — 二選一、或讓 Snyk 處理 vuln-driven upgrade、Dependabot 處理 routine version bump</li>
<li><strong>CI fail-on 設不對</strong>：<code>--severity-threshold=low</code> 把 release 整個擋死 / <code>--severity-threshold=critical</code> 漏 high — production 通常 <code>--severity-threshold=high --fail-on=upgradable</code>、再用 <code>.snyk</code> policy file 例外管理</li>
<li><strong>License check 誤殺</strong>：transitive dep 引入 LGPL 被當 GPL 阻擋 — 細分 license policy（allow LGPL-with-dynamic-linking、disallow GPL）、走 review workflow 而非 fail-fast</li>
<li><strong>API token over-scoped</strong>：CI 拿到 admin-level Service Account token、整 org Project 都能改 — 改 scoped token、限 Organization + 限 permission、進 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a></li>
<li><strong>SBOM 沒進 release pipeline</strong>：SBOM 只在 Snyk dashboard、release artifact 沒附 — 把 <code>snyk sbom</code> 加進 CI release step、SBOM 跟 binary 一起發</li>
<li><strong>Snyk Cloud drift 沒人看</strong>：CSPM alert 進 dashboard 但沒 routing 到 on-call — 接 <a href="/blog/backend/07-security-data-protection/vendors/" data-link-title="資安與資料保護 Vendor 清單" data-link-desc="規劃身份、秘密、金鑰、入口防護、供應鏈與偵測工具的服務頁撰寫順序與教學大綱">SIEM</a> / Slack / PagerDuty、高 severity drift 觸發 ticket</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>純 GitHub + 想跟 PR / Action 深整合</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GitHub Advanced Security</a></td>
      </tr>
      <tr>
          <td>純 container / IaC + OSS + 預算敏感</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a></td>
      </tr>
      <tr>
          <td>純 dependency 升級（routine version bump）</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/dependabot/" data-link-title="Dependabot" data-link-desc="GitHub 原生依賴更新自動化、Version Update &#43; Security Update &#43; Alerts、Grouped Updates 減 PR noise、Auto-merge 配 branch protection">Dependabot</a></td>
      </tr>
      <tr>
          <td>Secret scanning（leaked API key in repo）</td>
          <td>GitGuardian / Gitleaks（Snyk 不主打）</td>
      </tr>
      <tr>
          <td>Runtime container threat detection</td>
          <td>Falco / Cilium Tetragon</td>
      </tr>
      <tr>
          <td>深度 SAST（dataflow query / taint analysis）</td>
          <td>CodeQL / Semgrep（Snyk Code 偏 fast inline、深度查走 CodeQL）</td>
      </tr>
      <tr>
          <td>CSPM 跨 multi-cloud + asset inventory</td>
          <td>Wiz / Prisma Cloud / Lacework（Snyk Cloud 較新、功能仍在追）</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Snyk 完整 pricing tier（Team / Business / Enterprise）跟 Project 計費細節</li>
<li>Snyk Vulnerability DB 跟 NVD / GHSA 的覆蓋差異對照</li>
<li>Snyk Code SAST 規則完整 reference</li>
<li>Snyk IaC 內建 policy 完整列表 + CIS Benchmark 對照</li>
<li>Snyk Cloud 多雲 onboarding 步驟（AWS / Azure / GCP read-only role 設置）</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>Snyk 在 07 案例庫沒有直接 vendor-level 事件、但多個 supply chain 案例展示 Snyk 工具能力的 <em>範圍跟邊界</em>：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 Snyk 的關係</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/log4shell-cve-2021-44228-component-chain/" data-link-title="7.R7.2.7 Log4Shell 2021：共用元件風險與修補鏈" data-link-desc="共用元件漏洞如何同步影響多服務，並迫使團隊建立依賴治理 workflow">Log4Shell CVE-2021-44228</a></td>
          <td>對照啟示 — Reachability analysis 能快速回答「我的 service 是否真用到 vulnerable JndiLookup」、減少 emergency triage 的 noise</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/xz-backdoor-2024-open-source-supply-chain/" data-link-title="7.R7.2.4 XZ Backdoor 2024：開源供應鏈長期滲透" data-link-desc="開源維護鏈遭滲透後，為何會直接影響廣泛 Linux 發行流程">XZ Backdoor 2024 Open Source Supply Chain</a></td>
          <td>對照啟示 — Snyk 看 package version + CVE、看不到 maintainer takeover；需補 release-tarball 比對 + maintainer trust signal</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/3cx-2023-desktopapp-supply-chain/" data-link-title="7.R7.2.8 3CX 2023：桌面軟體更新鏈攻擊" data-link-desc="合法更新流程被植入後，桌面端供應鏈事件如何傳到企業端點">3CX 2023 Desktop App Supply Chain</a></td>
          <td>對照啟示 — Snyk Container 看 image 內 package CVE、看不到 update channel 被植入；需配合 artifact provenance / SLSA</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">7.12 供應鏈完整性與 Artifact 信任</a></td>
          <td>章節對應 — Snyk SBOM + License policy 是 supply chain governance 的工具、合規門檻（EO 14028 / NIS2）的標準產線之一</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">7.12 供應鏈完整性與 Artifact 信任</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GitHub Advanced Security</a>、<a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a>、<a href="/blog/backend/07-security-data-protection/vendors/dependabot/" data-link-title="Dependabot" data-link-desc="GitHub 原生依賴更新自動化、Version Update &#43; Security Update &#43; Alerts、Grouped Updates 減 PR noise、Auto-merge 配 branch protection">Dependabot</a></li>
<li>下游：<a href="/blog/backend/07-security-data-protection/data-protection-and-masking-governance/" data-link-title="7.4 資料保護與遮罩治理" data-link-desc="以問題驅動方式整理資料分級、遮罩、匯出與備份治理">7.4 資料保護與遮罩治理</a>（vuln 阻擋不完全時、資料層也要遮罩）</li>
<li>跨類：<a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a>、<a href="/blog/backend/07-security-data-protection/vendors/aws-secrets-manager/" data-link-title="AWS Secrets Manager" data-link-desc="AWS 原生 secret store &#43; 內建 RDS / Redshift rotation Lambda、Resource Policy 跨帳號共享、KMS 加密">AWS Secrets Manager</a>（Snyk API token 存放）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（Critical CVE 揭露時的 emergency triage routing）</li>
<li>官方：<a href="https://docs.snyk.io/">Snyk Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>Vegeta</title><link>https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/vegeta/</link><pubDate>Fri, 15 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/vegeta/</guid><description>&lt;p>Vegeta 的核心責任是用簡潔 CLI 對 HTTP endpoint 產生固定 rate 負載，快速探測 latency、throughput、error rate 與 saturation。它適合單一 endpoint、少量 header / body 變化、快速 baseline、incident 後驗證與工程師本機或 CI 中的輕量壓測。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Vegeta 是 Go 寫的 HTTP load testing CLI，核心模型是 &lt;em>constant rate attack&lt;/em>：指定「每秒 N 個 request」就持續打 N rps、不會因 server 變慢就降速，跟「fire-and-wait」型工具（hey / wrk 預設 closed-loop）行為差異很大。constant rate 是 &lt;em>open-loop&lt;/em> 模型 — 模擬真實流量「不會因服務慢而減少」的行為、所以 saturation 點才會明確浮現。&lt;/p>
&lt;p>Vegeta 是 Unix philosophy CLI：targets 從 stdin 讀（可以 pipe 進複雜 generator）、binary report 從 stdout 出（可以 pipe 進 &lt;code>vegeta report&lt;/code> / &lt;code>vegeta plot&lt;/code> / &lt;code>vegeta encode&lt;/code>）。這個設計讓 Vegeta 容易跟 shell pipeline / CI script 接合、但同時也決定它不適合表達多步驟 session。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/k6/" data-link-title="k6" data-link-desc="用 scriptable scenario 建立 API、protocol 與 CI 友善壓測的效能工程工具">k6&lt;/a> 比、Vegeta 走 &lt;em>CLI-first + open-loop constant rate&lt;/em>、k6 走 &lt;em>JS scenario + threshold + CI artifact&lt;/em>。Vegeta 適合「我要對這個 URL 打 200 rps 60 秒」的一次性壓測、k6 適合「我有 3 種 user journey、各占 40/30/30%、跑 ramp-up profile」的可維護 scenario。跟 hey 比、Vegeta 的 constant rate 是真的 open-loop、hey 的 &lt;code>-q&lt;/code> 是 per-worker rate（worker 變慢整體就降速）— 探測 saturation 時 Vegeta 比較誠實。跟 wrk / wrk2 比、Vegeta 沒有 LuaJIT 那麼極致的單機壓測效能、但 binary report + &lt;code>vegeta plot&lt;/code> + targets pipe 對日常工程師工作流更友善。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本頁、讀者能判斷：&lt;/p>
&lt;ol>
&lt;li>何時用 Vegeta、何時走 k6 / hey / wrk / Gatling / Locust 的取捨&lt;/li>
&lt;li>constant rate attack 的設計意涵（open-loop vs closed-loop、為什麼這對 saturation discovery 重要）&lt;/li>
&lt;li>target file / rate / duration / report 四件套的 baseline workflow 跟 evidence package 對應&lt;/li>
&lt;li>排錯時的常見陷阱：runner 端 TCP socket exhaust、open file limit、constant rate 跟 target server 限速 disconnect&lt;/li>
&lt;/ol>
&lt;h2 id="定位">定位&lt;/h2>
&lt;p>Vegeta 適合快速回答「這個 endpoint 在某個 rate 下表現如何」。當團隊需要先找出大概 knee point、驗證一個修補是否降低 latency、或在 CI 裡跑小型 performance smoke test，Vegeta 的 CLI workflow 很直接。&lt;/p></description><content:encoded><![CDATA[<p>Vegeta 的核心責任是用簡潔 CLI 對 HTTP endpoint 產生固定 rate 負載，快速探測 latency、throughput、error rate 與 saturation。它適合單一 endpoint、少量 header / body 變化、快速 baseline、incident 後驗證與工程師本機或 CI 中的輕量壓測。</p>
<h2 id="服務定位">服務定位</h2>
<p>Vegeta 是 Go 寫的 HTTP load testing CLI，核心模型是 <em>constant rate attack</em>：指定「每秒 N 個 request」就持續打 N rps、不會因 server 變慢就降速，跟「fire-and-wait」型工具（hey / wrk 預設 closed-loop）行為差異很大。constant rate 是 <em>open-loop</em> 模型 — 模擬真實流量「不會因服務慢而減少」的行為、所以 saturation 點才會明確浮現。</p>
<p>Vegeta 是 Unix philosophy CLI：targets 從 stdin 讀（可以 pipe 進複雜 generator）、binary report 從 stdout 出（可以 pipe 進 <code>vegeta report</code> / <code>vegeta plot</code> / <code>vegeta encode</code>）。這個設計讓 Vegeta 容易跟 shell pipeline / CI script 接合、但同時也決定它不適合表達多步驟 session。</p>
<p>跟 <a href="/blog/backend/09-performance-capacity/vendors/k6/" data-link-title="k6" data-link-desc="用 scriptable scenario 建立 API、protocol 與 CI 友善壓測的效能工程工具">k6</a> 比、Vegeta 走 <em>CLI-first + open-loop constant rate</em>、k6 走 <em>JS scenario + threshold + CI artifact</em>。Vegeta 適合「我要對這個 URL 打 200 rps 60 秒」的一次性壓測、k6 適合「我有 3 種 user journey、各占 40/30/30%、跑 ramp-up profile」的可維護 scenario。跟 hey 比、Vegeta 的 constant rate 是真的 open-loop、hey 的 <code>-q</code> 是 per-worker rate（worker 變慢整體就降速）— 探測 saturation 時 Vegeta 比較誠實。跟 wrk / wrk2 比、Vegeta 沒有 LuaJIT 那麼極致的單機壓測效能、但 binary report + <code>vegeta plot</code> + targets pipe 對日常工程師工作流更友善。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>何時用 Vegeta、何時走 k6 / hey / wrk / Gatling / Locust 的取捨</li>
<li>constant rate attack 的設計意涵（open-loop vs closed-loop、為什麼這對 saturation discovery 重要）</li>
<li>target file / rate / duration / report 四件套的 baseline workflow 跟 evidence package 對應</li>
<li>排錯時的常見陷阱：runner 端 TCP socket exhaust、open file limit、constant rate 跟 target server 限速 disconnect</li>
</ol>
<h2 id="定位">定位</h2>
<p>Vegeta 適合快速回答「這個 endpoint 在某個 rate 下表現如何」。當團隊需要先找出大概 knee point、驗證一個修補是否降低 latency、或在 CI 裡跑小型 performance smoke test，Vegeta 的 CLI workflow 很直接。</p>
<p>這個定位讓 Vegeta 接到 <a href="/blog/backend/09-performance-capacity/saturation-discovery/" data-link-title="9.4 Saturation Discovery" data-link-desc="找出 throughput plateau 與 latency knee 的方法">9.4 Saturation Discovery</a> 與 <a href="/blog/backend/09-performance-capacity/bottleneck-localization/" data-link-title="9.5 瓶頸定位流程" data-link-desc="從 app 到 DB / cache / broker / 第三方 quota 的逐層瓶頸定位">9.5 瓶頸定位流程</a>。它提供的是快速壓力探針，後續若要表達複雜 workload model，通常要轉向 k6、Gatling、Locust 或 JMeter。</p>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷一次 Vegeta 壓測是否有效、最少看四件事：</p>
<ul>
<li><strong>Target 描述完整性</strong>：targets file 是否包含 method / URL / headers / body、是否反映真實 request shape（含 auth header、content-type、representative payload size），缺一就會讓壓測結果偏離正式環境</li>
<li><strong>Rate model 設計</strong>：選的是 constant rate（<code>-rate=200/s</code>）還是 ramp（用多段 attack pipe），constant rate 適合 saturation probe、ramp-up 要 wrap script 自己 stage、Vegeta 沒有原生 ramp profile</li>
<li><strong>Report 解讀</strong>：<code>vegeta report</code> 給 mean / p50 / p95 / p99 / max latency + success rate + throughput，重點看 <em>p99 跟 max 的距離</em> 與 <em>requested rate vs actual throughput</em> 是否 disconnect — disconnect 表示 server / runner 端有人在限速</li>
<li><strong>Duration vs warm-up</strong>：短 duration（&lt; 30s）容易吃到 JIT / cache / connection pool warm-up 噪音，baseline 壓測 duration 至少 60s、且第一段 result 要 discard，否則 p99 會被前 5s 拉高</li>
</ul>
<h2 id="適用場景">適用場景</h2>
<p>單 endpoint saturation probe 是 Vegeta 的主要入口。工程師可以對 login、search、read API、feature flag endpoint 或 internal health-like endpoint 施加固定 rate，觀察 p95 / p99 與 error rate 何時開始上升。</p>
<p>Regression smoke test 適合用 Vegeta。CI 或 pre-release 可以用短時間固定 rate 測試，確認 hot path 沒有明顯退化，再把更完整的 scenario 交給 k6、Gatling 或 Locust。</p>
<p>Incident 後修補驗證適合用 Vegeta。當事故根因是某個 endpoint 的 query、cache miss、lock contention 或 timeout，修補後可以用相同 request set 重跑，快速比較 latency distribution。</p>
<h2 id="選型判準">選型判準</h2>
<table>
  <thead>
      <tr>
          <th>判準</th>
          <th>Vegeta 的價值</th>
          <th>需要補的能力</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>CLI 簡潔</td>
          <td>本機、CI、shell workflow 容易接</td>
          <td>長期報表與 artifact 標準化</td>
      </tr>
      <tr>
          <td>固定 rate</td>
          <td>探測 rate / latency 關係清楚</td>
          <td>複雜使用者行為與 arrival pattern</td>
      </tr>
      <tr>
          <td>HTTP 導向</td>
          <td>API hot path 快速驗證</td>
          <td>非 HTTP protocol 與 multi-step flow</td>
      </tr>
      <tr>
          <td>快速 probe</td>
          <td>適合 smoke test 與修補驗證</td>
          <td>完整 workload model 與資料治理</td>
      </tr>
  </tbody>
</table>
<p>CLI 簡潔價值來自低摩擦。當問題還在定位階段，工程師可以很快產生可重跑 command 與 target file，先取得 baseline，再決定是否需要完整壓測平台。</p>
<p>固定 rate 價值來自可比較。用相同 request set、rate、duration 與 target environment 重跑，可以讓修補前後的 latency distribution 有清楚對照。</p>
<h2 id="跟其他工具的取捨">跟其他工具的取捨</h2>
<p>Vegeta 和 k6 的主要差異是 scenario 深度。Vegeta 適合固定 rate HTTP probe；k6 適合多步驟 scenario、threshold、CI artifact 與 browser-style flow。</p>
<p>Vegeta 和 JMeter 的主要差異是工具重量。Vegeta 適合快速 CLI；JMeter 適合 GUI、多 protocol、plugin 與企業測試資產。</p>
<p>Vegeta 和 Gatling 的主要差異是長期維護模式。Vegeta 用 command / target file 保持簡單；Gatling 用 simulation 維護複雜 flow 與 injection profile。</p>
<p>Vegeta 和 Locust 的主要差異是自訂能力。Locust 適合 Python user behavior 與 custom client；Vegeta 適合 HTTP endpoint 的直接壓力測量。</p>
<h2 id="操作成本">操作成本</h2>
<p>Vegeta 的主要成本是 workload coverage 有限。它能快速測 endpoint，但多步驟 session、資料依賴、payment mock、queue side effect 與 realistic user journey 需要額外工具或腳本補上。</p>
<p>Artifact 成本來自命令可追溯性。每次測試要保存 rate、duration、targets、headers、body、環境、版本與結果檔；否則快速 probe 很容易變成不可比較的一次性觀察。</p>
<p>Runner 成本通常較低，但仍要檢查本機瓶頸。高 rate 測試時，產生負載的機器也可能先被 CPU、network、file descriptor 或 connection limit 卡住。</p>
<h2 id="evidence-package">Evidence Package</h2>
<p>Vegeta 結果應回寫到 evidence package。最小欄位包括 command、target file hash、rate、duration、workers、target environment、p95 / p99、max latency、error rate、throughput、target saturation metric、known gap 與 owner。</p>
<table>
  <thead>
      <tr>
          <th>欄位</th>
          <th>Vegeta 證據來源</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Source</td>
          <td>command、targets file、binary result、report</td>
      </tr>
      <tr>
          <td>Time range</td>
          <td>test start / end</td>
      </tr>
      <tr>
          <td>Query link</td>
          <td>APM / metrics / logs 查詢連結</td>
      </tr>
      <tr>
          <td>Data quality</td>
          <td>target set freshness、header / body correctness</td>
      </tr>
      <tr>
          <td>Confidence</td>
          <td>runner capacity、endpoint representativeness</td>
      </tr>
      <tr>
          <td>Known gap</td>
          <td>未覆蓋多步驟 flow、資料偏差、runner limit</td>
      </tr>
  </tbody>
</table>
<p>Evidence package 的核心用途是讓快速測試可以比較。Vegeta 的結果通常很短，反而更需要保存 command 與 target set，讓下一次修補驗證能跑同一組條件。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Vegeta</th>
          <th>k6</th>
          <th>hey</th>
          <th>wrk / wrk2</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>負載模型</td>
          <td>Open-loop constant rate（rps 不隨 latency 降）</td>
          <td>Open-loop（k6 default）/ closed-loop（VU mode）</td>
          <td>Per-worker rate（closed-loop 傾向）</td>
          <td>wrk closed-loop / wrk2 open-loop</td>
      </tr>
      <tr>
          <td>Scenario 深度</td>
          <td>單 endpoint pipe target、多 endpoint 需 script</td>
          <td>JS script、多步驟、staging / threshold / SLO 內建</td>
          <td>單一 URL CLI flag</td>
          <td>Lua script 可寫複雜邏輯但 idiom 較陡</td>
      </tr>
      <tr>
          <td>輸出形式</td>
          <td>Binary stream + <code>vegeta report/plot/encode</code></td>
          <td>stdout summary + JSON + 內建 dashboard</td>
          <td>stdout 文字 summary</td>
          <td>stdout 文字 summary、HdrHistogram</td>
      </tr>
      <tr>
          <td>CI 整合</td>
          <td>用 shell 包、自寫 threshold gate</td>
          <td>內建 threshold / exit code、CI artifact 標準化</td>
          <td>簡單 smoke、無 threshold</td>
          <td>需自寫 wrapper</td>
      </tr>
      <tr>
          <td>學習成本</td>
          <td>低 — 幾個 flag 就上手</td>
          <td>中 — 要寫 JS scenario</td>
          <td>極低 — 一行 CLI</td>
          <td>中 — Lua 加 HdrHistogram 概念</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>修補驗證、CI smoke、saturation probe</td>
          <td>完整壓測平台、SLO gate、多 scenario</td>
          <td>一次性 ad-hoc 探測</td>
          <td>極致單機壓測效能、低 overhead 量測</td>
      </tr>
  </tbody>
</table>
<p>選 Vegeta 的核心訴求：<em>工程師本機 / CI smoke / 修補驗證 / saturation probe</em> 都要快速可重跑、且結果要可以保存比較；不需要完整 scenario 模型也不需要 GUI 報表。若團隊需要完整 user journey、threshold / SLO gate、長期 trend dashboard，直接走 <a href="/blog/backend/09-performance-capacity/vendors/k6/" data-link-title="k6" data-link-desc="用 scriptable scenario 建立 API、protocol 與 CI 友善壓測的效能工程工具">k6</a> 或 <a href="/blog/backend/09-performance-capacity/vendors/gatling/" data-link-title="Gatling" data-link-desc="用 JVM DSL、simulation 與 injection profile 表達複雜 scenario 的效能工程工具">Gatling</a>。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Reporting 多輸出 format</strong>：<code>vegeta report</code> 預設 text summary、加 <code>-type=hist[0,10ms,50ms,100ms,500ms]</code> 給 latency bucket histogram、<code>-type=json</code> 給機器可讀 result、<code>vegeta plot</code> 出 HTML latency chart、<code>vegeta encode -to=csv</code> 轉成可進 spreadsheet / dashboard 的 CSV。binary result 檔可重複 decode 成不同 format，不用重跑壓測。修補驗證的標準作法是保留 <code>results.bin</code>、之後可隨時 re-render report。</p>
<p><strong>Pipe attack workflow</strong>：Vegeta 的 stdin/stdout 都是 stream — 可以用 shell pipe 串接 <code>jq</code> 動態產 targets（<code>jq -r '.urls[] | &quot;GET &quot; + .'</code>）、用 <code>vegeta attack | tee results.bin | vegeta report</code> 同時寫檔跟即時看 summary、用 <code>cat results-old.bin results-new.bin | vegeta report</code> 比較兩次結果。這個設計讓 Vegeta 跟 incident drill / chaos test script 容易接合 — 修補 deploy 完跑一次 attack、result 直接 commit 進 git 當 evidence。</p>
<p><strong>CI integration pattern</strong>：CI 裡 Vegeta 沒有 k6 那種內建 threshold，要自寫 gate — <code>vegeta report -type=json results.bin | jq '.latencies.p99'</code> 出 p99、bash 比較 budget、超標 exit 非零。把 <code>targets.txt</code> + <code>attack.sh</code> + <code>expected-budget.json</code> commit 進 repo、CI artifact 上傳 <code>results.bin</code> + <code>plot.html</code>，下次 regression 時可以 diff。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Requested rate 跟 actual throughput disconnect（要 200rps 實際只跑 80rps）</strong>：runner 端先飽和、不是 server 飽和 — 看 <code>vegeta attack</code> stderr 是否報 <code>socket: too many open files</code>、檢查 <code>ulimit -n</code>（生產壓測 runner 至少設 65535）；或 server 端有限速 / rate limit / connection cap 把 request reject 在 TCP 層、Vegeta 看不到完整 response 就被卡</li>
<li><strong>TCP socket exhaust（runner 端）</strong>：constant rate 模型下、若 server 回應慢、connection 會堆積、<code>TIME_WAIT</code> socket 爆 ephemeral port range — 用 <code>-keepalive=true</code>（預設）並調 <code>net.ipv4.tcp_tw_reuse=1</code>、或加 <code>-connections=N</code> 限制 connection pool 上限避免無限堆 socket</li>
<li><strong>p99 / max latency 異常高、但 server-side metrics 看不到</strong>：runner 端 GC pause / CPU steal / network jitter 把 latency 量測污染 — 把 runner 移到跟 target 同 placement group / same AZ、確認 runner CPU 沒被其他 process 搶、duration 拉長到 5min 讓 outlier 變稀釋</li>
<li><strong>Success rate 100% 但 server 已經爆</strong>：targets 沒帶 auth header / 打到 LB 而非 backend、所有 request 在前面就 200 / cache hit、server 根本沒收到壓力 — 檢查 target server access log 的 request count 跟 Vegeta requested rate 是否對得上</li>
<li><strong>短時間壓測結果不穩定（同 command 跑兩次差很多）</strong>：duration 太短（&lt; 30s）、warm-up 噪音占比太高 — 至少 60s、第一段 5-10s discard、若 endpoint 有 lazy initialization（cache / connection pool / JIT compile）先跑一段 warm-up attack 再正式量</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>Vegeta 適合回寫單 endpoint hot path 與修補驗證案例。它可接 <a href="/blog/backend/09-performance-capacity/cases/coinbase-ultra-low-latency-exchange-2023/" data-link-title="9.C3 Coinbase International Exchange：超低延遲交易的逆向容量設計" data-link-desc="為什麼 Coinbase 國際交易所選 Cluster Placement Group &#43; z1d 而不是自動擴容 — 延遲敏感型負載的容量取捨">9.C3 Coinbase ultra-low latency</a> 的 sub-millisecond latency distribution 判讀、<a href="/blog/backend/09-performance-capacity/cases/tubi-elasticache-ml-feature-store/" data-link-title="9.C25 Tubi：從 ScyllaDB 遷到 ElastiCache、ML feature store 達 sub-10ms p99" data-link-desc="Tubi 把 ML 推薦的 feature store 從 ScyllaDB 遷到 ElastiCache for Redis、99 百分位延遲降到 10ms 以下">9.C25 Tubi feature store</a> 的 p99 &lt; 10ms lookup 驗證、<a href="/blog/backend/09-performance-capacity/cases/ntt-docomo-lemino-japanese-streaming/" data-link-title="9.C29 NTT DOCOMO Lemino：3 個月達 500 萬 MAU 的串流後端" data-link-desc="Lemino 用 DynamoDB &#43; AWS Media Services 撐 30 channels live &#43; 5M MAU、工程工時下降 90%">9.C29 Lemino connection limit</a> 的 RDB bottleneck 探測、<a href="/blog/backend/09-performance-capacity/cases/tinder-elasticache-valkey-matching/" data-link-title="9.C6 Tinder：ElastiCache for Valkey 撐 4700 萬月活的配對引擎" data-link-desc="Tinder 用 Amazon ElastiCache for Valkey 提供配對引擎所需的次毫秒延遲快取層">9.C6 Tinder ElastiCache</a> 的次毫秒 cache lookup 驗證，以及 <a href="/blog/backend/09-performance-capacity/cases/amazon-ads-dynamodb-extreme-kv/" data-link-title="9.C5 Amazon Ads：DynamoDB 9000 萬 reads/sec 的廣告事件量測" data-link-desc="Amazon Ads 在 DynamoDB 上跑 9000 萬 reads/sec &#43; 500 萬 writes/sec、99.999% 可用性的廣告事件量測">9.C5 Amazon Ads DynamoDB</a> 的 hot partition 探測。</p>
<p>這些案例的重點是快速定位與比較。Vegeta 頁引用案例時，要把 case 轉成 endpoint、rate、duration、latency budget、target saturation metric 與 runner limit — 例如 Coinbase 的 sub-ms 目標要求 Vegeta runner 必須跟 target 同 placement group、否則 runner 自身的網路 jitter 會吃掉觀測精度。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/09-performance-capacity/saturation-discovery/" data-link-title="9.4 Saturation Discovery" data-link-desc="找出 throughput plateau 與 latency knee 的方法">9.4 Saturation Discovery</a></li>
<li>上游：<a href="/blog/backend/09-performance-capacity/bottleneck-localization/" data-link-title="9.5 瓶頸定位流程" data-link-desc="從 app 到 DB / cache / broker / 第三方 quota 的逐層瓶頸定位">9.5 瓶頸定位流程</a></li>
<li>平行：<a href="/blog/backend/09-performance-capacity/vendors/k6/" data-link-title="k6" data-link-desc="用 scriptable scenario 建立 API、protocol 與 CI 友善壓測的效能工程工具">k6</a>、<a href="/blog/backend/09-performance-capacity/vendors/gatling/" data-link-title="Gatling" data-link-desc="用 JVM DSL、simulation 與 injection profile 表達複雜 scenario 的效能工程工具">Gatling</a>、<a href="/blog/backend/09-performance-capacity/vendors/locust/" data-link-title="Locust" data-link-desc="用 Python user behavior 與 distributed worker 表達高自訂負載模型的效能工程工具">Locust</a></li>
<li>跨模組：<a href="/blog/backend/06-reliability/performance-regression-gate/" data-link-title="6.13 Performance Regression Gate" data-link-desc="把效能 baseline 從一次性壓測變成持續對齊的 release gate，涵蓋 baseline 設定、判讀方法、variance 控制與退化定位">6.13 Performance Regression Gate</a></li>
<li>官方：<a href="https://github.com/tsenart/vegeta">Vegeta documentation</a></li>
</ul>
]]></content:encoded></item><item><title>DynamoDB</title><link>https://tarrragon.github.io/blog/backend/01-database/vendors/dynamodb/</link><pubDate>Wed, 13 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/01-database/vendors/dynamodb/</guid><description>&lt;p>DynamoDB 是 AWS managed key-value store、用 partition-based scaling 提供 &lt;em>可預測 P99 latency&lt;/em> 跟 &lt;em>elastic capacity&lt;/em>。Amazon 自家 Ads（9000 萬 RPS）、Disney+、Zoom（COVID 30x surge）、Capcom（billions of requests / single-digit ms）都用 DynamoDB 撐核心 workload — 它是目前公開 case 最多、最被驗證的 managed KV 服務。&lt;/p>
&lt;h2 id="教學路線access-pattern-與-partition-capacity">教學路線：Access pattern 與 partition capacity&lt;/h2>
&lt;p>DynamoDB 服務頁的教學目標是把 access pattern 轉成 partition key、sort key、GSI、capacity mode 與 global tables 的設計判斷。讀者讀完後要能從查詢路徑反推資料模型，並估算 hot partition、成本與 consistency trade-off。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>學習段&lt;/th>
 &lt;th>核心問題&lt;/th>
 &lt;th>對應段落&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Access pattern&lt;/td>
 &lt;td>查詢形狀如何先於資料表設計&lt;/td>
 &lt;td>定位、適用場景&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Partition key&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/hot-partition/" data-link-title="Hot Partition" data-link-desc="說明分散式 KV / OLTP 中、單一 partition 流量遠超其他的容量問題">hot partition&lt;/a>、single-digit latency、GSI 如何成為設計核心&lt;/td>
 &lt;td>容量規劃要點、常見陷阱&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Capacity mode&lt;/td>
 &lt;td>on-demand、provisioned、auto scaling 如何對應高峰與成本&lt;/td>
 &lt;td>容量特性、案例對照&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Global tables&lt;/td>
 &lt;td>multi-region availability 與 consistency 會付出哪些代價&lt;/td>
 &lt;td>適用場景、跟其他 vendor 的取捨&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>替代路由&lt;/td>
 &lt;td>何時回 SQL、MongoDB、Cosmos DB 或 cache / queue&lt;/td>
 &lt;td>不適用場景、下一步路由&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="定位partition-based-kv-scale">定位：partition-based KV scale&lt;/h2>
&lt;p>DynamoDB 的核心設計是「partition 透明、capacity 抽象化」。不像 MongoDB 要主動 shard、不像 Cassandra 要管 ring topology、不像 PostgreSQL 要選 instance type — DynamoDB 把所有底層 scaling 隱藏在 RCU / WCU 抽象層後。&lt;/p>
&lt;p>&lt;strong>容量單位&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>1 RCU（Read Capacity Unit）= 1 strongly consistent read of 4KB / sec、2 eventually consistent reads&lt;/li>
&lt;li>1 WCU（Write Capacity Unit）= 1 write of 1KB / sec&lt;/li>
&lt;li>每個 partition 上限：3000 RCU / 1000 WCU&lt;/li>
&lt;li>總容量 = partition 數量 × 每 partition 上限（partition 數量透明、vendor 自動管理）&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>延遲特性&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>single-digit millisecond p99 latency（read / write）&lt;/li>
&lt;li>同 region 跨 AZ replication 內建、預設 eventually consistent reads&lt;/li>
&lt;li>strongly consistent reads 依 region 內 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/quorum/" data-link-title="Quorum" data-link-desc="分散式系統以多數節點同意作為提交或讀取有效性的門檻">quorum&lt;/a> 成立，跨 region 讀寫要看 Global Tables 語意&lt;/li>
&lt;/ul>
&lt;p>詳見 &lt;a href="https://tarrragon.github.io/blog/backend/01-database/kv-document-capacity-planning/" data-link-title="1.10 KV / Document DB 容量規劃" data-link-desc="DynamoDB / Cosmos DB / Bigtable / MongoDB 等 KV / Document DB 的容量設計、partition key 取捨、capacity mode 選擇">1.10 KV / Document DB 容量規劃&lt;/a> 跟 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/saturation-discovery/" data-link-title="9.4 Saturation Discovery" data-link-desc="找出 throughput plateau 與 latency knee 的方法">9.4 Saturation Discovery&lt;/a> 的 partition 設計章節。&lt;/p></description><content:encoded><![CDATA[<p>DynamoDB 是 AWS managed key-value store、用 partition-based scaling 提供 <em>可預測 P99 latency</em> 跟 <em>elastic capacity</em>。Amazon 自家 Ads（9000 萬 RPS）、Disney+、Zoom（COVID 30x surge）、Capcom（billions of requests / single-digit ms）都用 DynamoDB 撐核心 workload — 它是目前公開 case 最多、最被驗證的 managed KV 服務。</p>
<h2 id="教學路線access-pattern-與-partition-capacity">教學路線：Access pattern 與 partition capacity</h2>
<p>DynamoDB 服務頁的教學目標是把 access pattern 轉成 partition key、sort key、GSI、capacity mode 與 global tables 的設計判斷。讀者讀完後要能從查詢路徑反推資料模型，並估算 hot partition、成本與 consistency trade-off。</p>
<table>
  <thead>
      <tr>
          <th>學習段</th>
          <th>核心問題</th>
          <th>對應段落</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Access pattern</td>
          <td>查詢形狀如何先於資料表設計</td>
          <td>定位、適用場景</td>
      </tr>
      <tr>
          <td>Partition key</td>
          <td><a href="/blog/backend/knowledge-cards/hot-partition/" data-link-title="Hot Partition" data-link-desc="說明分散式 KV / OLTP 中、單一 partition 流量遠超其他的容量問題">hot partition</a>、single-digit latency、GSI 如何成為設計核心</td>
          <td>容量規劃要點、常見陷阱</td>
      </tr>
      <tr>
          <td>Capacity mode</td>
          <td>on-demand、provisioned、auto scaling 如何對應高峰與成本</td>
          <td>容量特性、案例對照</td>
      </tr>
      <tr>
          <td>Global tables</td>
          <td>multi-region availability 與 consistency 會付出哪些代價</td>
          <td>適用場景、跟其他 vendor 的取捨</td>
      </tr>
      <tr>
          <td>替代路由</td>
          <td>何時回 SQL、MongoDB、Cosmos DB 或 cache / queue</td>
          <td>不適用場景、下一步路由</td>
      </tr>
  </tbody>
</table>
<h2 id="定位partition-based-kv-scale">定位：partition-based KV scale</h2>
<p>DynamoDB 的核心設計是「partition 透明、capacity 抽象化」。不像 MongoDB 要主動 shard、不像 Cassandra 要管 ring topology、不像 PostgreSQL 要選 instance type — DynamoDB 把所有底層 scaling 隱藏在 RCU / WCU 抽象層後。</p>
<p><strong>容量單位</strong>：</p>
<ul>
<li>1 RCU（Read Capacity Unit）= 1 strongly consistent read of 4KB / sec、2 eventually consistent reads</li>
<li>1 WCU（Write Capacity Unit）= 1 write of 1KB / sec</li>
<li>每個 partition 上限：3000 RCU / 1000 WCU</li>
<li>總容量 = partition 數量 × 每 partition 上限（partition 數量透明、vendor 自動管理）</li>
</ul>
<p><strong>延遲特性</strong>：</p>
<ul>
<li>single-digit millisecond p99 latency（read / write）</li>
<li>同 region 跨 AZ replication 內建、預設 eventually consistent reads</li>
<li>strongly consistent reads 依 region 內 <a href="/blog/backend/knowledge-cards/quorum/" data-link-title="Quorum" data-link-desc="分散式系統以多數節點同意作為提交或讀取有效性的門檻">quorum</a> 成立，跨 region 讀寫要看 Global Tables 語意</li>
</ul>
<p>詳見 <a href="/blog/backend/01-database/kv-document-capacity-planning/" data-link-title="1.10 KV / Document DB 容量規劃" data-link-desc="DynamoDB / Cosmos DB / Bigtable / MongoDB 等 KV / Document DB 的容量設計、partition key 取捨、capacity mode 選擇">1.10 KV / Document DB 容量規劃</a> 跟 <a href="/blog/backend/09-performance-capacity/saturation-discovery/" data-link-title="9.4 Saturation Discovery" data-link-desc="找出 throughput plateau 與 latency knee 的方法">9.4 Saturation Discovery</a> 的 partition 設計章節。</p>
<h2 id="適用場景">適用場景</h2>
<p>按公開 case 提煉的典型適用場景：</p>
<p><strong>1. KV / single-table design 為主的查詢</strong>：</p>
<ul>
<li>用 partition key + sort key 設計、單筆 / 範圍查詢</li>
<li>查詢路徑固定，JOIN / ad-hoc query 需求低</li>
<li>對應案例：<a href="/blog/backend/09-performance-capacity/cases/amazon-ads-dynamodb-extreme-kv/" data-link-title="9.C5 Amazon Ads：DynamoDB 9000 萬 reads/sec 的廣告事件量測" data-link-desc="Amazon Ads 在 DynamoDB 上跑 9000 萬 reads/sec &#43; 500 萬 writes/sec、99.999% 可用性的廣告事件量測">9.C5 Amazon Ads</a> — 9000 萬 reads/sec + 500 萬 writes/sec、99.999% 可用</li>
</ul>
<p><strong>2. 可預測 sub-10ms p99 latency 需求</strong>：</p>
<ul>
<li>遊戲後端（玩家狀態、戰績）</li>
<li>內容平台 metadata（watchlist、播放進度）</li>
<li>對應案例：<a href="/blog/backend/09-performance-capacity/cases/capcom-gaming-dynamodb-eks/" data-link-title="9.C19 Capcom：Resident Evil / Monster Hunter 在 DynamoDB &#43; EKS 上的遊戲後端" data-link-desc="Capcom 把 Resident Evil、Street Fighter、Monster Hunter 遊戲後端跑在 DynamoDB &#43; EKS、單一秒位數延遲、營運成本降 30%">9.C19 Capcom</a>（billions of requests / single-digit ms）、<a href="/blog/backend/09-performance-capacity/cases/disney-plus-content-metadata/" data-link-title="9.C27 Disney&#43;：DynamoDB 撐每日數十億動作的觀看歷史" data-link-desc="Disney&#43; 用 DynamoDB 撐每日數十億動作的觀看歷史、watchlist、播放進度等串流 metadata">9.C27 Disney+</a>（每日數十億 actions）</li>
</ul>
<p><strong>3. 流量 spiky 或 surge 場景</strong>：</p>
<ul>
<li>on-demand capacity 自動吸收 burst</li>
<li>不需 connection pool（HTTP API、無 stateful connection）</li>
<li>對應案例：<a href="/blog/backend/09-performance-capacity/cases/zoom-covid-surge-dynamodb/" data-link-title="9.C18 Zoom：COVID 期間從 1000 萬到 3 億 DAU 的 30 倍突發" data-link-desc="Zoom 在 2020 年 COVID 爆發時、日活從 1000 萬衝到 3 億、用 DynamoDB 撐住會議後端">9.C18 Zoom</a>（COVID 1000 萬 → 3 億 DAU）、<a href="/blog/backend/09-performance-capacity/cases/tixcraft-ticketing-flash-sale-spike/" data-link-title="9.C15 拓元 Tixcraft：售票搶購的瞬間爆量架構" data-link-desc="拓元用 DynamoDB 當寫入緩衝 &#43; 傳統伺服器當慢速消費者、承受 100K&#43; 同時選位 &#43; 30 秒從 6 台擴到 800 台">9.C15 Tixcraft</a>（IOPS 20 → 135K、售票搶購）、<a href="/blog/backend/09-performance-capacity/cases/ntt-docomo-lemino-japanese-streaming/" data-link-title="9.C29 NTT DOCOMO Lemino：3 個月達 500 萬 MAU 的串流後端" data-link-desc="Lemino 用 DynamoDB &#43; AWS Media Services 撐 30 channels live &#43; 5M MAU、工程工時下降 90%">9.C29 Lemino</a>（RDB connection limit → 改 DynamoDB）</li>
</ul>
<p><strong>4. 大規模通知 / 訊息系統</strong>：</p>
<ul>
<li>TTL 自動清理過期 records</li>
<li>partition key 用 user_id / message_id 天然均勻</li>
<li>對應案例：<a href="/blog/backend/09-performance-capacity/cases/paypay-mobile-payment-messaging/" data-link-title="9.C26 PayPay：行動支付每日 3 億訊息的 DynamoDB 後端" data-link-desc="日本最大行動支付 PayPay 每日 3 億訊息、用 DynamoDB 處理通知與訊息功能、支撐次秒級反應">9.C26 PayPay</a>（行動支付每日 3 億訊息）</li>
</ul>
<p><strong>5. 5 個 9 可用性 B2B SaaS</strong>：</p>
<ul>
<li>multi-region Global Tables active-active</li>
<li>對應案例：<a href="/blog/backend/09-performance-capacity/cases/genesys-dynamodb-99999-availability/" data-link-title="9.C24 Genesys：用 DynamoDB 在 15 region 跑出 99.999% 可用性" data-link-desc="Genesys 客服平台用 DynamoDB 為預設資料層、跨 15 主 region &#43; 5 衛星 region、達成 12 個月 99.999% 可用性">9.C24 Genesys</a>（99.999% 跨 15 region）</li>
</ul>
<p><strong>6. 高吞吐 budget 敏感</strong>：</p>
<ul>
<li>on-demand 適合突發、provisioned 適合 sustained</li>
<li>對應案例：<a href="/blog/backend/09-performance-capacity/cases/zomato-tidb-to-dynamodb-migration/" data-link-title="9.C20 Zomato：從 TiDB 遷移到 DynamoDB、吞吐 4 倍、延遲降 90%、成本減 50%" data-link-desc="Zomato 帳單系統從 TiDB 遷移到 DynamoDB、吞吐 2K→8K RPM、延遲降 90%、成本減 50%">9.C20 Zomato</a> — TiDB over-provision 壓力轉成 DynamoDB on-demand pay-per-use，成本下降 50%</li>
</ul>
<h2 id="不適用場景">不適用場景</h2>
<p><strong>1. 複雜 ad-hoc query / JOIN</strong>：</p>
<ul>
<li>DynamoDB query 以 partition key + sort key 為主，JOIN-heavy workload 交給 SQL 系統</li>
<li>PartiQL 提供 SQL-like 語法但底層還是 KV、複雜 query 會 scan 全表</li>
<li>替代：用 Aurora / PostgreSQL / Spanner</li>
</ul>
<p><strong>2. 強一致 multi-row transaction</strong>：</p>
<ul>
<li>DynamoDB Transaction 支援 25 個 item 的 ACID</li>
<li>超過 25 個 item 或跨 region 的 transaction 要改用 workflow / SQL / distributed SQL 設計</li>
<li>替代：Spanner / Aurora DSQL / CockroachDB</li>
</ul>
<p><strong>3. 跨雲需求</strong>：</p>
<ul>
<li>DynamoDB only on AWS、vendor lock-in</li>
<li>替代：Cosmos DB（Azure global NoSQL）、自管 ScyllaDB</li>
</ul>
<p><strong>4. 大物件 / 文件儲存</strong>：</p>
<ul>
<li>單一 item 最大 400KB</li>
<li>大物件用 S3、metadata 用 DynamoDB</li>
</ul>
<p><strong>5. 預算極度敏感 + 流量穩定</strong>：</p>
<ul>
<li>流量高度 predictable 的 sustained workload，自管 PostgreSQL / MySQL 可能更便宜</li>
<li>DynamoDB 的 managed 跟 elastic 是有溢價的</li>
</ul>
<h2 id="跟其他-vendor-的取捨">跟其他 vendor 的取捨</h2>
<p><strong>vs MongoDB（自管或 Atlas）</strong>：</p>
<ul>
<li>DynamoDB：managed、partition 透明、application 主要管理 partition key，有 5 個 9 SLA</li>
<li>MongoDB：彈性高、可自管、aggregation pipeline 強、跨雲可用</li>
<li>選 DynamoDB：AWS-only、想轉移 operation、partition 設計簡單可預測</li>
<li>選 MongoDB：跨雲、複雜 query、ad-hoc analysis</li>
</ul>
<p><strong>vs Aurora（同 AWS）</strong>：</p>
<ul>
<li>DynamoDB：KV、partition 擴展、無 connection pool 限制</li>
<li>Aurora：SQL（PostgreSQL / MySQL）、有 transaction、ad-hoc query</li>
<li>詳見 <a href="/blog/backend/01-database/kv-document-capacity-planning/" data-link-title="1.10 KV / Document DB 容量規劃" data-link-desc="DynamoDB / Cosmos DB / Bigtable / MongoDB 等 KV / Document DB 的容量設計、partition key 取捨、capacity mode 選擇">1.10 KV / Document DB 容量規劃</a> 跟 <a href="/blog/backend/09-performance-capacity/cases/ntt-docomo-lemino-japanese-streaming/" data-link-title="9.C29 NTT DOCOMO Lemino：3 個月達 500 萬 MAU 的串流後端" data-link-desc="Lemino 用 DynamoDB &#43; AWS Media Services 撐 30 channels live &#43; 5M MAU、工程工時下降 90%">9.C29 Lemino case</a> — connection limit 是 RDB vs DynamoDB 的關鍵差異</li>
</ul>
<p><strong>vs Redis（含 ElastiCache）作為 KV 替代</strong>：</p>
<ul>
<li>DynamoDB：持久化、單 item 持久查得到、有 TTL 但物件不會自動失蹤</li>
<li>Redis：純記憶體、預設不持久（MemoryDB 例外）、快但易失</li>
<li>選 DynamoDB：data 是 <a href="/blog/backend/knowledge-cards/source-of-truth/" data-link-title="Source of Truth" data-link-desc="說明正式資料來源如何決定資料判斷、修復與一致性責任">source of truth</a>，需要持久保存</li>
<li>選 Redis：data 是 cache、丟了能 recompute</li>
</ul>
<p><strong>vs Cosmos DB（cross-cloud）</strong>：</p>
<ul>
<li>DynamoDB：AWS-only、KV 為主、無 multi-model</li>
<li>Cosmos DB：Azure-only、multi-model（SQL / Mongo / Cassandra / Gremlin / Table）、5 個 <a href="/blog/backend/knowledge-cards/consistency-level/" data-link-title="Consistency Level" data-link-desc="資料系統對讀寫一致性語意的可選擇層級">consistency level</a>s</li>
<li>選 DynamoDB：AWS 生態、KV 純粹</li>
<li>選 Cosmos DB：Azure 生態、需要 multi-model、需要 multi-region active-active write</li>
</ul>
<p><strong>vs Cassandra / ScyllaDB（self-managed）</strong>：</p>
<ul>
<li>DynamoDB：managed、5 個 9 SLA、無 ops 負擔</li>
<li>Cassandra / ScyllaDB：可自管、更深 tuning、跨雲可用</li>
<li>選 DynamoDB：團隊想把 DBA / SRE 操作責任交給 AWS</li>
<li>選 Cassandra / ScyllaDB：有 DBA、想 lock-in 風險低、需要極限 throughput tuning</li>
</ul>
<p><strong>vs PostgreSQL（SQL baseline）</strong>：</p>
<ul>
<li>詳見 <a href="/blog/backend/01-database/vendors/postgresql/" data-link-title="PostgreSQL" data-link-desc="多用途 OLTP 主流關聯式資料庫、MVCC、豐富 SQL 特性、是 Aurora / Cosmos DB / Spanner / CockroachDB / Aurora DSQL 的相容目標">PostgreSQL vendor page</a> 取捨段、跟 <a href="/blog/backend/01-database/kv-document-capacity-planning/" data-link-title="1.10 KV / Document DB 容量規劃" data-link-desc="DynamoDB / Cosmos DB / Bigtable / MongoDB 等 KV / Document DB 的容量設計、partition key 取捨、capacity mode 選擇">1.10 KV / Document DB 容量規劃</a> 的 connection model 對比</li>
<li>摘要：DynamoDB 是 <em>access pattern 固定 + 需要避免 connection-bound</em> 的選項；ad-hoc query / 複雜 transaction 留 PostgreSQL</li>
</ul>
<h2 id="容量規劃要點">容量規劃要點</h2>
<p>從 09 案例庫提煉的 DynamoDB 容量規劃實踐：</p>
<p><strong>1. partition key 設計是命脈</strong>：</p>
<ul>
<li>partition key 不均 → hot partition → 名義容量達不到</li>
<li>composite key（event_id + user_id_hash）強制分散</li>
<li>對應 <a href="/blog/backend/09-performance-capacity/cases/amazon-ads-dynamodb-extreme-kv/" data-link-title="9.C5 Amazon Ads：DynamoDB 9000 萬 reads/sec 的廣告事件量測" data-link-desc="Amazon Ads 在 DynamoDB 上跑 9000 萬 reads/sec &#43; 500 萬 writes/sec、99.999% 可用性的廣告事件量測">9.C5 Amazon Ads</a> 9000 萬 RPS 靠 partition 均勻、<a href="/blog/backend/09-performance-capacity/cases/tixcraft-ticketing-flash-sale-spike/" data-link-title="9.C15 拓元 Tixcraft：售票搶購的瞬間爆量架構" data-link-desc="拓元用 DynamoDB 當寫入緩衝 &#43; 傳統伺服器當慢速消費者、承受 100K&#43; 同時選位 &#43; 30 秒從 6 台擴到 800 台">9.C15 Tixcraft</a> 用 composite key 分散售票流量</li>
<li>詳見 <a href="/blog/backend/knowledge-cards/hot-partition/" data-link-title="Hot Partition" data-link-desc="說明分散式 KV / OLTP 中、單一 partition 流量遠超其他的容量問題">Hot Partition 卡片</a></li>
</ul>
<p><strong>2. on-demand vs provisioned 選型</strong>：</p>
<ul>
<li>流量 peak/avg &gt; 5x → on-demand</li>
<li>sustained predictable → provisioned + auto-scaling</li>
<li>知名大事件（Black Friday）→ provisioned baseline + scheduled scale-up</li>
<li>對應 <a href="/blog/backend/09-performance-capacity/cases/zomato-tidb-to-dynamodb-migration/" data-link-title="9.C20 Zomato：從 TiDB 遷移到 DynamoDB、吞吐 4 倍、延遲降 90%、成本減 50%" data-link-desc="Zomato 帳單系統從 TiDB 遷移到 DynamoDB、吞吐 2K→8K RPM、延遲降 90%、成本減 50%">9.C20 Zomato</a> — on-demand 解放 over-provisioning</li>
</ul>
<p><strong>3. Global Tables（multi-region active-active）</strong>：</p>
<ul>
<li>每個 region 都能寫、conflict resolution 用 LWW</li>
<li>容量在每個 region 獨立配置，全球總和要按 region 分別估算</li>
<li>對應 <a href="/blog/backend/09-performance-capacity/cases/genesys-dynamodb-99999-availability/" data-link-title="9.C24 Genesys：用 DynamoDB 在 15 region 跑出 99.999% 可用性" data-link-desc="Genesys 客服平台用 DynamoDB 為預設資料層、跨 15 主 region &#43; 5 衛星 region、達成 12 個月 99.999% 可用性">9.C24 Genesys</a> — 15 region 達 5 個 9 可用</li>
</ul>
<p><strong>4. DAX（DynamoDB Accelerator）</strong>：</p>
<ul>
<li>DynamoDB 前置 in-memory cache</li>
<li>從 single-digit ms 降到 microsecond</li>
<li>適合超高 read 重複的 workload（同樣 key 大量讀）</li>
<li>對應 <a href="/blog/backend/09-performance-capacity/cases/ntt-docomo-lemino-japanese-streaming/" data-link-title="9.C29 NTT DOCOMO Lemino：3 個月達 500 萬 MAU 的串流後端" data-link-desc="Lemino 用 DynamoDB &#43; AWS Media Services 撐 30 channels live &#43; 5M MAU、工程工時下降 90%">9.C29 Lemino</a> 用 DAX 加速</li>
</ul>
<p><strong>5. Streams + Lambda</strong>：</p>
<ul>
<li>DynamoDB 寫入 → Stream event → Lambda 處理</li>
<li>適合 CDC、event-driven 工作流</li>
<li>對應 <a href="/blog/backend/09-performance-capacity/cases/tixcraft-ticketing-flash-sale-spike/" data-link-title="9.C15 拓元 Tixcraft：售票搶購的瞬間爆量架構" data-link-desc="拓元用 DynamoDB 當寫入緩衝 &#43; 傳統伺服器當慢速消費者、承受 100K&#43; 同時選位 &#43; 30 秒從 6 台擴到 800 台">9.C15 Tixcraft</a> 用 Stream 把 DynamoDB 當 durable queue 給 legacy server 消費</li>
</ul>
<h2 id="anti-recommendation-與升級路由">Anti-recommendation 與升級路由</h2>
<p>DynamoDB 的 managed elasticity 會讓團隊忽略 access pattern 的前置成本。這一段先說何時維持單純 table / index，再說何時升級到 Global Tables、DAX、Streams、或改回 SQL / document DB。</p>
<table>
  <thead>
      <tr>
          <th>機制 / 路線</th>
          <th>維持簡單設計的條件</th>
          <th>升級訊號</th>
          <th>主要引用路徑</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>單 table / 少量 GSI</td>
          <td>access pattern 穩定、partition key 均勻、query 成本可預測</td>
          <td>新查詢路徑大量增加、GSI 成本壓過主表、hot partition 出現</td>
          <td><a href="/blog/backend/knowledge-cards/hot-partition/" data-link-title="Hot Partition" data-link-desc="說明分散式 KV / OLTP 中、單一 partition 流量遠超其他的容量問題">Hot Partition</a>、<a href="/blog/backend/knowledge-cards/workload-model/" data-link-title="Workload Model" data-link-desc="描述 production traffic 形狀的可重播模型 — 容量規劃跟壓測的共同輸入">Workload Model</a></td>
      </tr>
      <tr>
          <td>On-demand capacity</td>
          <td>peak/avg 差距大、流量有事件性 surge</td>
          <td>sustained traffic 穩定、成本曲線可預測</td>
          <td><a href="/blog/backend/knowledge-cards/peak-forecast/" data-link-title="Peak Forecast" data-link-desc="說明預期峰值流量的預測方法 — 容量規劃的第一個輸入">Peak Forecast</a>、<a href="/blog/backend/knowledge-cards/cost-per-request/" data-link-title="Cost Per Request" data-link-desc="把雲端成本拆到單一 API 請求的 unit economics 模型">Cost Per Request</a></td>
      </tr>
      <tr>
          <td>Provisioned + autoscaling</td>
          <td>baseline 穩定、團隊能預測高峰</td>
          <td>黑五、售票、直播等已知大事件需要預先升配</td>
          <td><a href="/blog/backend/knowledge-cards/scheduled-scaling/" data-link-title="Scheduled Scaling" data-link-desc="說明按已知時間表預先擴容的 autoscaler 模式">Scheduled Scaling</a></td>
      </tr>
      <tr>
          <td>DAX</td>
          <td>read 重複率低、single-digit ms 已足夠</td>
          <td>同 key 超高讀取、需要 microsecond read</td>
          <td><a href="/blog/backend/knowledge-cards/cache-aside/" data-link-title="Cache Aside" data-link-desc="說明 application 如何在讀取時自行管理快取與正式資料來源">Cache Aside</a>、<a href="/blog/backend/knowledge-cards/stale-data/" data-link-title="Stale Data" data-link-desc="說明過期資料在快取、replica 與衍生資料中的產品影響">Stale Data</a></td>
      </tr>
      <tr>
          <td>Global Tables</td>
          <td>single-region availability 已足夠</td>
          <td>RTO/RPO、region residency 或 active-active write 是產品需求</td>
          <td><a href="/blog/backend/knowledge-cards/rto/" data-link-title="RTO" data-link-desc="說明恢復時間目標如何約束事故回復策略">RTO</a>、<a href="/blog/backend/knowledge-cards/rpo/" data-link-title="RPO" data-link-desc="說明恢復點目標如何定義可接受資料損失範圍">RPO</a>、<a href="/blog/backend/knowledge-cards/consistency-level/" data-link-title="Consistency Level" data-link-desc="資料系統對讀寫一致性語意的可選擇層級">Consistency Level</a></td>
      </tr>
      <tr>
          <td>SQL / document DB</td>
          <td>access pattern 可提前列舉</td>
          <td>ad-hoc query、JOIN、multi-row transaction 或 document traversal 成主題</td>
          <td><a href="/blog/backend/01-database/vendors/aurora/" data-link-title="AWS Aurora" data-link-desc="AWS managed PostgreSQL / MySQL、storage / compute 分離、&#43;75% 效能改善的 production 證據">Aurora vendor</a>、<a href="/blog/backend/01-database/vendors/mongodb/" data-link-title="MongoDB" data-link-desc="Document database 代表、Atlas managed、跨雲可用、許多大規模平台從 MongoDB 起家">MongoDB vendor</a></td>
      </tr>
  </tbody>
</table>
<p>DynamoDB 的簡單路徑是先把每個 query path 寫成契約。table、partition key、sort key、GSI 與 TTL 都應從 access pattern 反推；如果需求仍在探索期，PostgreSQL 或 MongoDB 可能提供更低的變更成本。</p>
<p>Global Tables 的升級路徑要先處理 conflict 與讀寫語意。它提供 multi-region availability，但 LWW conflict resolution、region-local capacity 與跨 region reconciliation 仍要由 application contract 承擔。</p>
<h2 id="deep-article已完成">Deep article（已完成）</h2>
<p>本 vendor 現有 deep article 覆蓋 DynamoDB 從 access pattern 反推到寫一致性、讀加速、事件驅動與資料生命週期的核心 production 議題：</p>
<table>
  <thead>
      <tr>
          <th>主題</th>
          <th>文章</th>
          <th>對應 production 議題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>適用度 4 軸前置判讀 + access pattern 反推 PK/SK + durable queue</td>
          <td><a href="single-table-design-pattern/">single-table-design-pattern</a></td>
          <td>適用度判讀 + control plane vs data plane + 9.C15 Tixcraft Stream durable queue</td>
      </tr>
      <tr>
          <td>1000 WCU partition 上限 + composite key / calculated shard 修法</td>
          <td><a href="partition-key-antipatterns/">partition-key-antipatterns</a></td>
          <td>9.C15 Tixcraft 6750x 擴展、mode × partition 在 provisioned / on-demand 表現</td>
      </tr>
      <tr>
          <td>GSI / LSI projection 三型、sparse、DAX 補位</td>
          <td><a href="gsi-lsi-design/">gsi-lsi-design</a></td>
          <td>GSI 自己會 hot partition、Capcom derive vs Lemino case fact 分層</td>
      </tr>
      <tr>
          <td>6 軸 capacity mode 決策 + auto-scaling 邊界 + cost crossover</td>
          <td><a href="on-demand-vs-provisioned/">on-demand-vs-provisioned</a></td>
          <td>Zomato 50% 成本下降、Zoom 30x permanent surge、Amazon Ads sustained workload</td>
      </tr>
      <tr>
          <td>Multi-region active-active + LWW conflict + cross-device sync</td>
          <td><a href="global-tables-conflict/">global-tables-conflict</a></td>
          <td>Genesys 99.999% / 15 region、Disney+ 跨裝置同步</td>
      </tr>
      <tr>
          <td>Strongly / eventually consistent read 取捨</td>
          <td><a href="consistency-model-optimization/">consistency-model-optimization</a></td>
          <td>read consistency 成本選擇</td>
      </tr>
      <tr>
          <td>跨 item 原子性 + conditional write + optimistic lock + idempotency</td>
          <td><a href="transactions-conditional-writes/">transactions-conditional-writes</a></td>
          <td>雙寫不一致、超賣 race、transaction 2x 成本邊界</td>
      </tr>
      <tr>
          <td>DAX cluster + item/query cache + write-through + invalidation 邊界</td>
          <td><a href="dax-caching-strategy/">dax-caching-strategy</a></td>
          <td>讀峰值 p99 尖刺、query cache 只靠 TTL 失效、strong read 繞過 cache</td>
      </tr>
      <tr>
          <td>Streams CDC + shard 順序 + Lambda 消費 + 失敗處理</td>
          <td><a href="streams-lambda-event-driven/">streams-lambda-event-driven</a></td>
          <td>下游即時反應、at-least-once 冪等、毒丸 record 隔離</td>
      </tr>
      <tr>
          <td>TTL 自動過期 + 48h 刪除延遲 + 過期仍可讀 + storage 成本</td>
          <td><a href="ttl-data-lifecycle/">ttl-data-lifecycle</a></td>
          <td>9.C26 PayPay 每日上億訊息 storage 清理、過期未刪 item 讀取陷阱</td>
      </tr>
  </tbody>
</table>
<p>Migration playbook：<a href="migrate-rds-mongodb-to-dynamodb/">從 RDS / MongoDB 遷移到 DynamoDB</a>（Type E paradigm shift、access-pattern-first 重建模 + 混合架構 + Zomato cost crossover）。</p>
<p>跨 vendor entry：先看 <a href="../db3-vendor-selection/">DB3 vendor selection</a>（MongoDB / DynamoDB / Cosmos DB 三方選型 + workload shape 前置判讀），再進本 vendor 的 deep article。</p>
<h2 id="後續擴充仍待補">後續擴充（仍待補）</h2>
<ul>
<li>DynamoDB Streams 進階 lab：Kinesis Data Streams for DynamoDB 多消費者 fan-out 與長 retention 重播（Lambda vs Kinesis 比較層已在 <a href="streams-lambda-event-driven/">streams-lambda-event-driven</a> 覆蓋、此處指可操作的深度 hands-on lab）</li>
<li>Export to S3 / point-in-time export 做離線分析</li>
<li>DynamoDB → SQL / search / analytics split（遷出方向 playbook）</li>
<li>Backup / PITR restore drill（hands-on lab）</li>
</ul>
<h2 id="案例對照">案例對照</h2>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>規模</th>
          <th>教學重點</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/cases/amazon-ads-dynamodb-extreme-kv/" data-link-title="9.C5 Amazon Ads：DynamoDB 9000 萬 reads/sec 的廣告事件量測" data-link-desc="Amazon Ads 在 DynamoDB 上跑 9000 萬 reads/sec &#43; 500 萬 writes/sec、99.999% 可用性的廣告事件量測">9.C5 Amazon Ads</a></td>
          <td>9000 萬 RPS + 500 萬 WPS</td>
          <td>partition 均勻設計典範</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/cases/tixcraft-ticketing-flash-sale-spike/" data-link-title="9.C15 拓元 Tixcraft：售票搶購的瞬間爆量架構" data-link-desc="拓元用 DynamoDB 當寫入緩衝 &#43; 傳統伺服器當慢速消費者、承受 100K&#43; 同時選位 &#43; 30 秒從 6 台擴到 800 台">9.C15 Tixcraft</a></td>
          <td>IOPS 20 → 135K（6750x 擴展）</td>
          <td>flash-sale 緩衝模式</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/cases/zoom-covid-surge-dynamodb/" data-link-title="9.C18 Zoom：COVID 期間從 1000 萬到 3 億 DAU 的 30 倍突發" data-link-desc="Zoom 在 2020 年 COVID 爆發時、日活從 1000 萬衝到 3 億、用 DynamoDB 撐住會議後端">9.C18 Zoom</a></td>
          <td>30x DAU surge（1000 萬 → 3 億）</td>
          <td>SaaS surge baseline 重新校準</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/cases/capcom-gaming-dynamodb-eks/" data-link-title="9.C19 Capcom：Resident Evil / Monster Hunter 在 DynamoDB &#43; EKS 上的遊戲後端" data-link-desc="Capcom 把 Resident Evil、Street Fighter、Monster Hunter 遊戲後端跑在 DynamoDB &#43; EKS、單一秒位數延遲、營運成本降 30%">9.C19 Capcom</a></td>
          <td>billions of requests / single-digit ms</td>
          <td>遊戲後端 KV、跨遊戲共用平台</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/cases/zomato-tidb-to-dynamodb-migration/" data-link-title="9.C20 Zomato：從 TiDB 遷移到 DynamoDB、吞吐 4 倍、延遲降 90%、成本減 50%" data-link-desc="Zomato 帳單系統從 TiDB 遷移到 DynamoDB、吞吐 2K→8K RPM、延遲降 90%、成本減 50%">9.C20 Zomato</a></td>
          <td>4x 吞吐、90% latency 降、50% 成本降</td>
          <td>TiDB → DynamoDB cross-DB 遷移</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/cases/genesys-dynamodb-99999-availability/" data-link-title="9.C24 Genesys：用 DynamoDB 在 15 region 跑出 99.999% 可用性" data-link-desc="Genesys 客服平台用 DynamoDB 為預設資料層、跨 15 主 region &#43; 5 衛星 region、達成 12 個月 99.999% 可用性">9.C24 Genesys</a></td>
          <td>99.999% / 15 region / 8000+ orgs</td>
          <td>B2B SaaS 5 個 9 可用性</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/cases/paypay-mobile-payment-messaging/" data-link-title="9.C26 PayPay：行動支付每日 3 億訊息的 DynamoDB 後端" data-link-desc="日本最大行動支付 PayPay 每日 3 億訊息、用 DynamoDB 處理通知與訊息功能、支撐次秒級反應">9.C26 PayPay</a></td>
          <td>3 億 訊息 / 天</td>
          <td>行動支付通知系統、TTL 自動清理</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/cases/disney-plus-content-metadata/" data-link-title="9.C27 Disney&#43;：DynamoDB 撐每日數十億動作的觀看歷史" data-link-desc="Disney&#43; 用 DynamoDB 撐每日數十億動作的觀看歷史、watchlist、播放進度等串流 metadata">9.C27 Disney+</a></td>
          <td>每日數十億 actions</td>
          <td>串流 metadata 層 + cross-device 同步</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/cases/ntt-docomo-lemino-japanese-streaming/" data-link-title="9.C29 NTT DOCOMO Lemino：3 個月達 500 萬 MAU 的串流後端" data-link-desc="Lemino 用 DynamoDB &#43; AWS Media Services 撐 30 channels live &#43; 5M MAU、工程工時下降 90%">9.C29 Lemino</a></td>
          <td>tens of thousands req/sec、5M MAU / 3 月</td>
          <td>RDB connection limit → DynamoDB</td>
      </tr>
  </tbody>
</table>
<p>DynamoDB case 的讀法是先分類 access pattern，再看容量模式。Amazon Ads / Capcom / Disney+ 說明高吞吐 KV，Zoom / Tixcraft / Lemino 說明 surge 與 connection-free scaling，Zomato 則說明 on-demand cost model 如何改變 over-provision 壓力。</p>
<h2 id="反向-sibling-路由">反向 sibling 路由</h2>
<p>DynamoDB 的反向 sibling 路由用來把 RDBMS 退場條件寫清楚。若讀者從 PostgreSQL / MySQL 的 connection bottleneck 過來，先讀 <a href="/blog/backend/09-performance-capacity/cases/ntt-docomo-lemino-japanese-streaming/" data-link-title="9.C29 NTT DOCOMO Lemino：3 個月達 500 萬 MAU 的串流後端" data-link-desc="Lemino 用 DynamoDB &#43; AWS Media Services 撐 30 channels live &#43; 5M MAU、工程工時下降 90%">Lemino case</a> 與 <a href="/blog/backend/01-database/kv-document-capacity-planning/" data-link-title="1.10 KV / Document DB 容量規劃" data-link-desc="DynamoDB / Cosmos DB / Bigtable / MongoDB 等 KV / Document DB 的容量設計、partition key 取捨、capacity mode 選擇">1.10 KV / Document DB 容量規劃</a>；若需求仍需要 ad hoc SQL、join 與 transaction report，回 <a href="/blog/backend/01-database/vendors/aurora/" data-link-title="AWS Aurora" data-link-desc="AWS managed PostgreSQL / MySQL、storage / compute 分離、&#43;75% 效能改善的 production 證據">Aurora vendor</a> 或 <a href="/blog/backend/01-database/vendors/postgresql/" data-link-title="PostgreSQL" data-link-desc="多用途 OLTP 主流關聯式資料庫、MVCC、豐富 SQL 特性、是 Aurora / Cosmos DB / Spanner / CockroachDB / Aurora DSQL 的相容目標">PostgreSQL vendor</a>；若需求是 global document model 與 Azure 生態，再對照 <a href="/blog/backend/01-database/vendors/cosmosdb/" data-link-title="Azure Cosmos DB" data-link-desc="全球分散式 multi-model DB、5 個 consistency levels、Microsoft 自家 dogfood 證據">Cosmos DB vendor</a>。</p>
<p>這條路由的判準是 access pattern 是否穩定到可以先設計 key。DynamoDB 擅長固定 lookup、寫入尖峰、connection-free scaling 與 TTL 類生命週期；資料探索、報表 join 與多條件查詢仍應留在 SQL / search / analytics service。</p>
<h2 id="常見陷阱">常見陷阱</h2>
<p>從公開 incident 跟 case 提煉：</p>
<ul>
<li><strong>partition key 集中</strong>：event_id 一個演唱會、bot user 大量同 user_id 寫入 → 用 composite key 或 write sharding</li>
<li><strong>單一 partition 達 3000 RCU / 1000 WCU 上限</strong>：throttling event 出現、即使整體 capacity 還沒滿</li>
<li><strong>Scan 全表</strong>：scan 會吃光 capacity，正式讀取路徑應回到 query / index design</li>
<li><strong>DAX 跟 DynamoDB 直連混用</strong>：寫入直連 DynamoDB、讀經過 DAX → cache 一致性問題</li>
<li><strong>Global Tables conflict</strong>：跨 region 同 key 同時被寫、LWW 可能丟失寫入、要設計 idempotency</li>
</ul>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>完整 T1 對照：<a href="/blog/backend/01-database/vendors/" data-link-title="資料庫 Vendor 清單" data-link-desc="規劃 SQL、managed SQL、document、KV 與 distributed SQL 的服務頁撰寫順序與教學大綱">01-database vendors index</a></li>
<li>平行：<a href="/blog/backend/01-database/vendors/aurora/" data-link-title="AWS Aurora" data-link-desc="AWS managed PostgreSQL / MySQL、storage / compute 分離、&#43;75% 效能改善的 production 證據">Aurora vendor page</a>（SQL 對比）</li>
<li>上游：<a href="/blog/backend/01-database/kv-document-capacity-planning/" data-link-title="1.10 KV / Document DB 容量規劃" data-link-desc="DynamoDB / Cosmos DB / Bigtable / MongoDB 等 KV / Document DB 的容量設計、partition key 取捨、capacity mode 選擇">1.10 KV / Document DB 容量規劃</a></li>
<li>下游：<a href="/blog/backend/01-database/large-scale-db-migration/" data-link-title="1.12 大規模 DB 遷移實戰" data-link-desc="跨 DB 遷移的 dual-write、[shadow read](/backend/knowledge-cards/shadow-read/)、cutover、rollback 流程 — 從實戰案例提煉的工程做法">1.12 大規模 DB 遷移實戰</a>（從 RDBMS 遷 DynamoDB 案例）</li>
<li>跨模組：<a href="/blog/backend/09-performance-capacity/saturation-discovery/" data-link-title="9.4 Saturation Discovery" data-link-desc="找出 throughput plateau 與 latency knee 的方法">9.4 Saturation Discovery</a>、<a href="/blog/backend/09-performance-capacity/capacity-planning/" data-link-title="9.6 容量規劃模型" data-link-desc="peak forecast、headroom budget、growth curve、autoscaling sizing">9.6 容量規劃模型</a></li>
<li>Last reviewed：2026-05-22（capacity mode / Global Tables / best practices 屬時間敏感 claim）</li>
<li>官方：<a href="https://aws.amazon.com/dynamodb/customers/">Amazon DynamoDB Customers</a>、<a href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/best-practices.html">DynamoDB 設計 best practices</a></li>
</ul>
]]></content:encoded></item><item><title>Apache JMeter</title><link>https://tarrragon.github.io/blog/backend/06-reliability/vendors/jmeter/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/06-reliability/vendors/jmeter/</guid><description>&lt;p>JMeter 是 Apache 出品的老牌 load test 工具、承擔三個責任：GUI-driven test plan 設計、多 protocol sampler（HTTP / JDBC / JMS / FTP / mail）、plugins 生態廣 + 企業環境普及。設計取捨偏向「GUI 易上手 + 既有測試資產治理 + 多 protocol」、跟 code-first（k6 / Gatling）的取捨在 dev workflow 跟 version control 友善度。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>用 GUI 設計 test plan（thread group / sampler / listener / assertion）&lt;/li>
&lt;li>跑 non-GUI mode 給 CI&lt;/li>
&lt;li>用 Distributed mode（master / slave）擴張 VU&lt;/li>
&lt;li>用 JMeter Plugins Manager 加擴展&lt;/li>
&lt;li>評估 JMeter vs 現代 CLI-first（k6 / Gatling / Locust）的選用&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑5-分鐘把-jmeter-跑起來">最短路徑：5 分鐘把 JMeter 跑起來&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 1. 安裝&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: brew install jmeter / 下載 zip&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="c1"># 2. GUI 設計 .jmx&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: 開 jmeter GUI、加 Thread Group / HTTP Sampler / Listener&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">&lt;span class="c1"># 3. CI 跑 non-GUI mode&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: jmeter -n -t test.jmx -l result.jtl -e -o report/&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="日常操作與決策形狀">日常操作與決策形狀&lt;/h2>
&lt;h3 id="test-plan-結構">Test plan 結構&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>Thread Group（VU + ramp-up + loop count）&lt;/li>
&lt;li>Sampler（HTTP / JDBC / JMS / FTP / Java Request）&lt;/li>
&lt;li>Listener（aggregate report / view tree / graph）&lt;/li>
&lt;li>Assertion（response / duration / size）&lt;/li>
&lt;/ul>
&lt;h3 id="non-gui-mode-for-ci">Non-GUI mode for CI&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>&lt;code>-n&lt;/code> non-GUI&lt;/li>
&lt;li>&lt;code>-t&lt;/code> test file / &lt;code>-l&lt;/code> log file&lt;/li>
&lt;li>&lt;code>-e -o&lt;/code> 產生 HTML dashboard&lt;/li>
&lt;li>Exit code 0 / 1（搭配 backend listener / assertion）&lt;/li>
&lt;/ul>
&lt;h3 id="distributed-testing">Distributed testing&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>Master / slave 配置&lt;/li>
&lt;li>RMI port 設定&lt;/li>
&lt;li>Result aggregation 在 master&lt;/li>
&lt;/ul>
&lt;h2 id="進階主題按需閱讀">進階主題（按需閱讀）&lt;/h2>
&lt;h3 id="plugins-manager">Plugins Manager&lt;/h3>
&lt;p>子議題：&lt;/p></description><content:encoded><![CDATA[<p>JMeter 是 Apache 出品的老牌 load test 工具、承擔三個責任：GUI-driven test plan 設計、多 protocol sampler（HTTP / JDBC / JMS / FTP / mail）、plugins 生態廣 + 企業環境普及。設計取捨偏向「GUI 易上手 + 既有測試資產治理 + 多 protocol」、跟 code-first（k6 / Gatling）的取捨在 dev workflow 跟 version control 友善度。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>用 GUI 設計 test plan（thread group / sampler / listener / assertion）</li>
<li>跑 non-GUI mode 給 CI</li>
<li>用 Distributed mode（master / slave）擴張 VU</li>
<li>用 JMeter Plugins Manager 加擴展</li>
<li>評估 JMeter vs 現代 CLI-first（k6 / Gatling / Locust）的選用</li>
</ol>
<h2 id="最短路徑5-分鐘把-jmeter-跑起來">最短路徑：5 分鐘把 JMeter 跑起來</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 1. 安裝</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># TODO: brew install jmeter / 下載 zip</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 2. GUI 設計 .jmx</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="c1"># TODO: 開 jmeter GUI、加 Thread Group / HTTP Sampler / Listener</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="c1"># 3. CI 跑 non-GUI mode</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="c1"># TODO: jmeter -n -t test.jmx -l result.jtl -e -o report/</span></span></span></code></pre></div><h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="test-plan-結構">Test plan 結構</h3>
<p>子議題：</p>
<ul>
<li>Thread Group（VU + ramp-up + loop count）</li>
<li>Sampler（HTTP / JDBC / JMS / FTP / Java Request）</li>
<li>Listener（aggregate report / view tree / graph）</li>
<li>Assertion（response / duration / size）</li>
</ul>
<h3 id="non-gui-mode-for-ci">Non-GUI mode for CI</h3>
<p>子議題：</p>
<ul>
<li><code>-n</code> non-GUI</li>
<li><code>-t</code> test file / <code>-l</code> log file</li>
<li><code>-e -o</code> 產生 HTML dashboard</li>
<li>Exit code 0 / 1（搭配 backend listener / assertion）</li>
</ul>
<h3 id="distributed-testing">Distributed testing</h3>
<p>子議題：</p>
<ul>
<li>Master / slave 配置</li>
<li>RMI port 設定</li>
<li>Result aggregation 在 master</li>
</ul>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<h3 id="plugins-manager">Plugins Manager</h3>
<p>子議題：</p>
<ul>
<li>jmeter-plugins.org plugins</li>
<li>常用：PerfMon / Dummy Sampler / Custom Thread Groups / WebSocket</li>
<li>安裝管理：Plugins Manager 安裝後可 UI 管</li>
</ul>
<h3 id="recording-controller">Recording controller</h3>
<p>子議題：</p>
<ul>
<li>HTTP(S) Test Script Recorder</li>
<li>Browser proxy 設定</li>
<li>適合：快速錄製 user flow</li>
</ul>
<h3 id="csv-data-set--parameterization">CSV data set / parameterization</h3>
<p>子議題：</p>
<ul>
<li>CSV Data Set Config</li>
<li>各 thread 取不同資料</li>
<li>適合 data-driven test</li>
</ul>
<h3 id="ci--jenkins-integration">CI / Jenkins integration</h3>
<p>子議題：</p>
<ul>
<li>Jenkins JMeter plugin</li>
<li>Performance plugin（trend analysis）</li>
<li>對應 <a href="/blog/backend/06-reliability/performance-regression-gate/" data-link-title="6.13 Performance Regression Gate" data-link-desc="把效能 baseline 從一次性壓測變成持續對齊的 release gate，涵蓋 baseline 設定、判讀方法、variance 控制與退化定位">6.13 Performance Regression Gate</a></li>
</ul>
<h3 id="既有-jmx-資產治理">既有 .jmx 資產治理</h3>
<p>子議題：</p>
<ul>
<li>XML 不友善 git diff</li>
<li>大 test plan 可讀性差</li>
<li>改用 module 拆 + Test Fragment</li>
<li>對應企業遷移到 k6 / Gatling 評估</li>
</ul>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<h3 id="high-vu-起不來">High VU 起不來</h3>
<p>操作原則：JVM heap 不夠 / GUI 模式有限制（永遠 non-GUI for production load）。</p>
<h3 id="listener-拖慢">Listener 拖慢</h3>
<p>操作原則：View Results Tree 記錄太多 → 改 simple data writer / disable detail。</p>
<h3 id="distributed-rmi-連不上">Distributed RMI 連不上</h3>
<p>操作原則：firewall + RMI port 不對。</p>
<h3 id="assertion-noise">Assertion noise</h3>
<p>操作原則：assertion failed 多但實際 OK → response time / size 設過嚴。</p>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Code-first / CI-first</td>
          <td><a href="/blog/backend/06-reliability/vendors/k6/" data-link-title="k6" data-link-desc="現代 load test、JS scripting、Grafana Labs">k6</a> / <a href="/blog/backend/06-reliability/vendors/gatling/" data-link-title="Gatling" data-link-desc="JVM-based load test、Scala / Java / Kotlin DSL、強型別 scenario、HAR-driven recording">Gatling</a></td>
      </tr>
      <tr>
          <td>Python</td>
          <td><a href="/blog/backend/06-reliability/vendors/locust/" data-link-title="Locust" data-link-desc="Python-based load test、distributed、易擴展">Locust</a></td>
      </tr>
      <tr>
          <td>Cloud managed</td>
          <td>BlazeMeter / Octoperf / Tricentis NeoLoad</td>
      </tr>
      <tr>
          <td>Browser flow</td>
          <td>Playwright / Cypress / k6 browser</td>
      </tr>
      <tr>
          <td>Capacity planning</td>
          <td><a href="/blog/backend/09-performance-capacity/" data-link-title="模組九：效能工程與容量規劃" data-link-desc="把『目前配置能撐多少、要加多少機器』變成可量化、可驗證、可改進的工程流程">09 performance capacity</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>完整 plugins 列表</li>
<li>BeanShell / Groovy scripting</li>
<li>JMeter internal architecture</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<table>
  <thead>
      <tr>
          <th>案例方向</th>
          <th>對應主題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/06-reliability/cases/linkedin/capacity-headroom-and-oncall-tiering/" data-link-title="LinkedIn：Capacity Headroom 與 On-call 分層" data-link-desc="把容量預測與值班分層綁在一起，降低高峰時段的升級混亂與恢復延遲。">LinkedIn：Capacity 與 On-call 分層</a></td>
          <td>企業內部 load test pipeline + headroom 驗證</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/06-reliability/cases/shopify/bfcm-capacity-and-game-day/" data-link-title="Shopify：BFCM 容量治理與 Game Day 驗證節奏" data-link-desc="把季節性流量峰值轉成年度可靠性流程，透過容量模型、演練與隔離策略提前吸收風險。">Shopify：BFCM 容量治理與 Game Day</a></td>
          <td>峰值前 load test scenario 與 capacity baseline 的對照組</td>
      </tr>
  </tbody>
</table>
<p><strong>待補 JMeter customer case</strong>：企業內部 JMeter 大規模採用案例、JMeter → k6 遷移案例。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游概念：<a href="/blog/backend/06-reliability/performance-regression-gate/" data-link-title="6.13 Performance Regression Gate" data-link-desc="把效能 baseline 從一次性壓測變成持續對齊的 release gate，涵蓋 baseline 設定、判讀方法、variance 控制與退化定位">6.13 Performance Regression Gate</a></li>
<li>平行 vendor：<a href="/blog/backend/06-reliability/vendors/k6/" data-link-title="k6" data-link-desc="現代 load test、JS scripting、Grafana Labs">k6</a>、<a href="/blog/backend/06-reliability/vendors/gatling/" data-link-title="Gatling" data-link-desc="JVM-based load test、Scala / Java / Kotlin DSL、強型別 scenario、HAR-driven recording">Gatling</a></li>
<li>下游能力：<a href="/blog/backend/09-performance-capacity/" data-link-title="模組九：效能工程與容量規劃" data-link-desc="把『目前配置能撐多少、要加多少機器』變成可量化、可驗證、可改進的工程流程">09 performance capacity</a></li>
</ul>
]]></content:encoded></item><item><title>AWS ElastiCache</title><link>https://tarrragon.github.io/blog/backend/02-cache-redis/vendors/aws-elasticache/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/02-cache-redis/vendors/aws-elasticache/</guid><description>&lt;p>AWS ElastiCache 是 AWS managed cache 服務、承擔三個責任：託管 Redis / Valkey / Memcached engine（無需自管 broker）、自動 failover + 跨 AZ 複製、AWS 生態原生整合（IAM / VPC / CloudWatch / KMS）。設計取捨偏向「把運維責任轉給 AWS、付 managed premium 換可預測 SLA」、AWS 生態下的 cache 預設選擇。2024 起 default engine 從 Redis 改為 Valkey（成本約低 20%）。&lt;/p>
&lt;p>對「AWS 生態服務需要 cache、不想自管 Redis cluster、跨 AZ 高可用」這條路徑、ElastiCache 是首選。本頁先給最短路徑、再展開日常 cluster 管理跟 engine 選擇、最後進階治理（Serverless、MemoryDB 對照）跟排錯。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>用 AWS CLI 建立 ElastiCache cluster、選擇 engine（Redis / Valkey / Memcached）&lt;/li>
&lt;li>區分 Cluster mode enabled vs disabled 的選用條件&lt;/li>
&lt;li>配置 auto failover、cross-AZ replication、snapshot backup&lt;/li>
&lt;li>評估 ElastiCache Serverless vs node-based 的成本取捨&lt;/li>
&lt;li>區分 ElastiCache 跟 MemoryDB（durable）跟自管 Redis 的定位&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑5-分鐘把-elasticache-跑起來">最短路徑：5 分鐘把 ElastiCache 跑起來&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 1. 建立 Valkey replication group（cluster mode disabled、單 primary + 1 replica、Multi-AZ）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">aws elasticache create-replication-group &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> --replication-group-id demo &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> --replication-group-description &lt;span class="s2">&amp;#34;demo cache&amp;#34;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> --engine valkey &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> --cache-node-type cache.t4g.micro &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> --num-cache-clusters &lt;span class="m">2&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> --automatic-failover-enabled &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> --multi-az-enabled
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">&lt;span class="c1"># 2. 取得 primary endpoint（建立需數分鐘、status 變 available 才有 endpoint）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">aws elasticache describe-replication-groups &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> --replication-group-id demo &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> --query &lt;span class="s2">&amp;#34;ReplicationGroups[0].NodeGroups[0].PrimaryEndpoint.Address&amp;#34;&lt;/span> --output text
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl">&lt;span class="c1"># 3. 從 VPC 內（EC2 / Lambda）用 redis-cli 連線（ElastiCache 只在 VPC 內可達）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl">redis-cli -h &amp;lt;primary-endpoint&amp;gt; -p &lt;span class="m">6379&lt;/span> PING &lt;span class="c1"># → PONG&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>指令依 &lt;a href="https://docs.aws.amazon.com/cli/latest/reference/elasticache/">AWS ElastiCache CLI 官方文件&lt;/a>、最後檢查日 2026-06-16（managed 服務需 AWS 帳號與 VPC、本機無法 docker 驗證、引數以官方為準）。ElastiCache 端點只在 VPC 內可達、不對公網開放。實際 production 需要評估 cluster mode、節點大小、replica 數、AZ 分布。&lt;/p>
&lt;h2 id="日常操作與決策形狀">日常操作與決策形狀&lt;/h2>
&lt;h3 id="aws-cli-與-console">AWS CLI 與 console&lt;/h3>
&lt;p>子議題：&lt;/p></description><content:encoded><![CDATA[<p>AWS ElastiCache 是 AWS managed cache 服務、承擔三個責任：託管 Redis / Valkey / Memcached engine（無需自管 broker）、自動 failover + 跨 AZ 複製、AWS 生態原生整合（IAM / VPC / CloudWatch / KMS）。設計取捨偏向「把運維責任轉給 AWS、付 managed premium 換可預測 SLA」、AWS 生態下的 cache 預設選擇。2024 起 default engine 從 Redis 改為 Valkey（成本約低 20%）。</p>
<p>對「AWS 生態服務需要 cache、不想自管 Redis cluster、跨 AZ 高可用」這條路徑、ElastiCache 是首選。本頁先給最短路徑、再展開日常 cluster 管理跟 engine 選擇、最後進階治理（Serverless、MemoryDB 對照）跟排錯。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>用 AWS CLI 建立 ElastiCache cluster、選擇 engine（Redis / Valkey / Memcached）</li>
<li>區分 Cluster mode enabled vs disabled 的選用條件</li>
<li>配置 auto failover、cross-AZ replication、snapshot backup</li>
<li>評估 ElastiCache Serverless vs node-based 的成本取捨</li>
<li>區分 ElastiCache 跟 MemoryDB（durable）跟自管 Redis 的定位</li>
</ol>
<h2 id="最短路徑5-分鐘把-elasticache-跑起來">最短路徑：5 分鐘把 ElastiCache 跑起來</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># 1. 建立 Valkey replication group（cluster mode disabled、單 primary + 1 replica、Multi-AZ）</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">aws elasticache create-replication-group <span class="se">\
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="se"></span>  --replication-group-id demo <span class="se">\
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="se"></span>  --replication-group-description <span class="s2">&#34;demo cache&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="se"></span>  --engine valkey <span class="se">\
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="se"></span>  --cache-node-type cache.t4g.micro <span class="se">\
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="se"></span>  --num-cache-clusters <span class="m">2</span> <span class="se">\
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="se"></span>  --automatic-failover-enabled <span class="se">\
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="se"></span>  --multi-az-enabled
</span></span><span class="line"><span class="ln">10</span><span class="cl">
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="c1"># 2. 取得 primary endpoint（建立需數分鐘、status 變 available 才有 endpoint）</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">aws elasticache describe-replication-groups <span class="se">\
</span></span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="se"></span>  --replication-group-id demo <span class="se">\
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="se"></span>  --query <span class="s2">&#34;ReplicationGroups[0].NodeGroups[0].PrimaryEndpoint.Address&#34;</span> --output text
</span></span><span class="line"><span class="ln">15</span><span class="cl">
</span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="c1"># 3. 從 VPC 內（EC2 / Lambda）用 redis-cli 連線（ElastiCache 只在 VPC 內可達）</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">redis-cli -h &lt;primary-endpoint&gt; -p <span class="m">6379</span> PING   <span class="c1"># → PONG</span></span></span></code></pre></div><p>指令依 <a href="https://docs.aws.amazon.com/cli/latest/reference/elasticache/">AWS ElastiCache CLI 官方文件</a>、最後檢查日 2026-06-16（managed 服務需 AWS 帳號與 VPC、本機無法 docker 驗證、引數以官方為準）。ElastiCache 端點只在 VPC 內可達、不對公網開放。實際 production 需要評估 cluster mode、節點大小、replica 數、AZ 分布。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="aws-cli-與-console">AWS CLI 與 console</h3>
<p>子議題：</p>
<ul>
<li>CLI 指令對照表（create-cache-cluster / create-replication-group / describe-* / modify-* / delete-*）</li>
<li>Console 操作流程（VPC subnet group / security group / parameter group）</li>
<li>Terraform / CloudFormation 範例</li>
<li>對應指令範例：<code>aws elasticache describe-replication-groups --replication-group-id &lt;id&gt;</code></li>
</ul>
<h3 id="engine-選擇">Engine 選擇</h3>
<p>子議題：</p>
<ul>
<li><strong>Valkey</strong>（2024+ default）：成本低 20%、OSI 開源、Redis 7.2.4 fork</li>
<li><strong>Redis OSS</strong>（legacy support）：仍可選、但 AWS 不推</li>
<li><strong>Memcached</strong>：純 cache 場景、無 cluster mode 概念（client-side sharding）</li>
<li>選擇判讀：新部署 → Valkey；既有 Redis 遷移 → Valkey（API 相容）；純 cache → Memcached</li>
</ul>
<h3 id="cluster-mode-enabled-vs-disabled">Cluster mode enabled vs disabled</h3>
<p>子議題：</p>
<ul>
<li><strong>Disabled</strong>：1 primary + N replica（最多 5）、單 shard、上限 ~340GB</li>
<li><strong>Enabled</strong>：多 shard（最多 500）、自動 sharding、橫向擴展</li>
<li>客戶端要求：Cluster mode enabled 需要 cluster-aware client</li>
<li>選擇判讀：&lt; 300GB + 簡單 → disabled；&gt; 300GB 或要 sharding → enabled</li>
</ul>
<h3 id="snapshot-與-backup">Snapshot 與 backup</h3>
<p>子議題：</p>
<ul>
<li>Automatic snapshot（保留 1-35 天）</li>
<li>Manual snapshot（保留永久、可跨 region 複製）</li>
<li>Restore：從 snapshot 建新 cluster</li>
<li>對應指令：<code>aws elasticache create-snapshot</code></li>
</ul>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<h3 id="auto-failover-機制">Auto failover 機制</h3>
<p>子議題：</p>
<ul>
<li>Multi-AZ 部署：primary 失敗、replica 自動晉升</li>
<li>Failover 時間：~30 秒到幾分鐘（依 client 重連)</li>
<li>Client 影響：DNS 切到新 primary、client 要 reconnect</li>
<li>對應 <a href="/blog/backend/02-cache-redis/cases/netflix-evcache-global-cache-layer/" data-link-title="2.C6 Netflix：EVCache 全域快取層" data-link-desc="快取從本地層演進為跨區分散式能力的案例。">2.C6 Netflix EVCache</a> 跨 AZ 對照</li>
</ul>
<h3 id="elasticache-serverless">ElastiCache Serverless</h3>
<p>子議題：</p>
<ul>
<li>On-demand 模式：不選 node type、按 ECPU + storage 計費</li>
<li>自動 scale：流量增加自動擴</li>
<li>適合：流量不可預測、不想規劃容量</li>
<li>不適合：成本敏感（serverless premium）、極大 dataset</li>
</ul>
<h3 id="跨-region-replicationglobal-datastore">跨 region replication（Global Datastore）</h3>
<p>子議題：</p>
<ul>
<li>Global Datastore：1 primary region + 多個 secondary region read replica</li>
<li>跨 region replication lag &lt; 1 second（業界宣稱）</li>
<li>適合 active-passive DR</li>
<li>不支援 active-active multi-master</li>
</ul>
<h3 id="memorydb-對照">MemoryDB 對照</h3>
<p>子議題：</p>
<ul>
<li>ElastiCache：cache、Multi-AZ replica 但仍是 cache 語意（資料可重建）</li>
<li>MemoryDB：Redis-compatible durable database、multi-AZ transaction log</li>
<li>MemoryDB cost 2-3x ElastiCache、但提供 source-of-truth 語意</li>
<li>選擇判讀：要 source-of-truth Redis API → MemoryDB；cache 用途 → ElastiCache</li>
</ul>
<h3 id="parameter-group-與配置">Parameter group 與配置</h3>
<p>子議題：</p>
<ul>
<li>Parameter group：custom maxmemory-policy、timeout、client-output-buffer-limit</li>
<li>Cluster vs parameter group 的應用範圍</li>
<li>對應指令：<code>aws elasticache modify-cache-parameter-group</code></li>
</ul>
<h3 id="iam-authenticationredis-7">IAM authentication（Redis 7+）</h3>
<p>子議題：</p>
<ul>
<li>從 Redis AUTH password 升級到 IAM-based authentication</li>
<li>IAM role / user 連 ElastiCache、無需傳 password</li>
<li>對應 <a href="/blog/backend/07-security-data-protection/" data-link-title="模組七：資安與資料保護" data-link-desc="以問題驅動方式擴充資安知識網：先定義服務環節問題，再以案例作為觸發式參考">security 模組</a></li>
</ul>
<h3 id="cost-模型">Cost 模型</h3>
<p>子議題：</p>
<ul>
<li>Node type 成本（t4g.micro 到 r7g.16xlarge）</li>
<li>Reserved Instance（1/3 年承諾、折扣 30-60%）</li>
<li>Data transfer cost（同 AZ 免費、跨 AZ 收費）</li>
<li>Snapshot storage cost</li>
</ul>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<h3 id="endpoint-連不上">Endpoint 連不上</h3>
<p>操作原則：先確認 VPC + security group + subnet group 配置正確。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">aws elasticache describe-replication-groups --replication-group-id &lt;id&gt; <span class="se">\
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="se"></span>  --query <span class="s2">&#34;ReplicationGroups[0].Status&#34;</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="c1"># 從 VPC 內 EC2 測試連通性</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">redis-cli -h &lt;primary-endpoint&gt; -p <span class="m">6379</span> PING</span></span></code></pre></div><p>判讀路徑：security group 沒開 6379 → VPC peering 不通 → DNS 解析失敗。</p>
<h3 id="failover-過程中-client-持續-error">Failover 過程中 client 持續 error</h3>
<p>操作原則：failover 期間 client 重連需要時間、確認 client 有 reconnect 邏輯。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">aws elasticache describe-events --source-identifier &lt;id&gt; --source-type replication-group
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># 看 failover 開始 / 完成事件、對照 client 重連時間軸</span></span></span></code></pre></div><h3 id="replication-lag-高">Replication lag 高</h3>
<p>操作原則：cross-AZ replication 通常 ms 級、若 &gt; 1 sec 看 CloudWatch ReplicationLag metric。原因可能是 write throughput 過高、replica node 規格不足。</p>
<h3 id="memory-pressure--eviction">Memory pressure / eviction</h3>
<p>操作原則：看 CloudWatch DatabaseMemoryUsagePercentage、超 80% 考慮 scale up node type 或調 maxmemory-policy。</p>
<h3 id="snapshot-失敗">Snapshot 失敗</h3>
<p>操作原則：snapshot 過程暫時 fork（Redis）會佔用記憶體、若 memory 已緊張可能失敗。看 CloudWatch BytesUsedForCache。</p>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>需要 source-of-truth Redis API</td>
          <td>AWS MemoryDB（durable Redis-compatible）</td>
      </tr>
      <tr>
          <td>跨雲</td>
          <td>自管 <a href="/blog/backend/02-cache-redis/vendors/redis/" data-link-title="Redis" data-link-desc="OSS in-memory data structure store、cache 主流">Redis</a> / <a href="/blog/backend/02-cache-redis/vendors/valkey/" data-link-title="Valkey" data-link-desc="Redis fork、Linux Foundation 託管、BSD 授權">Valkey</a></td>
      </tr>
      <tr>
          <td>極端 throughput single instance</td>
          <td><a href="/blog/backend/02-cache-redis/vendors/dragonflydb/" data-link-title="DragonflyDB" data-link-desc="高效能 Redis / Memcached 相容替代、多核架構">DragonflyDB</a> self-host</td>
      </tr>
      <tr>
          <td>Edge / HTTP cache</td>
          <td>CloudFront / Cloudflare Cache（T4 候選）</td>
      </tr>
      <tr>
          <td>不在 AWS 生態</td>
          <td>GCP Memorystore / Azure Cache for Redis</td>
      </tr>
      <tr>
          <td>完全 serverless 計費</td>
          <td>ElastiCache Serverless（同模組內）/ <a href="/blog/backend/02-cache-redis/vendors/momento/" data-link-title="Momento" data-link-desc="Serverless cache、按用量計費、無容量規劃">Momento</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>AWS IAM / VPC / Security Group 完整配置（見 security 模組）</li>
<li>CloudFormation / Terraform 完整模板</li>
<li>AWS pricing 詳細計算</li>
<li>ElastiCache vs Memorystore vs Azure Cache 完整對照</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<h3 id="直接相關案例">直接相關案例</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>對 ElastiCache 的對應</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/netflix-evcache-global-cache-layer/" data-link-title="2.C6 Netflix：EVCache 全域快取層" data-link-desc="快取從本地層演進為跨區分散式能力的案例。">2.C6 Netflix EVCache</a></td>
          <td>EVCache 為 Netflix 自管 Memcached based 全域 cache、對應 ElastiCache for Memcached + Global Datastore</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/shopify-write-through-cache-at-scale/" data-link-title="2.C5 Shopify：Write-through Cache 在高讀流量的實作" data-link-desc="read-heavy 服務如何轉向 write-through 快取模型。">2.C5 Shopify write-through</a></td>
          <td>Write-through 在 managed cache 的實作、ElastiCache 提供同樣 Redis/Valkey API、無 self-host 維運負擔</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/shopify-cache-serialization-migration/" data-link-title="2.C3 Shopify：快取序列化格式遷移" data-link-desc="快取 payload 從 Marshal 轉 MessagePack 的遷移策略。">2.C3 Shopify serialization</a></td>
          <td>Payload 雙軌遷移 client-side 實作、ElastiCache 對應為 engine version upgrade + parameter group 滾動</td>
      </tr>
  </tbody>
</table>
<p><strong>待補 ElastiCache-specific 案例</strong>：Airbnb / Lyft / Pinterest 等公開的 ElastiCache 規模化案例、re:Invent talks（如 ElastiCache for Valkey 遷移、Serverless 採用、Global Datastore active-passive DR 實作）。</p>
<h3 id="跨-vendor-對照">跨 vendor 對照</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>對 ElastiCache 的對應</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/failure-cache-stampede-rollout-regression/" data-link-title="2.C9 反例：快取切換引發 Stampede 回歸" data-link-desc="快取策略切換若缺乏保護，會導致回源壓力與錯誤率連鎖上升。">2.C9 Cache Stampede</a></td>
          <td>Managed 也會 stampede、AWS 不會幫你做 client-side jitter / singleflight、需自行設計</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/contrast-cache-strategy-by-scale/" data-link-title="2.C10 對照：規模差異下的快取策略" data-link-desc="同一快取策略在小中大型服務下會產生不同風險。">2.C10 規模對照</a></td>
          <td>小型 single primary / 中型 Multi-AZ replica / 大型 Cluster mode enabled + Global Datastore</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/meta-mcrouter-global-cache-routing/" data-link-title="2.C2 Meta：mcrouter 與跨區快取路由" data-link-desc="快取從單點最佳化演進到分散式路由層的案例。">2.C2 Meta mcrouter</a></td>
          <td>ElastiCache 對應為 Cluster mode + Configuration Endpoint（client-side discovery）、無原生 protocol proxy</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/meta-cache-consistency-upgrade/" data-link-title="2.C1 Meta：Cache Consistency 升級" data-link-desc="快取 invalidation 一致性如何從常見錯誤演進到高可信治理。">2.C1 Meta cache consistency</a></td>
          <td>Failover / replica promotion 期間 ElastiCache 也會出現一致性議題、CloudWatch ReplicationLag 是主要訊號</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/cloudflare-cache-reserve-tiered-storage/" data-link-title="2.C7 Cloudflare：Cache Reserve 分層儲存快取" data-link-desc="邊緣快取延伸到持久層以降低回源壓力的案例。">2.C7 Cloudflare Cache Reserve</a></td>
          <td>分層儲存對照、AWS 對應為 ElastiCache（hot）+ S3 / DynamoDB（cold）的應用層分層設計</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游概念：<a href="/blog/backend/02-cache-redis/cache-aside/" data-link-title="2.2 cache aside 與失效策略" data-link-desc="整理 read-through 思路、cache miss 與 invalidation">2.2 Cache Aside</a>、<a href="/blog/backend/00-service-selection/cost-risk-tradeoffs/" data-link-title="0.6 成本、風險與選型取捨" data-link-desc="用人力成本、雲端成本、操作成本與失敗代價判斷後端能力投入順序">0.6 成本取捨</a></li>
<li>平行 vendor：<a href="/blog/backend/02-cache-redis/vendors/redis/" data-link-title="Redis" data-link-desc="OSS in-memory data structure store、cache 主流">Redis</a>、<a href="/blog/backend/02-cache-redis/vendors/valkey/" data-link-title="Valkey" data-link-desc="Redis fork、Linux Foundation 託管、BSD 授權">Valkey</a></li>
<li>下游能力：<a href="/blog/backend/02-cache-redis/cache-copy-freshness-boundary/" data-link-title="2.7 Cache Copy Boundary 與 Freshness" data-link-desc="說明快取何時只是可重建副本，何時會影響交易、權限或配額正確性。">2.7 cache copy boundary</a></li>
</ul>
]]></content:encoded></item><item><title>AWS SQS</title><link>https://tarrragon.github.io/blog/backend/03-message-queue/vendors/aws-sqs/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/03-message-queue/vendors/aws-sqs/</guid><description>&lt;p>AWS SQS 是 AWS managed queue 服務、承擔三個責任：訊息排隊與重試（visibility timeout + DLQ）、解耦 producer / consumer（無 broker 運維）、AWS 生態原生整合（Lambda / EventBridge / Step Functions）。設計取捨偏向「極簡 API + managed 運維、用 visibility timeout 取代 broker ACK、無原生 ordering（standard queue）」。&lt;/p>
&lt;p>對「AWS 生態 task queue、不想自管 broker、配合 Lambda 事件處理」這條路徑、SQS 是首選。本頁先給最短路徑、再展開日常 SendMessage / ReceiveMessage 操作與 visibility timeout 設計、最後進階治理（FIFO、DLQ、IAM、VPC endpoint）跟排錯。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>用 AWS CLI 建 standard / FIFO queue、發送與接收訊息&lt;/li>
&lt;li>設計 visibility timeout 對齊 consumer 處理時間&lt;/li>
&lt;li>配置 DLQ（dead-letter queue）與 maxReceiveCount&lt;/li>
&lt;li>區分 long polling vs short polling、配合 Lambda event source mapping&lt;/li>
&lt;li>評估 IAM policy、VPC endpoint、cross-account 訪問等治理場景&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑5-分鐘把-sqs-跑起來">最短路徑：5 分鐘把 SQS 跑起來&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 1. 建 queue（回傳 QueueUrl、後續操作都用它）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">aws sqs create-queue --queue-name demo-queue
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="c1"># 2. 發送訊息&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">aws sqs send-message --queue-url &amp;lt;url&amp;gt; --message-body &lt;span class="s2">&amp;#34;hello&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">&lt;span class="c1"># 3. 接收訊息（long polling、最多等 20 秒）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl">aws sqs receive-message --queue-url &amp;lt;url&amp;gt; --wait-time-seconds &lt;span class="m">20&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>最短路徑驗證「queue 建得起來、能發能收」。實際應用配合 SDK / Lambda、見&lt;a href="#%e6%97%a5%e5%b8%b8%e6%93%8d%e4%bd%9c%e8%88%87%e6%b1%ba%e7%ad%96%e5%bd%a2%e7%8b%80">日常操作&lt;/a>。指令對真實 AWS 需設定 credentials 與 region；本機要先驗證可加 &lt;code>--endpoint-url&lt;/code> 指向 SQS-相容的 local 模擬器跑同一組指令。&lt;/p>
&lt;h2 id="日常操作與決策形狀">日常操作與決策形狀&lt;/h2>
&lt;h3 id="aws-cli-與-sdk">AWS CLI 與 SDK&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>AWS CLI 指令對照表（create-queue / send-message / receive-message / delete-message / set-queue-attributes）&lt;/li>
&lt;li>SDK 配置：region / credentials / retry policy / timeout&lt;/li>
&lt;li>Batch operation（SendMessageBatch、DeleteMessageBatch、最多 10 條）&lt;/li>
&lt;li>對應指令範例：&lt;code>aws sqs get-queue-attributes --queue-url &amp;lt;url&amp;gt;&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="standard-vs-fifo-queue">Standard vs FIFO queue&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>Standard：高吞吐、at-least-once、無 ordering、適合多數 task queue&lt;/li>
&lt;li>FIFO：exactly-once-ish（去重 5 分鐘窗口）、ordering（per MessageGroupId）、吞吐受限（3000 msg/sec with batching）&lt;/li>
&lt;li>選擇判讀（ordering 需求 vs 吞吐）&lt;/li>
&lt;/ul>
&lt;h3 id="visibility-timeout-與-in-flight">Visibility timeout 與 in-flight&lt;/h3>
&lt;p>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/in-flight/" data-link-title="In-Flight Work" data-link-desc="目前已接收但尚未完成處理的工作量">Visibility timeout&lt;/a> 是 SQS 的 delivery 控制機制、取代 broker ACK：&lt;/p></description><content:encoded><![CDATA[<p>AWS SQS 是 AWS managed queue 服務、承擔三個責任：訊息排隊與重試（visibility timeout + DLQ）、解耦 producer / consumer（無 broker 運維）、AWS 生態原生整合（Lambda / EventBridge / Step Functions）。設計取捨偏向「極簡 API + managed 運維、用 visibility timeout 取代 broker ACK、無原生 ordering（standard queue）」。</p>
<p>對「AWS 生態 task queue、不想自管 broker、配合 Lambda 事件處理」這條路徑、SQS 是首選。本頁先給最短路徑、再展開日常 SendMessage / ReceiveMessage 操作與 visibility timeout 設計、最後進階治理（FIFO、DLQ、IAM、VPC endpoint）跟排錯。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>用 AWS CLI 建 standard / FIFO queue、發送與接收訊息</li>
<li>設計 visibility timeout 對齊 consumer 處理時間</li>
<li>配置 DLQ（dead-letter queue）與 maxReceiveCount</li>
<li>區分 long polling vs short polling、配合 Lambda event source mapping</li>
<li>評估 IAM policy、VPC endpoint、cross-account 訪問等治理場景</li>
</ol>
<h2 id="最短路徑5-分鐘把-sqs-跑起來">最短路徑：5 分鐘把 SQS 跑起來</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 1. 建 queue（回傳 QueueUrl、後續操作都用它）</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">aws sqs create-queue --queue-name demo-queue
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 2. 發送訊息</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">aws sqs send-message --queue-url &lt;url&gt; --message-body <span class="s2">&#34;hello&#34;</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="c1"># 3. 接收訊息（long polling、最多等 20 秒）</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl">aws sqs receive-message --queue-url &lt;url&gt; --wait-time-seconds <span class="m">20</span></span></span></code></pre></div><p>最短路徑驗證「queue 建得起來、能發能收」。實際應用配合 SDK / Lambda、見<a href="#%e6%97%a5%e5%b8%b8%e6%93%8d%e4%bd%9c%e8%88%87%e6%b1%ba%e7%ad%96%e5%bd%a2%e7%8b%80">日常操作</a>。指令對真實 AWS 需設定 credentials 與 region；本機要先驗證可加 <code>--endpoint-url</code> 指向 SQS-相容的 local 模擬器跑同一組指令。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="aws-cli-與-sdk">AWS CLI 與 SDK</h3>
<p>子議題：</p>
<ul>
<li>AWS CLI 指令對照表（create-queue / send-message / receive-message / delete-message / set-queue-attributes）</li>
<li>SDK 配置：region / credentials / retry policy / timeout</li>
<li>Batch operation（SendMessageBatch、DeleteMessageBatch、最多 10 條）</li>
<li>對應指令範例：<code>aws sqs get-queue-attributes --queue-url &lt;url&gt;</code></li>
</ul>
<h3 id="standard-vs-fifo-queue">Standard vs FIFO queue</h3>
<p>子議題：</p>
<ul>
<li>Standard：高吞吐、at-least-once、無 ordering、適合多數 task queue</li>
<li>FIFO：exactly-once-ish（去重 5 分鐘窗口）、ordering（per MessageGroupId）、吞吐受限（3000 msg/sec with batching）</li>
<li>選擇判讀（ordering 需求 vs 吞吐）</li>
</ul>
<h3 id="visibility-timeout-與-in-flight">Visibility timeout 與 in-flight</h3>
<p><a href="/blog/backend/knowledge-cards/in-flight/" data-link-title="In-Flight Work" data-link-desc="目前已接收但尚未完成處理的工作量">Visibility timeout</a> 是 SQS 的 delivery 控制機制、取代 broker ACK：</p>
<ul>
<li>訊息被接收後變 in-flight、其他 consumer 看不到</li>
<li>Consumer 處理完呼叫 DeleteMessage、否則 timeout 後回到 queue</li>
<li>ChangeMessageVisibility 動態延長（長任務）</li>
<li>預設 30 秒、上限 12 小時</li>
</ul>
<h3 id="dlq-設計dead-letter-queue">DLQ 設計（dead-letter queue）</h3>
<p>子議題：</p>
<ul>
<li>maxReceiveCount：訊息被接收 N 次後送 DLQ</li>
<li>DLQ 監控與 alarm（CloudWatch metric）</li>
<li>Redrive policy（從 DLQ 重新放回 main queue）</li>
<li>對應 <a href="/blog/backend/knowledge-cards/poison-message/" data-link-title="Poison Message" data-link-desc="說明特定訊息內容如何穩定造成 consumer 失敗">poison message</a> 處理思路</li>
</ul>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<p>visibility timeout、polling、Lambda event source 與 cost 已展開為 deep article：<a href="visibility-polling-lambda-cost/">visibility timeout / long polling / Lambda + cost</a>。下列子議題段保留選題判讀入口。</p>
<h3 id="long-polling-vs-short-polling">Long polling vs Short polling</h3>
<p>子議題：</p>
<ul>
<li>Short polling（預設）：立即回應、可能空回（高 cost）</li>
<li>Long polling（WaitTimeSeconds 1-20）：等到有訊息或超時</li>
<li>對 cost 與 latency 的取捨</li>
</ul>
<h3 id="sqs--lambda-event-source-mapping">SQS + Lambda event source mapping</h3>
<p>子議題：</p>
<ul>
<li>Lambda 自動 poll SQS（managed event source）</li>
<li>Batch size / batch window 配置</li>
<li>Partial batch failure（ReportBatchItemFailures）</li>
<li>對應 <a href="/blog/backend/03-message-queue/cases/cloudflare-queues-global-delivery-model/" data-link-title="3.C8 Cloudflare：Queues 全球交付模型" data-link-desc="事件佇列服務在全球網路下的交付語義與治理案例。">3.C8 Cloudflare Queues</a> 的全球交付對照</li>
</ul>
<h3 id="iam--cross-account-訪問">IAM / Cross-account 訪問</h3>
<p>子議題：</p>
<ul>
<li>Queue policy（resource-based）vs IAM policy（identity-based）</li>
<li>Cross-account producer / consumer 設定</li>
<li>Encryption（SSE-SQS / SSE-KMS）</li>
</ul>
<h3 id="vpc-endpoint私網訪問">VPC endpoint（私網訪問）</h3>
<p>子議題：</p>
<ul>
<li>Interface endpoint（PrivateLink）</li>
<li>適合不想經 public internet 的場景</li>
<li>跟 NAT Gateway 的 cost 對照</li>
</ul>
<h3 id="cloudwatch-metric-與-alarm">CloudWatch metric 與 alarm</h3>
<p>子議題：</p>
<ul>
<li>ApproximateNumberOfMessagesVisible（queue depth）</li>
<li>ApproximateAgeOfOldestMessage（lag 訊號）</li>
<li>NumberOfMessagesSent / Received / Deleted</li>
<li>Alarm 設計（depth 暴增、age 超 SLO）</li>
</ul>
<h3 id="cost-模型">Cost 模型</h3>
<p>子議題：</p>
<ul>
<li>Request cost（每百萬 request）</li>
<li>Data transfer cost（跨 region 才有）</li>
<li>FIFO 比 standard 貴的判讀</li>
<li>對應 <a href="/blog/backend/00-service-selection/cost-risk-tradeoffs/" data-link-title="0.6 成本、風險與選型取捨" data-link-desc="用人力成本、雲端成本、操作成本與失敗代價判斷後端能力投入順序">0.6 成本取捨</a></li>
</ul>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<h3 id="message-反覆-redelivery看到同訊息多次">Message 反覆 redelivery（看到同訊息多次）</h3>
<p>操作原則：visibility timeout 設定 &lt; consumer 處理時間、訊息回 queue 又被另一 consumer 領走。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">aws sqs get-queue-attributes --queue-url &lt;url&gt; --attribute-names VisibilityTimeout
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># 新建 queue 預設 VisibilityTimeout 為 30 秒、處理時間長於此值就會看到 redelivery</span></span></span></code></pre></div><p>調整：延長 VisibilityTimeout 或 consumer 主動 ChangeMessageVisibility。</p>
<h3 id="dlq-累積">DLQ 累積</h3>
<p>操作原則：先看 DLQ 訊息內容、判斷 poison message vs 下游卡。</p>
<p>判讀路徑：訊息格式錯（永遠失敗）→ 下游服務 down（暫時失敗、可 redrive）→ consumer bug。</p>
<h3 id="throttlingaccount-quota">Throttling（account quota）</h3>
<p>操作原則：超過 account-level SendMessage / ReceiveMessage TPS、看 CloudWatch ThrottledRequests。處理：requeue exchange、quota 申請。</p>
<h3 id="iam-權限錯">IAM 權限錯</h3>
<p>操作原則：access denied 大多是 queue policy 跟 IAM policy 互動。判讀：用 IAM Policy Simulator 或 CloudTrail 看 deny 原因。</p>
<h3 id="lambda-event-source-失敗">Lambda event source 失敗</h3>
<p>操作原則：Lambda 失敗會自動 retry、超過 retry 進 DLQ。看 Lambda 的 DLQ 跟 SQS 的 DLQ 分工。</p>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>需要 streaming / replay</td>
          <td>AWS Kinesis / <a href="/blog/backend/03-message-queue/vendors/kafka/" data-link-title="Apache Kafka" data-link-desc="Distributed event streaming platform、log-based 模型">Kafka</a> / MSK</td>
      </tr>
      <tr>
          <td>需要 pub/sub fan-out</td>
          <td>AWS SNS（搭配 SQS 做 fan-out）/ EventBridge</td>
      </tr>
      <tr>
          <td>需要複雜 routing</td>
          <td><a href="/blog/backend/03-message-queue/vendors/rabbitmq/" data-link-title="RabbitMQ" data-link-desc="Classic message broker、AMQP routing 為主">RabbitMQ</a> on EC2</td>
      </tr>
      <tr>
          <td>跨雲 / 跨平台</td>
          <td><a href="/blog/backend/03-message-queue/vendors/kafka/" data-link-title="Apache Kafka" data-link-desc="Distributed event streaming platform、log-based 模型">Kafka</a> / <a href="/blog/backend/03-message-queue/vendors/nats/" data-link-title="NATS" data-link-desc="Lightweight messaging、JetStream 加持久化與 streams">NATS</a></td>
      </tr>
      <tr>
          <td>嚴格低延遲（&lt; 100ms）</td>
          <td><a href="/blog/backend/03-message-queue/vendors/nats/" data-link-title="NATS" data-link-desc="Lightweight messaging、JetStream 加持久化與 streams">NATS</a> / Redis</td>
      </tr>
      <tr>
          <td>Workflow + durable execution</td>
          <td>AWS Step Functions / Temporal</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>SNS / EventBridge 細節（另開 cloud event routing 章節）</li>
<li>Step Functions / Lambda 完整功能</li>
<li>AWS SDK 各語言完整 API</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<h3 id="sqs-專屬案例c48-c59">SQS 專屬案例（C48-C59）</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>主討論議題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/sqs-airbnb-dynein-delayed-jobs/" data-link-title="3.C48 Airbnb Dynein：SQS 分散式延遲任務排程" data-link-desc="Airbnb 用 SQS at-least-once &#43; DLQ 取代 Resque 單 Redis 限制、每 scheduler 1000 QPS、SQS wrap DynamoDB 處理 &gt; 15 分鐘 delay。">3.C48 Airbnb Dynein</a></td>
          <td>分散式延遲任務 / at-least-once + DLQ</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/sqs-airbnb-inspekt-data-protection/" data-link-title="3.C49 Airbnb Inspekt：Visibility timeout 當 retry budget" data-link-desc="Airbnb Inspekt 隱私掃描器、scanner pull message、visibility timeout 自然觸發重現、用重現次數當 retry budget。">3.C49 Airbnb Inspekt</a></td>
          <td>Visibility timeout 當隱式 retry</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/sqs-capital-one-visibility-timeout/" data-link-title="3.C50 Capital One：Visibility timeout 設計與 Lambda event source" data-link-desc="Capital One tech blog 講 SQS &#43; Lambda：visibility timeout 應略高於最大處理時間、Lambda 初 5 個 long polling、可擴 60/min。">3.C50 Capital One</a></td>
          <td>Visibility timeout / Lambda event source</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/sqs-atlassian-jirt-kinesis-sqs/" data-link-title="3.C51 Atlassian JiRT：Kinesis &#43; SQS subscription" data-link-desc="Atlassian StreamHub Kinesis 底層、每 consumer 自己一個 SQS queue、JiRT 把輪詢 1 min 改成秒級 event-driven。">3.C51 Atlassian JiRT</a></td>
          <td>Kinesis + per-consumer SQS</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/sqs-nielsen-spark-eks-dual-queue/" data-link-title="3.C52 Nielsen：Spark on EKS 雙 SQS 工作流" data-link-desc="Nielsen 每日 25TB / 30B event、work queue &#43; completion queue 雙 SQS、queue depth autoscale EKS pod。">3.C52 Nielsen Spark on EKS</a></td>
          <td>雙 SQS / queue depth autoscale</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/sqs-finra-large-file-service/" data-link-title="3.C53 FINRA：S3 → SQS notification 大檔上傳" data-link-desc="FINRA 金融監管、broker 上傳大檔、S3 → SQS notification → LFS、KMS &#43; bucket policy &#43; queue policy 三層稽核。">3.C53 FINRA Large File</a></td>
          <td>S3 → SQS 合規 / IAM 多層稽核</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/sqs-twitch-eventsub-fanout/" data-link-title="3.C54 Twitch EventSub：SNS&#43;SQS fan-out 給第三方" data-link-desc="Twitch Event Bus ~1660 events/sec 進 SNS、EventSub 用 SQS 接收 &#43; Dispatcher fan-out 給訂閱者。">3.C54 Twitch EventSub</a></td>
          <td>SNS-SQS fan-out + Dispatcher</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/sqs-smugmug-search-pipeline/" data-link-title="3.C55 SmugMug：SQS 驅動可重放搜尋管線" data-link-desc="SmugMug 用 SQS 兩種模式：DynamoDB scan-segment 平行 backfill &#43; production query 鏡像 replay 到 replica。">3.C55 SmugMug search</a></td>
          <td>Workload generator / 平行 scan + replay</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/sqs-postnl-mission-critical-ebe/" data-link-title="3.C56 PostNL EBE：完整 DLQ &#43; retention &#43; redrive 設計" data-link-desc="PostNL 物流每天 1000 萬訊息、每 producer/consumer 隔離 stack、24h 內 100 次 retry、final DLQ 可 consumer redrive。">3.C56 PostNL EBE</a></td>
          <td>完整 DLQ + redrive + 隔離 stack</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/sqs-lob-sqs-consumer-library/" data-link-title="3.C57 Lob：自家 fork @lob/sqs-consumer 修 FIFO bug" data-link-desc="Lob 原用 bbc/sqs-consumer 鎖 SDK v2、fork 出 @lob/sqs-consumer 支援 SDK v3 &#43; TypeScript &#43; 修 FIFO bug。">3.C57 Lob sqs-consumer</a></td>
          <td>Client library / SDK v3 / FIFO bug</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/sqs-twilio-webhook-buffer/" data-link-title="3.C58 Twilio：SQS 緩衝高流量 webhook" data-link-desc="Twilio 教用 SQS 緩衝 SMS / status callback webhook、分 queue（SMS vs callback）、long polling 減 cost、FIFO 300 TPS 上限要分片。">3.C58 Twilio webhook</a></td>
          <td>Webhook → SQS buffer / FIFO 300 TPS</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/sqs-rapid7-scale-billion-messages/" data-link-title="3.C59 Rapid7：SQS 100 億 message/day 規模" data-link-desc="Rapid7 公開引述：SQS 撐 10s of billions of messages per day、是架構關鍵元件、scale 量級的具體參考。">3.C59 Rapid7 scale</a></td>
          <td>100 億 msg/day 規模參考點</td>
      </tr>
  </tbody>
</table>
<h3 id="跨-vendor-對照">跨 vendor 對照</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>對 SQS 的對應</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/vmware-kafka-to-msk/" data-link-title="3.C2 VMware Tanzu CloudHealth：Kafka 轉 Amazon MSK" data-link-desc="自管 Kafka 遷移到託管平台時的治理重點。">3.C2 VMware → MSK</a></td>
          <td>反面對照：何時 managed queue 不夠用、要升 streaming</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/cloudflare-queues-global-delivery-model/" data-link-title="3.C8 Cloudflare：Queues 全球交付模型" data-link-desc="事件佇列服務在全球網路下的交付語義與治理案例。">3.C8 Cloudflare Queues</a></td>
          <td>全球交付對照（SQS 是 region-scoped）</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/contrast-queue-model-by-scale/" data-link-title="3.C10 對照：規模差異下的佇列模型" data-link-desc="同一 queue 模型在不同規模下的治理與失敗邊界差異。">3.C10 規模對照</a></td>
          <td>小型直接用 SQS / 中型補 idempotency / 大型補 streaming</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游概念：<a href="/blog/backend/00-service-selection/async-delivery-selection/" data-link-title="0.3 非同步與事件傳遞選型" data-link-desc="區分背景工作、durable queue、stream、pub/sub 與 outbox 的選型邊界">0.3 非同步選型</a>、<a href="/blog/backend/03-message-queue/broker-basics/" data-link-title="3.1 broker 基礎與投遞模型" data-link-desc="先理解 broker、queue、consumer 與 delivery semantics">3.1 broker basics</a></li>
<li>平行 vendor：<a href="/blog/backend/03-message-queue/vendors/google-pubsub/" data-link-title="Google Cloud Pub/Sub" data-link-desc="GCP managed pub/sub、global routing、push/pull">Google Pub/Sub</a>、<a href="/blog/backend/03-message-queue/vendors/rabbitmq/" data-link-title="RabbitMQ" data-link-desc="Classic message broker、AMQP routing 為主">RabbitMQ</a></li>
<li>下游能力：<a href="/blog/backend/03-message-queue/durable-queue/" data-link-title="3.2 durable queue 與重試策略" data-link-desc="整理持久化佇列、DLQ 與重試流程">3.2 durable queue</a>、<a href="/blog/backend/03-message-queue/consumer-design/" data-link-title="3.4 consumer 設計與去重" data-link-desc="整理 consumer、checkpoint 與 replay safety">3.4 consumer 設計</a></li>
</ul>
]]></content:encoded></item><item><title>Elastic Stack</title><link>https://tarrragon.github.io/blog/backend/04-observability/vendors/elastic-stack/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/04-observability/vendors/elastic-stack/</guid><description>&lt;p>Elastic Stack（前 ELK）是 logs-heavy observability 棧、承擔三個責任：Elasticsearch 搜尋與分析（full-text + structured query）、Beats / Logstash 採集 pipeline、Kibana 視覺化 + Elastic APM（traces）。設計取捨偏向「搜尋為核心 + 統一搜尋介面 + Elastic Security SIEM 整合」。AWS 因 2021 license 變動 fork OpenSearch、提供 Apache 2.0 替代。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>部署 Elasticsearch + Kibana + Beats 基本棧&lt;/li>
&lt;li>用 KQL / Lucene 查詢 logs、用 ES DSL 寫進階搜尋&lt;/li>
&lt;li>設計 index lifecycle（hot / warm / cold / frozen）&lt;/li>
&lt;li>評估 Beats / Logstash / Fluent Bit / Vector 的採集選擇&lt;/li>
&lt;li>評估 Elastic License vs OpenSearch fork 的取捨&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑5-分鐘把-elastic-stack-跑起來">最短路徑：5 分鐘把 Elastic Stack 跑起來&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 1. 用 docker-compose 跑 ES + Kibana&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: docker-compose.yml with elasticsearch + kibana&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="c1"># 2. 用 Filebeat 採集 host logs&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: filebeat.yml with inputs + output.elasticsearch&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">&lt;span class="c1"># 3. 在 Kibana 查詢驗證&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: KQL: `@timestamp &amp;gt;= now-15m AND log.level: &amp;#34;error&amp;#34;`&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="日常操作與決策形狀">日常操作與決策形狀&lt;/h2>
&lt;h3 id="採集-pipeline">採集 pipeline&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>Beats（Filebeat / Metricbeat / Packetbeat / Heartbeat / Auditbeat）：輕量、各自專屬&lt;/li>
&lt;li>Logstash：重型 ETL（grok parsing / enrichment / 多 output）&lt;/li>
&lt;li>Fluent Bit / Vector：替代採集 agent（更輕量、OSS）&lt;/li>
&lt;li>對應 &lt;a href="https://tarrragon.github.io/blog/backend/04-observability/cases/adot-eks-observability-pipeline-migration/" data-link-title="4.C6 AWS：ADOT on EKS 管線遷移" data-link-desc="從分散式 agent 組合轉成 OpenTelemetry collector 管線治理。">4.C6 ADOT EKS&lt;/a> 對照&lt;/li>
&lt;/ul>
&lt;h3 id="查詢語法">查詢語法&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>KQL（Kibana Query Language）：直覺、適合日常查詢&lt;/li>
&lt;li>Lucene query string：複雜搜尋、boolean operators&lt;/li>
&lt;li>ES DSL（JSON）：API 級進階查詢&lt;/li>
&lt;li>ES|QL（Elastic Query Language、ES 8.11+）：類 SQL pipeline 語法&lt;/li>
&lt;/ul>
&lt;h3 id="index-設計">Index 設計&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>Index template（mapping / settings）&lt;/li>
&lt;li>Data streams（time-series log / metrics）&lt;/li>
&lt;li>Field types：keyword / text / date / numeric / object / nested&lt;/li>
&lt;li>Dynamic mapping 風險：unbounded field 爆 index&lt;/li>
&lt;/ul>
&lt;h3 id="index-lifecycle-managementilm">Index Lifecycle Management（ILM）&lt;/h3>
&lt;p>子議題：&lt;/p></description><content:encoded><![CDATA[<p>Elastic Stack（前 ELK）是 logs-heavy observability 棧、承擔三個責任：Elasticsearch 搜尋與分析（full-text + structured query）、Beats / Logstash 採集 pipeline、Kibana 視覺化 + Elastic APM（traces）。設計取捨偏向「搜尋為核心 + 統一搜尋介面 + Elastic Security SIEM 整合」。AWS 因 2021 license 變動 fork OpenSearch、提供 Apache 2.0 替代。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>部署 Elasticsearch + Kibana + Beats 基本棧</li>
<li>用 KQL / Lucene 查詢 logs、用 ES DSL 寫進階搜尋</li>
<li>設計 index lifecycle（hot / warm / cold / frozen）</li>
<li>評估 Beats / Logstash / Fluent Bit / Vector 的採集選擇</li>
<li>評估 Elastic License vs OpenSearch fork 的取捨</li>
</ol>
<h2 id="最短路徑5-分鐘把-elastic-stack-跑起來">最短路徑：5 分鐘把 Elastic Stack 跑起來</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 1. 用 docker-compose 跑 ES + Kibana</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># TODO: docker-compose.yml with elasticsearch + kibana</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 2. 用 Filebeat 採集 host logs</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="c1"># TODO: filebeat.yml with inputs + output.elasticsearch</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="c1"># 3. 在 Kibana 查詢驗證</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="c1"># TODO: KQL: `@timestamp &gt;= now-15m AND log.level: &#34;error&#34;`</span></span></span></code></pre></div><h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="採集-pipeline">採集 pipeline</h3>
<p>子議題：</p>
<ul>
<li>Beats（Filebeat / Metricbeat / Packetbeat / Heartbeat / Auditbeat）：輕量、各自專屬</li>
<li>Logstash：重型 ETL（grok parsing / enrichment / 多 output）</li>
<li>Fluent Bit / Vector：替代採集 agent（更輕量、OSS）</li>
<li>對應 <a href="/blog/backend/04-observability/cases/adot-eks-observability-pipeline-migration/" data-link-title="4.C6 AWS：ADOT on EKS 管線遷移" data-link-desc="從分散式 agent 組合轉成 OpenTelemetry collector 管線治理。">4.C6 ADOT EKS</a> 對照</li>
</ul>
<h3 id="查詢語法">查詢語法</h3>
<p>子議題：</p>
<ul>
<li>KQL（Kibana Query Language）：直覺、適合日常查詢</li>
<li>Lucene query string：複雜搜尋、boolean operators</li>
<li>ES DSL（JSON）：API 級進階查詢</li>
<li>ES|QL（Elastic Query Language、ES 8.11+）：類 SQL pipeline 語法</li>
</ul>
<h3 id="index-設計">Index 設計</h3>
<p>子議題：</p>
<ul>
<li>Index template（mapping / settings）</li>
<li>Data streams（time-series log / metrics）</li>
<li>Field types：keyword / text / date / numeric / object / nested</li>
<li>Dynamic mapping 風險：unbounded field 爆 index</li>
</ul>
<h3 id="index-lifecycle-managementilm">Index Lifecycle Management（ILM）</h3>
<p>子議題：</p>
<ul>
<li>Hot phase：active write</li>
<li>Warm phase：read-only、查詢頻率低</li>
<li>Cold phase：searchable snapshot（S3 / object storage）</li>
<li>Frozen phase（ES 7.12+）：searchable snapshot + minimal cluster resource</li>
<li>Delete phase</li>
</ul>
<h2 id="deep-article">Deep Article</h2>
<ul>
<li><a href="ilm-log-pipeline/">Index Lifecycle Management 與 Log Pipeline</a>：ILM policy 設計、data stream / rollover、Beats vs Elastic Agent 採集選擇、ingest pipeline 與 shard sizing、cost governance</li>
</ul>
<h2 id="migration-playbook">Migration Playbook</h2>
<ul>
<li><a href="migrate-to-elastic-cloud/">Elastic Cloud 遷移</a>：自管 Elastic Stack 遷移到 Elastic Cloud</li>
</ul>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<h3 id="elastic-apm">Elastic APM</h3>
<p>子議題：</p>
<ul>
<li>APM Server 接收 trace data</li>
<li>各語言 APM agent（Java / Python / Node / .NET / Go / Ruby / PHP）</li>
<li>接受 OTLP（ES 7.16+）</li>
<li>Service map / dependency 視覺化</li>
</ul>
<h3 id="elastic-securitysiem">Elastic Security（SIEM）</h3>
<p>子議題：</p>
<ul>
<li>SIEM dashboard / detection rule</li>
<li>ECS（Elastic Common Schema）跨資料統一 field naming</li>
<li>Sigma rule import</li>
<li>跟 <a href="/blog/backend/07-security-data-protection/" data-link-title="模組七：資安與資料保護" data-link-desc="以問題驅動方式擴充資安知識網：先定義服務環節問題，再以案例作為觸發式參考">07 security 模組</a> 對照</li>
</ul>
<h3 id="cluster-scaling">Cluster scaling</h3>
<p>子議題：</p>
<ul>
<li>Node roles：master / data / ingest / coordinating / ML / transform</li>
<li>Hot-warm-cold architecture</li>
<li>Shard sizing（推薦 20-40GB per shard）</li>
<li>Cross-cluster search / replication</li>
</ul>
<h3 id="elastic-license-vs-opensearch-fork">Elastic License vs OpenSearch fork</h3>
<p>子議題：</p>
<ul>
<li>2021 Elastic 改 ELv2 / SSPL（非 OSI 認可）— AWS 不能提供「Elasticsearch as a Service」</li>
<li>AWS fork OpenSearch（Apache 2.0、基於 ES 7.10）</li>
<li>OpenSearch 持續演進、跟 ES 功能逐漸分歧</li>
<li>選擇判讀：合規 → OpenSearch；要最新 ES feature → Elastic</li>
</ul>
<h3 id="searchable-snapshots">Searchable Snapshots</h3>
<p>子議題：</p>
<ul>
<li>把 cold/frozen index 存 S3 / GCS / Azure Blob</li>
<li>查詢時動態 hydrate、成本降 80%+</li>
<li>適合 logs retention 長但查詢頻率低</li>
<li>對應 <a href="/blog/backend/04-observability/cases/healthcare-access-traceability-and-retention/" data-link-title="Healthcare：存取可追溯性與保留邊界" data-link-desc="在資料主權限制下，建立可追溯存取證據與分層保留策略。">4.C3 Healthcare retention</a></li>
</ul>
<h3 id="vector--fluent-bit-採集替代">Vector / Fluent Bit 採集替代</h3>
<p>子議題：</p>
<ul>
<li>為何用 Vector / Fluent Bit：更輕、resource 用量低</li>
<li>Beats 在 K8s 跑起來資源耗較大</li>
<li>對應 cost 跟 maintainability 取捨</li>
</ul>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<h3 id="index-mapping-explosion">Index mapping explosion</h3>
<p>操作原則：dynamic mapping 對未知 field 自動建 index、大量 field 爆 ES。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># TODO: GET /_cat/indices?v 看 field count</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># TODO: PUT index/_mapping 鎖定 fields</span></span></span></code></pre></div><h3 id="cluster-yellow--red">Cluster yellow / red</h3>
<p>操作原則：cluster status 影響 query。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># TODO: GET /_cluster/health</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># TODO: GET /_cat/shards?v 看 unassigned shards</span></span></span></code></pre></div><h3 id="query-過慢">Query 過慢</h3>
<p>操作原則：query 結果 &gt; 10K → 用 search_after / scroll；text field 上做 aggregation → 改 keyword field。</p>
<h3 id="disk-pressure">Disk pressure</h3>
<p>操作原則：cluster disk &gt; 85% → ES 進 read-only 模式。判讀：cluster.routing.allocation.disk.watermark。</p>
<h3 id="logstash-backpressure">Logstash backpressure</h3>
<p>操作原則：Logstash queue full → upstream Beats 累積 backpressure。判讀：Logstash monitoring page。</p>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Pure metrics</td>
          <td><a href="/blog/backend/04-observability/vendors/prometheus/" data-link-title="Prometheus" data-link-desc="Pull-based metrics 主流 OSS、PromQL 與 alerting">Prometheus</a> / Mimir</td>
      </tr>
      <tr>
          <td>純 logs 但 less search</td>
          <td>Loki（<a href="/blog/backend/04-observability/vendors/grafana-stack/" data-link-title="Grafana Stack" data-link-desc="Grafana / Loki / Tempo / Mimir / Pyroscope 全棧">Grafana Stack</a>）— 更便宜</td>
      </tr>
      <tr>
          <td>SaaS turnkey APM</td>
          <td><a href="/blog/backend/04-observability/vendors/datadog/" data-link-title="Datadog" data-link-desc="All-in-one SaaS 觀測平台、APM / Logs / Metrics / RUM / Security">Datadog</a></td>
      </tr>
      <tr>
          <td>AWS-managed Elastic</td>
          <td>OpenSearch on AWS（Apache 2.0）</td>
      </tr>
      <tr>
          <td>Cloud-native logs</td>
          <td><a href="/blog/backend/04-observability/vendors/aws-cloudwatch/" data-link-title="AWS CloudWatch" data-link-desc="AWS 原生觀測性服務、Logs / Metrics / Traces (X-Ray)">CloudWatch Logs</a> / <a href="/blog/backend/04-observability/vendors/gcp-cloud-operations/" data-link-title="GCP Cloud Operations" data-link-desc="GCP 原生觀測性套件（前 Stackdriver）：Logging / Monitoring / Trace / Profiler">Cloud Logging</a></td>
      </tr>
      <tr>
          <td>多 tier observability</td>
          <td><a href="/blog/backend/04-observability/vendors/datadog/" data-link-title="Datadog" data-link-desc="All-in-one SaaS 觀測平台、APM / Logs / Metrics / RUM / Security">Datadog</a> / <a href="/blog/backend/04-observability/vendors/grafana-stack/" data-link-title="Grafana Stack" data-link-desc="Grafana / Loki / Tempo / Mimir / Pyroscope 全棧">Grafana Stack</a></td>
      </tr>
      <tr>
          <td>Enterprise SIEM</td>
          <td>Splunk / Microsoft Sentinel</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>ES query DSL 完整 reference</li>
<li>Lucene scoring 演算法</li>
<li>Kibana dashboard 美術</li>
<li>Elastic ML / Anomaly Detection 細節</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<h3 id="直接相關案例">直接相關案例</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>主討論議題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/fintech-audit-evidence-observability/" data-link-title="FinTech：審計證據鏈的可觀測性設計" data-link-desc="把交易與存取事件轉成可回查證據，降低合規審核與事故判讀落差。">4.C1 Fintech audit</a></td>
          <td>Logs 作為 audit evidence</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/healthcare-access-traceability-and-retention/" data-link-title="Healthcare：存取可追溯性與保留邊界" data-link-desc="在資料主權限制下，建立可追溯存取證據與分層保留策略。">4.C3 Healthcare retention</a></td>
          <td>Index Lifecycle / retention</td>
      </tr>
  </tbody>
</table>
<h3 id="跨-vendor-對照">跨 vendor 對照</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>對 Elastic Stack 的對應</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/adot-eks-observability-pipeline-migration/" data-link-title="4.C6 AWS：ADOT on EKS 管線遷移" data-link-desc="從分散式 agent 組合轉成 OpenTelemetry collector 管線治理。">4.C6 ADOT EKS pipeline</a></td>
          <td>Beats / Logstash ↔ OTel Collector 採集 pipeline 對照</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/contrast-observability-rollout-by-scale/" data-link-title="4.C10 對照：規模差異下的觀測遷移" data-link-desc="觀測遷移在不同規模團隊下的流程與風險差異。">4.C10 規模對照</a></td>
          <td>小型 single-node / 中型 hot-warm / 大型 hot-warm-cold-frozen</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游概念：<a href="/blog/backend/04-observability/telemetry-data-quality/" data-link-title="4.17 Telemetry Data Quality" data-link-desc="把 missing signal、schema drift、sampling bias 與 timestamp skew 變成資料品質問題">4.17 Telemetry Data Quality</a></li>
<li>平行 vendor：<a href="/blog/backend/04-observability/vendors/grafana-stack/" data-link-title="Grafana Stack" data-link-desc="Grafana / Loki / Tempo / Mimir / Pyroscope 全棧">Grafana Stack</a>（Loki 對照）、<a href="/blog/backend/04-observability/vendors/opentelemetry/" data-link-title="OpenTelemetry" data-link-desc="可觀測性開放標準、SDK 與 Collector">OpenTelemetry</a></li>
<li>下游能力：<a href="/blog/backend/04-observability/observability-evidence-package/" data-link-title="4.20 Observability Evidence Package" data-link-desc="把 log、metric、trace、audit 與資料品質限制包成可交接證據">4.20 Observability Evidence Package</a></li>
</ul>
]]></content:encoded></item><item><title>Envoy</title><link>https://tarrragon.github.io/blog/backend/05-deployment-platform/vendors/envoy/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/05-deployment-platform/vendors/envoy/</guid><description>&lt;p>Envoy 是 CNCF graduated 的 service proxy、承擔三個責任：cloud-native L7 + L4 proxy（HTTP/1.1 + HTTP/2 + HTTP/3 + gRPC）、xDS dynamic config（不需 reload）、observability 內建（access log / stats / tracing）。設計取捨偏向「dynamic config + advanced traffic management + filter chain extensibility」、是 Istio / Linkerd2-proxy / AWS App Mesh / Envoy Gateway 的底層實作。&lt;/p>
&lt;p>對「service mesh data plane、API Gateway、advanced traffic management、gRPC / HTTP/2 / HTTP/3」這條路徑、Envoy 是首選。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>跑起 Envoy + 基本 reverse proxy config&lt;/li>
&lt;li>用 xDS API 動態更新 config（不 reload）&lt;/li>
&lt;li>配置 listener / route / cluster / filter chain&lt;/li>
&lt;li>看懂 Envoy access log + stats + admin endpoint&lt;/li>
&lt;li>評估 Envoy 直接用 vs 用 Istio / Envoy Gateway 抽象&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑5-分鐘把-envoy-跑起來">最短路徑：5 分鐘把 Envoy 跑起來&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 1. 啟動 Envoy&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">docker run -d --name envoy-demo &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> -p 9901:9901 -p 10000:10000 &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> -v &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>&lt;span class="nb">pwd&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">/envoy.yaml:/etc/envoy/envoy.yaml:ro&amp;#34;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> envoyproxy/envoy:v1.31-latest&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Static config 範例（&lt;code>envoy.yaml&lt;/code>）：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="nt">static_resources&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">listeners&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">listener_0&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">address&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>{&lt;span class="w"> &lt;/span>&lt;span class="nt">socket_address&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>{&lt;span class="w"> &lt;/span>&lt;span class="nt">address: 0.0.0.0, port_value&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">10000&lt;/span>&lt;span class="w"> &lt;/span>}&lt;span class="w"> &lt;/span>}&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">filter_chains&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">filters&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">envoy.filters.network.http_connection_manager&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">typed_config&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">&amp;#34;@type&amp;#34;: &lt;/span>&lt;span class="l">type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">stat_prefix&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">ingress_http&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">route_config&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">virtual_hosts&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">backend&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">domains&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;*&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">routes&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">match&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>{&lt;span class="w"> &lt;/span>&lt;span class="nt">prefix&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;/&amp;#34;&lt;/span>&lt;span class="w"> &lt;/span>}&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">route&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>{&lt;span class="w"> &lt;/span>&lt;span class="nt">cluster&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">service_backend }&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">http_filters&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">envoy.filters.http.router&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">typed_config&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">&amp;#34;@type&amp;#34;: &lt;/span>&lt;span class="l">type.googleapis.com/envoy.extensions.filters.http.router.v3.Router&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">22&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">clusters&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">23&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">service_backend&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">24&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">connect_timeout&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">5s&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">25&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">type&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">STRICT_DNS&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">26&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">load_assignment&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">27&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">cluster_name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">service_backend&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">28&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">endpoints&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">29&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">lb_endpoints&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">30&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">endpoint&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>{&lt;span class="w"> &lt;/span>&lt;span class="nt">address&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>{&lt;span class="w"> &lt;/span>&lt;span class="nt">socket_address&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>{&lt;span class="w"> &lt;/span>&lt;span class="nt">address: app, port_value&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">8080&lt;/span>&lt;span class="w"> &lt;/span>}&lt;span class="w"> &lt;/span>}&lt;span class="w"> &lt;/span>}&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">31&lt;/span>&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">admin&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">32&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">address&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>{&lt;span class="w"> &lt;/span>&lt;span class="nt">socket_address&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>{&lt;span class="w"> &lt;/span>&lt;span class="nt">address: 0.0.0.0, port_value&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">9901&lt;/span>&lt;span class="w"> &lt;/span>}&lt;span class="w"> &lt;/span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>




&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 3. 驗證 + admin endpoint&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">curl http://localhost:10000 &lt;span class="c1"># proxy 路徑&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">curl http://localhost:9901/stats &lt;span class="c1"># metrics&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">curl http://localhost:9901/clusters &lt;span class="c1"># upstream health&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">curl http://localhost:9901/config_dump &lt;span class="c1"># running config&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="日常操作與決策形狀">日常操作與決策形狀&lt;/h2>
&lt;h3 id="envoy-config-結構">Envoy config 結構&lt;/h3>
&lt;p>子議題：&lt;/p></description><content:encoded><![CDATA[<p>Envoy 是 CNCF graduated 的 service proxy、承擔三個責任：cloud-native L7 + L4 proxy（HTTP/1.1 + HTTP/2 + HTTP/3 + gRPC）、xDS dynamic config（不需 reload）、observability 內建（access log / stats / tracing）。設計取捨偏向「dynamic config + advanced traffic management + filter chain extensibility」、是 Istio / Linkerd2-proxy / AWS App Mesh / Envoy Gateway 的底層實作。</p>
<p>對「service mesh data plane、API Gateway、advanced traffic management、gRPC / HTTP/2 / HTTP/3」這條路徑、Envoy 是首選。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>跑起 Envoy + 基本 reverse proxy config</li>
<li>用 xDS API 動態更新 config（不 reload）</li>
<li>配置 listener / route / cluster / filter chain</li>
<li>看懂 Envoy access log + stats + admin endpoint</li>
<li>評估 Envoy 直接用 vs 用 Istio / Envoy Gateway 抽象</li>
</ol>
<h2 id="最短路徑5-分鐘把-envoy-跑起來">最短路徑：5 分鐘把 Envoy 跑起來</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 1. 啟動 Envoy</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">docker run -d --name envoy-demo <span class="se">\
</span></span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="se"></span>  -p 9901:9901 -p 10000:10000 <span class="se">\
</span></span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="se"></span>  -v <span class="s2">&#34;</span><span class="k">$(</span><span class="nb">pwd</span><span class="k">)</span><span class="s2">/envoy.yaml:/etc/envoy/envoy.yaml:ro&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="se"></span>  envoyproxy/envoy:v1.31-latest</span></span></code></pre></div><p>Static config 範例（<code>envoy.yaml</code>）：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="nt">static_resources</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="w">  </span><span class="nt">listeners</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="w">  </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">listener_0</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="w">    </span><span class="nt">address</span><span class="p">:</span><span class="w"> </span>{<span class="w"> </span><span class="nt">socket_address</span><span class="p">:</span><span class="w"> </span>{<span class="w"> </span><span class="nt">address: 0.0.0.0, port_value</span><span class="p">:</span><span class="w"> </span><span class="m">10000</span><span class="w"> </span>}<span class="w"> </span>}<span class="w">
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="w">    </span><span class="nt">filter_chains</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="w">    </span>- <span class="nt">filters</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="w">      </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">envoy.filters.network.http_connection_manager</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="w">        </span><span class="nt">typed_config</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="w">          </span><span class="nt">&#34;@type&#34;: </span><span class="l">type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager</span><span class="w">
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="w">          </span><span class="nt">stat_prefix</span><span class="p">:</span><span class="w"> </span><span class="l">ingress_http</span><span class="w">
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="w">          </span><span class="nt">route_config</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="w">            </span><span class="nt">virtual_hosts</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="w">            </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">backend</span><span class="w">
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="w">              </span><span class="nt">domains</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&#34;*&#34;</span><span class="p">]</span><span class="w">
</span></span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="w">              </span><span class="nt">routes</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="w">              </span>- <span class="nt">match</span><span class="p">:</span><span class="w"> </span>{<span class="w"> </span><span class="nt">prefix</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;/&#34;</span><span class="w"> </span>}<span class="w">
</span></span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="w">                </span><span class="nt">route</span><span class="p">:</span><span class="w"> </span>{<span class="w"> </span><span class="nt">cluster</span><span class="p">:</span><span class="w"> </span><span class="l">service_backend }</span><span class="w">
</span></span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="w">          </span><span class="nt">http_filters</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="w">          </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">envoy.filters.http.router</span><span class="w">
</span></span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="w">            </span><span class="nt">typed_config</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="w">              </span><span class="nt">&#34;@type&#34;: </span><span class="l">type.googleapis.com/envoy.extensions.filters.http.router.v3.Router</span><span class="w">
</span></span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="w">  </span><span class="nt">clusters</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">23</span><span class="cl"><span class="w">  </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">service_backend</span><span class="w">
</span></span></span><span class="line"><span class="ln">24</span><span class="cl"><span class="w">    </span><span class="nt">connect_timeout</span><span class="p">:</span><span class="w"> </span><span class="l">5s</span><span class="w">
</span></span></span><span class="line"><span class="ln">25</span><span class="cl"><span class="w">    </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">STRICT_DNS</span><span class="w">
</span></span></span><span class="line"><span class="ln">26</span><span class="cl"><span class="w">    </span><span class="nt">load_assignment</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">27</span><span class="cl"><span class="w">      </span><span class="nt">cluster_name</span><span class="p">:</span><span class="w"> </span><span class="l">service_backend</span><span class="w">
</span></span></span><span class="line"><span class="ln">28</span><span class="cl"><span class="w">      </span><span class="nt">endpoints</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">29</span><span class="cl"><span class="w">      </span>- <span class="nt">lb_endpoints</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">30</span><span class="cl"><span class="w">        </span>- <span class="nt">endpoint</span><span class="p">:</span><span class="w"> </span>{<span class="w"> </span><span class="nt">address</span><span class="p">:</span><span class="w"> </span>{<span class="w"> </span><span class="nt">socket_address</span><span class="p">:</span><span class="w"> </span>{<span class="w"> </span><span class="nt">address: app, port_value</span><span class="p">:</span><span class="w"> </span><span class="m">8080</span><span class="w"> </span>}<span class="w"> </span>}<span class="w"> </span>}<span class="w">
</span></span></span><span class="line"><span class="ln">31</span><span class="cl"><span class="w"></span><span class="nt">admin</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">32</span><span class="cl"><span class="w">  </span><span class="nt">address</span><span class="p">:</span><span class="w"> </span>{<span class="w"> </span><span class="nt">socket_address</span><span class="p">:</span><span class="w"> </span>{<span class="w"> </span><span class="nt">address: 0.0.0.0, port_value</span><span class="p">:</span><span class="w"> </span><span class="m">9901</span><span class="w"> </span>}<span class="w"> </span>}</span></span></code></pre></div>




<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 3. 驗證 + admin endpoint</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">curl http://localhost:10000                    <span class="c1"># proxy 路徑</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">curl http://localhost:9901/stats               <span class="c1"># metrics</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">curl http://localhost:9901/clusters            <span class="c1"># upstream health</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">curl http://localhost:9901/config_dump         <span class="c1"># running config</span></span></span></code></pre></div><h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="envoy-config-結構">Envoy config 結構</h3>
<p>子議題：</p>
<ul>
<li>Listener：listen address + filter chain</li>
<li>Route：path matching + cluster routing</li>
<li>Cluster：upstream endpoint discovery + load balancing</li>
<li>Endpoint：實際 backend</li>
<li>對應 <a href="/blog/backend/05-deployment-platform/load-balancer-contract/" data-link-title="5.3 load balancer 合約" data-link-desc="整理 idle timeout、draining 與 health check">5.3 LB Contract</a></li>
</ul>
<h3 id="static-vs-dynamic-config">Static vs Dynamic config</h3>
<p>子議題：</p>
<ul>
<li>Static：YAML 寫死、適合 dev / debug</li>
<li>Dynamic（xDS）：control plane push config</li>
<li>xDS protocol：LDS / RDS / CDS / EDS / SDS</li>
<li>對應 control plane：Istio / Gloo / 自寫</li>
</ul>
<h3 id="admin-endpoint">Admin endpoint</h3>
<p>子議題：</p>
<ul>
<li>/stats / /clusters / /config_dump / /listeners / /server_info</li>
<li>runtime config（/runtime_modify）</li>
<li>對應 observability 跟 debug</li>
<li>對應指令：<code>curl admin:9901/clusters</code></li>
</ul>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<h3 id="xds-api-細節">xDS API 細節</h3>
<p>子議題：</p>
<ul>
<li>LDS / RDS / CDS / EDS / SDS / RTDS / ECDS</li>
<li>ADS（Aggregated Discovery Service）統一通道</li>
<li>Delta xDS（incremental）vs SOTW（State of the World）</li>
<li>對應案例 <a href="/blog/backend/05-deployment-platform/cases/airbnb-istio-upgrade-governance/" data-link-title="5.C7 Airbnb：Istio 升級治理" data-link-desc="service mesh 升級在大規模環境下如何保持高可用。">5.C7 Airbnb Istio</a></li>
</ul>
<h3 id="filter-chainhttp--network-filter">Filter chain（HTTP / network filter）</h3>
<p>子議題：</p>
<ul>
<li>HTTP filters：router / cors / fault / rate_limit / ext_authz / jwt_authn</li>
<li>Network filters：tcp_proxy / mongo_proxy / redis_proxy</li>
<li>自訂 filter（C++ / WebAssembly）</li>
<li>對應 <a href="/blog/backend/07-security-data-protection/" data-link-title="模組七：資安與資料保護" data-link-desc="以問題驅動方式擴充資安知識網：先定義服務環節問題，再以案例作為觸發式參考">security 模組</a>（ext_authz）</li>
</ul>
<h3 id="observability-內建">Observability 內建</h3>
<p>子議題：</p>
<ul>
<li>Access log（structured / configurable format）</li>
<li>Stats（envoy 內建 metrics）</li>
<li>Distributed tracing（Jaeger / Zipkin / Datadog / OpenTelemetry）</li>
<li>對應 <a href="/blog/backend/04-observability/" data-link-title="模組四：可觀測性平台" data-link-desc="整理 log、metric、trace、dashboard 與 alert 的後端操作實務">04 observability</a></li>
</ul>
<h3 id="envoy-gateway--emissary--gloo">Envoy Gateway / Emissary / Gloo</h3>
<p>子議題：</p>
<ul>
<li>Envoy Gateway：Gateway API native（CNCF project）</li>
<li>Emissary（前 Ambassador）：K8s ingress + API Gateway</li>
<li>Gloo：Solo.io 商業 Envoy 整合</li>
<li>選型判讀：純 K8s ingress → Envoy Gateway；商業支援 → Gloo / Emissary</li>
</ul>
<h3 id="service-mesh-data-plane">Service mesh data plane</h3>
<p>子議題：</p>
<ul>
<li>Istio：control plane + Envoy sidecar</li>
<li>Linkerd2：自家 Rust proxy（不是 Envoy）— Linkerd2-proxy</li>
<li>Cilium Service Mesh：eBPF + Envoy</li>
<li>對應 <a href="/blog/backend/05-deployment-platform/cases/airbnb-istio-upgrade-governance/" data-link-title="5.C7 Airbnb：Istio 升級治理" data-link-desc="service mesh 升級在大規模環境下如何保持高可用。">5.C7 Airbnb Istio governance</a></li>
</ul>
<h3 id="webassembly-extension">WebAssembly extension</h3>
<p>子議題：</p>
<ul>
<li>WASM filter：跨語言寫 Envoy extension（Rust / AssemblyScript / Go）</li>
<li>跟 Lua（OpenResty 模式）對比</li>
<li>適合：custom auth / rate limit / metric collection</li>
</ul>
<h3 id="advanced-traffic-management">Advanced traffic management</h3>
<p>子議題：</p>
<ul>
<li>Retry / Circuit breaker / Outlier detection</li>
<li>Timeout（connect / request / idle）</li>
<li>Traffic split（canary / blue-green / mirror）</li>
<li>Rate limit（local + global）</li>
</ul>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<h3 id="config-sync-失敗">Config sync 失敗</h3>
<p>操作原則：xDS control plane 連不上 / config 格式錯。判讀：admin /stats 看 update_failure、/config_dump 看當前 config。</p>
<h3 id="listener-config-error">Listener config error</h3>
<p>操作原則：YAML 格式錯、port 衝突、bind address 錯。判讀：startup log + admin /listeners。</p>
<h3 id="cluster-endpoint-全-unhealthy">Cluster endpoint 全 unhealthy</h3>
<p>操作原則：health check 失敗、SDS 沒提供 cert、network 不通。判讀：admin /clusters 看 endpoint state。</p>
<h3 id="circuit-breaker-trip">Circuit breaker trip</h3>
<p>操作原則：upstream 失敗率 &gt; threshold、Envoy 主動切。判讀：admin /stats 看 cb 相關 metric。</p>
<h3 id="tracing-missing-spans">Tracing missing spans</h3>
<p>操作原則：tracer config + sampler rate 設錯、context propagation 不對。對應 <a href="/blog/backend/04-observability/vendors/opentelemetry/" data-link-title="OpenTelemetry" data-link-desc="可觀測性開放標準、SDK 與 Collector">04 observability OTel</a>。</p>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>配置簡單 / 小場景</td>
          <td><a href="/blog/backend/05-deployment-platform/vendors/nginx/" data-link-title="nginx" data-link-desc="HTTP server / reverse proxy / LB / ingress">nginx</a></td>
      </tr>
      <tr>
          <td>Cloud-native auto-discovery</td>
          <td><a href="/blog/backend/05-deployment-platform/vendors/traefik/" data-link-title="Traefik" data-link-desc="Cloud-native ingress / reverse proxy、auto-discovery">Traefik</a></td>
      </tr>
      <tr>
          <td>AWS managed</td>
          <td><a href="/blog/backend/05-deployment-platform/vendors/aws-elb/" data-link-title="AWS ELB（ALB / NLB / CLB）" data-link-desc="AWS managed load balancer、ALB（L7）/ NLB（L4）/ CLB（legacy）">AWS ELB</a></td>
      </tr>
      <tr>
          <td>K8s ingress only</td>
          <td>Ingress-nginx / Envoy Gateway / Gateway API</td>
      </tr>
      <tr>
          <td>Service mesh control plane</td>
          <td>Istio / Linkerd / Consul Connect</td>
      </tr>
      <tr>
          <td>Edge proxy / CDN</td>
          <td>Cloudflare / Fastly / CloudFront</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>完整 Envoy YAML schema reference</li>
<li>xDS protocol binary format</li>
<li>各 Istio / Gloo / Emissary 細節（見各自 docs）</li>
<li>Envoy C++ filter 開發</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<h3 id="直接相關案例">直接相關案例</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>主討論議題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/05-deployment-platform/cases/airbnb-istio-upgrade-governance/" data-link-title="5.C7 Airbnb：Istio 升級治理" data-link-desc="service mesh 升級在大規模環境下如何保持高可用。">5.C7 Airbnb Istio governance</a></td>
          <td>Envoy-based service mesh 在大規模叢集的分批升級與可重播流程</td>
      </tr>
  </tbody>
</table>
<h3 id="跨-vendor-對照">跨 vendor 對照</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>對 Envoy 的對應</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/05-deployment-platform/cases/tradeshift-self-managed-k8s-to-eks/" data-link-title="5.C1 Tradeshift：self-managed Kubernetes 遷移到 EKS" data-link-desc="零停機平台遷移的分段策略案例。">5.C1 Tradeshift self-managed → EKS</a></td>
          <td>Tradeshift 選 Linkerd（非 Envoy）做切流、對照 Envoy/Istio 的取捨</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/05-deployment-platform/cases/failure-platform-cutover-without-drain/" data-link-title="5.C9 反例：平台切流未先 Draining" data-link-desc="切流時忽略連線清退造成請求錯誤與重試風暴。">5.C9 cutover without drain</a></td>
          <td>Envoy outlier detection / circuit breaker / draining listener 是回退面</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/05-deployment-platform/cases/contrast-platform-migration-by-scale/" data-link-title="5.C10 對照：規模差異下的平台遷移" data-link-desc="平台遷移策略在小中大型組織下的差異。">5.C10 規模對照</a></td>
          <td>大規模 / 複雜 traffic / 多 DC → Envoy mesh 才能撐住協同節奏</td>
      </tr>
  </tbody>
</table>
<p><strong>待補 Envoy 案例</strong>：Lyft 自家 Envoy production 案例、Stripe / Reddit 用 Envoy 邊緣案例、Envoy Gateway 早期 adopter。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游概念：<a href="/blog/backend/05-deployment-platform/load-balancer-contract/" data-link-title="5.3 load balancer 合約" data-link-desc="整理 idle timeout、draining 與 health check">5.3 LB Contract</a></li>
<li>平行 vendor：<a href="/blog/backend/05-deployment-platform/vendors/nginx/" data-link-title="nginx" data-link-desc="HTTP server / reverse proxy / LB / ingress">nginx</a>、<a href="/blog/backend/05-deployment-platform/vendors/traefik/" data-link-title="Traefik" data-link-desc="Cloud-native ingress / reverse proxy、auto-discovery">Traefik</a></li>
<li>下游能力：<a href="/blog/backend/04-observability/vendors/opentelemetry/" data-link-title="OpenTelemetry" data-link-desc="可觀測性開放標準、SDK 與 Collector">04 observability OTel</a>、<a href="/blog/backend/07-security-data-protection/" data-link-title="模組七：資安與資料保護" data-link-desc="以問題驅動方式擴充資安知識網：先定義服務環節問題，再以案例作為觸發式參考">07 security</a></li>
</ul>
]]></content:encoded></item><item><title>FireHydrant</title><link>https://tarrragon.github.io/blog/backend/08-incident-response/vendors/firehydrant/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/08-incident-response/vendors/firehydrant/</guid><description>&lt;p>FireHydrant 是 IR 平台、承擔三個責任：incident response lifecycle（declare / respond / update）、retrospective workflow + runbook automation、cross-platform integration（Slack + Microsoft Teams 雙支援）。內建 status page、後加 on-call 模組。設計取捨偏向「完整 IR + retrospective + Teams 支援」、跟 incident.io 的差異是 Teams 友善。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>FireHydrant 的核心定位是 &lt;em>service catalog 驅動的 IR platform&lt;/em> — 強調 &lt;em>service ownership + runbook automation + retrospective workflow&lt;/em> 三角支撐、而不是只把 Slack 當 chat surface。底層是 &lt;em>service catalog&lt;/em>（service / team / dependency / owner metadata）、incident 一宣告就自動關聯 affected service 跟 on-call team；上層是 &lt;em>runbook engine&lt;/em>（trigger + action DAG）跟 &lt;em>retrospective workflow&lt;/em>（template + facilitator + action item tracking）。跟 &lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/vendors/incident-io/" data-link-title="incident.io" data-link-desc="Slack-native IR 平台、整合 paging / response / retro">incident.io&lt;/a> 同層、差異在 &lt;em>Teams-native&lt;/em> 而非 Slack-only — Microsoft 365 + Salesforce-heavy enterprise 是 FireHydrant 主場。跟 &lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/vendors/pagerduty/" data-link-title="PagerDuty" data-link-desc="On-call / alerting 主流 SaaS、IR 平台演化">PagerDuty&lt;/a> 比是 &lt;em>IR + retrospective platform&lt;/em> vs &lt;em>paging platform&lt;/em>、覆蓋 lifecycle 更廣但 on-call 模組相對年輕。跟 &lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/vendors/rootly/" data-link-title="Rootly" data-link-desc="IR 自動化平台、no-code workflow &amp;#43; AI investigation、Slack-native &amp;#43; 200&amp;#43; integration">Rootly&lt;/a> 比走 &lt;em>catalog-first&lt;/em> 而非 &lt;em>AI / no-code first&lt;/em>。&lt;/p>
&lt;p>關鍵張力：&lt;em>service catalog 完整度&lt;/em> ↔ &lt;em>runbook automation 黑箱&lt;/em> 是 FireHydrant 客戶最大的 trade-off。catalog 沒維護好、runbook 自動 page 錯 team、retrospective owner 找不到；catalog 維護成本又會被視為 platform team 負擔。要看清楚自己 &lt;em>願意投多少 catalog 治理換多少 IR 自動化&lt;/em>。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;ol>
&lt;li>整合 FireHydrant 到 Slack / Teams&lt;/li>
&lt;li>配置 incident lifecycle + severity matrix&lt;/li>
&lt;li>用 Runbook automation 自動化 standard response&lt;/li>
&lt;li>用 Retrospective facilitator 跑復盤&lt;/li>
&lt;li>評估 FireHydrant vs incident.io / Rootly&lt;/li>
&lt;/ol>
&lt;h2 id="最短判讀路徑">最短判讀路徑&lt;/h2>
&lt;p>判斷 FireHydrant deployment 是否健康、最少看四件事：&lt;/p></description><content:encoded><![CDATA[<p>FireHydrant 是 IR 平台、承擔三個責任：incident response lifecycle（declare / respond / update）、retrospective workflow + runbook automation、cross-platform integration（Slack + Microsoft Teams 雙支援）。內建 status page、後加 on-call 模組。設計取捨偏向「完整 IR + retrospective + Teams 支援」、跟 incident.io 的差異是 Teams 友善。</p>
<h2 id="服務定位">服務定位</h2>
<p>FireHydrant 的核心定位是 <em>service catalog 驅動的 IR platform</em> — 強調 <em>service ownership + runbook automation + retrospective workflow</em> 三角支撐、而不是只把 Slack 當 chat surface。底層是 <em>service catalog</em>（service / team / dependency / owner metadata）、incident 一宣告就自動關聯 affected service 跟 on-call team；上層是 <em>runbook engine</em>（trigger + action DAG）跟 <em>retrospective workflow</em>（template + facilitator + action item tracking）。跟 <a href="/blog/backend/08-incident-response/vendors/incident-io/" data-link-title="incident.io" data-link-desc="Slack-native IR 平台、整合 paging / response / retro">incident.io</a> 同層、差異在 <em>Teams-native</em> 而非 Slack-only — Microsoft 365 + Salesforce-heavy enterprise 是 FireHydrant 主場。跟 <a href="/blog/backend/08-incident-response/vendors/pagerduty/" data-link-title="PagerDuty" data-link-desc="On-call / alerting 主流 SaaS、IR 平台演化">PagerDuty</a> 比是 <em>IR + retrospective platform</em> vs <em>paging platform</em>、覆蓋 lifecycle 更廣但 on-call 模組相對年輕。跟 <a href="/blog/backend/08-incident-response/vendors/rootly/" data-link-title="Rootly" data-link-desc="IR 自動化平台、no-code workflow &#43; AI investigation、Slack-native &#43; 200&#43; integration">Rootly</a> 比走 <em>catalog-first</em> 而非 <em>AI / no-code first</em>。</p>
<p>關鍵張力：<em>service catalog 完整度</em> ↔ <em>runbook automation 黑箱</em> 是 FireHydrant 客戶最大的 trade-off。catalog 沒維護好、runbook 自動 page 錯 team、retrospective owner 找不到；catalog 維護成本又會被視為 platform team 負擔。要看清楚自己 <em>願意投多少 catalog 治理換多少 IR 自動化</em>。</p>
<h2 id="本章目標">本章目標</h2>
<ol>
<li>整合 FireHydrant 到 Slack / Teams</li>
<li>配置 incident lifecycle + severity matrix</li>
<li>用 Runbook automation 自動化 standard response</li>
<li>用 Retrospective facilitator 跑復盤</li>
<li>評估 FireHydrant vs incident.io / Rootly</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 FireHydrant deployment 是否健康、最少看四件事：</p>
<ul>
<li><strong>Runbook automation 範圍</strong>：runbook 是否走版控（API / Terraform Provider）、trigger 條件是否有 staging dry-run、high-impact action（自動 page exec / 自動發 customer notification）是否走 <em>approval gate</em> 而非 fire-and-forget</li>
<li><strong>Service catalog 完整度</strong>：service / team / dependency / owner 是否齊全、stale entry 是否有 review cadence、incident declare 時 affected service dropdown 是否能立即定位、catalog 是否跟 <a href="/blog/backend/09-performance-capacity/" data-link-title="模組九：效能工程與容量規劃" data-link-desc="把『目前配置能撐多少、要加多少機器』變成可量化、可驗證、可改進的工程流程">ServiceNow CMDB</a> / Backstage / Salesforce 同步</li>
<li><strong>Retrospective workflow</strong>：incident close 後是否自動觸發 retrospective、facilitator 是否指定、action item 是否寫回 Jira / Linear 並 track close-rate、template 是否區分 sev1 / sev2 不同深度</li>
<li><strong>SSO + audit</strong>：SCIM provisioning 是否跟 IdP 同步、admin / responder / viewer 三層角色是否區分、audit log 是否 export 到 <a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> 或 SIEM</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/08-incident-response/drills-and-oncall-readiness/" data-link-title="8.6 演練與值班能力建設" data-link-desc="用演練與值班訓練提升事故反應品質">Drills and On-call Readiness</a> 邊界的待補項目。</p>
<h2 id="最短路徑">最短路徑</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 1. 註冊 + install Slack / Teams app</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># 2. 配置 severity matrix / roles</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="c1"># 3. Declare test incident</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 4. 跑 retrospective workflow</span></span></span></code></pre></div><h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="incident-lifecycle">Incident lifecycle</h3>
<p>子議題：</p>
<ul>
<li>Severity matrix（impact × urgency）</li>
<li>Status workflow（detected → investigating → identified → monitoring → resolved）</li>
<li>Role：commander / scribe / SME</li>
</ul>
<h3 id="runbook-automation--retrospective">Runbook automation + Retrospective</h3>
<p>子議題：</p>
<ul>
<li>預定 runbook（auto page / 建 Jira / open Zoom）</li>
<li>Trigger condition</li>
<li>Retrospective template + facilitator role + action items</li>
</ul>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>FireHydrant</th>
          <th>incident.io</th>
          <th>PagerDuty</th>
          <th>Rootly</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Chat 主場</td>
          <td>Slack + Teams 雙支援</td>
          <td>Slack-first（Teams 後加）</td>
          <td>Slack / Teams（chat 非核心）</td>
          <td>Slack-first</td>
      </tr>
      <tr>
          <td>核心抽象</td>
          <td>Service catalog + runbook</td>
          <td>Incident workflow + AI assist</td>
          <td>On-call schedule + paging</td>
          <td>No-code workflow + AI</td>
      </tr>
      <tr>
          <td>Retrospective</td>
          <td>內建 facilitator + template + action 追蹤</td>
          <td>內建、AI assist 草稿</td>
          <td>弱、靠 integration</td>
          <td>內建、AI summary</td>
      </tr>
      <tr>
          <td>Catalog</td>
          <td>一級概念、service / team / dependency</td>
          <td>有 catalog、深度較淺</td>
          <td>Service 概念存在、不強調 ownership</td>
          <td>有 catalog、強調 no-code 編輯</td>
      </tr>
      <tr>
          <td>On-call</td>
          <td>後加模組、相對年輕</td>
          <td>內建、跟 incident workflow 整合</td>
          <td>業界最成熟</td>
          <td>內建</td>
      </tr>
      <tr>
          <td>整合主場</td>
          <td>ServiceNow / Salesforce / Microsoft</td>
          <td>Linear / Notion / GitHub</td>
          <td>廣泛、paging-centric</td>
          <td>Jira / Slack</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>Enterprise + Teams + service ownership-heavy</td>
          <td>Slack-native + 高速 startup</td>
          <td>Paging-first + 已有 IR tooling</td>
          <td>No-code / AI-forward + 中型團隊</td>
      </tr>
  </tbody>
</table>
<p>選 FireHydrant 的核心訴求：<em>service ownership 是組織一級概念</em>（platform team / SRE 已維護 catalog）、<em>Microsoft 365 / Teams 是預設辦公 surface</em>、<em>retrospective + action item 追蹤要 first-class</em>。Slack-only + startup 速度優先走 incident.io；paging 是核心走 PagerDuty。</p>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<h3 id="status-page-內建">Status page 內建</h3>
<p>子議題：不需另接 Statuspage / Instatus、Component / incident sync、Subscriber notification</p>
<h3 id="cross-platformslack--teams">Cross-platform（Slack + Teams）</h3>
<p>子議題：同帳號跨兩平台、Microsoft Teams enterprise 需求</p>
<h3 id="on-call-模組--service-catalog">On-call 模組 + Service catalog</h3>
<p>子議題：後加 module、service / team / dependency metadata 跟 incident 自動關聯</p>
<h3 id="runbook-automationtrigger--action-dag">Runbook automation（trigger + action DAG）</h3>
<p>Runbook 是 trigger（severity 升級 / service 標籤 / 時間 elapsed）+ action（page team / 建 Zoom / 建 Jira / 發 customer notification / 更新 status page）的 DAG。production 設計要回答：<em>哪些 action 可以 fire-and-forget</em>（建 Zoom / 建 ticket）、<em>哪些要 approval gate</em>（發 customer notification / 自動 page exec）、<em>失敗回退是什麼</em>（action 失敗時 commander 是否會收到通知、還是默默 skip）。Runbook 走 API / Terraform Provider 版控、不在 console 直改 production。</p>
<h3 id="service-catalog--dependency">Service catalog + dependency</h3>
<p>Catalog 一級欄位：service / owning team / on-call rotation / upstream dependency / downstream consumer / tier（critical / standard / experimental）。意義是 incident declare 時 <em>affected service</em> 一選、systems team + on-call + 通報範圍自動推導。catalog stale 是最大失敗模式 — team 重組沒同步、deprecated service 沒下架、ownership 落在離職員工身上。對應 <a href="/blog/backend/09-performance-capacity/" data-link-title="模組九：效能工程與容量規劃" data-link-desc="把『目前配置能撐多少、要加多少機器』變成可量化、可驗證、可改進的工程流程">9 IT asset 模組</a> 的 CMDB / inventory 治理原則。</p>
<h3 id="servicenow--salesforce-整合">ServiceNow / Salesforce 整合</h3>
<p>FireHydrant 的 Microsoft / Salesforce 生態整合是 differentiator：incident 自動建 ServiceNow ticket（CMDB CI 關聯）、Salesforce case escalate 自動 declare incident、Customer Success 在 Salesforce 看到 affected account list。enterprise customer 常見部署模式。</p>
<h3 id="signalsalerting-layer">Signals（alerting layer）</h3>
<p>FireHydrant Signals 是 alerting / paging layer、跟 PagerDuty 直接對打 — alert source（<a href="/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &#43; CSPM &#43; CWS &#43; AAP &#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog</a> / Prometheus / <a href="/blog/backend/07-security-data-protection/" data-link-title="模組七：資安與資料保護" data-link-desc="以問題驅動方式擴充資安知識網：先定義服務環節問題，再以案例作為觸發式參考">Sentry</a> etc）→ Signals → on-call rotation。意義是 <em>paging 不再需要外接 PagerDuty</em>、FireHydrant 一站涵蓋 alert → incident → retrospective。但成熟度仍年輕、PagerDuty paging 細節（escalation policy / override / global event routing）仍有差距。</p>
<h3 id="ai-features">AI features</h3>
<p>FireHydrant 後加 AI assist：incident summary 草稿、retrospective draft、similar incident suggestion。定位是 <em>assist</em>、不取代 commander / facilitator 判斷。production 用法限制在 <em>草稿 + human review</em>、不自動 publish 對外 communication。</p>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<ul>
<li><strong>Severity matrix 不一致</strong>：跨 team 定義不同、用 catalog default + onboarding</li>
<li><strong>Runbook 沒觸發</strong>：trigger 不滿足 / integration token 失效</li>
<li><strong>Status page 不同步</strong>：自動 / 手動 sync 配置錯</li>
<li><strong>Retrospective 沒人做</strong>：close 後沒 prompt / facilitator 沒指派</li>
<li><strong>Service catalog stale</strong>：team 重組沒同步、ownership 落在離職員工身上 — 設 quarterly review cadence、catalog 走 PR + owner attestation、跟 IdP / HR system join 偵測 orphan ownership</li>
<li><strong>Runbook action 黑箱 fire-and-forget</strong>：自動發 customer notification 結果發錯客群、自動 page exec 結果半夜誤叫 — high-impact action 走 approval gate、failure path 要顯式通知 commander、不能默默 skip</li>
<li><strong>SSO sync drift</strong>：SCIM 沒同步離職 user、admin 角色沒回收 — SCIM provisioning 必開、admin 角色走 break-glass、audit log export 到 SIEM 對賬</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Slack-first</td>
          <td><a href="/blog/backend/08-incident-response/vendors/incident-io/" data-link-title="incident.io" data-link-desc="Slack-native IR 平台、整合 paging / response / retro">incident.io</a></td>
      </tr>
      <tr>
          <td>No-code / AI</td>
          <td><a href="/blog/backend/08-incident-response/vendors/rootly/" data-link-title="Rootly" data-link-desc="IR 自動化平台、no-code workflow &#43; AI investigation、Slack-native &#43; 200&#43; integration">Rootly</a></td>
      </tr>
      <tr>
          <td>Paging-first</td>
          <td><a href="/blog/backend/08-incident-response/vendors/pagerduty/" data-link-title="PagerDuty" data-link-desc="On-call / alerting 主流 SaaS、IR 平台演化">PagerDuty</a></td>
      </tr>
      <tr>
          <td>Atlassian 套件</td>
          <td><a href="/blog/backend/08-incident-response/vendors/opsgenie/" data-link-title="Opsgenie" data-link-desc="Atlassian on-call、跟 Jira / Statuspage 套件整合、JSM Premium migration 議題">Opsgenie</a> + JSM</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>各 integration 完整 setup / Pricing / Teams workflow 細節</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p><strong>FireHydrant 偏向 Microsoft Teams + Jira 生態的 IR 平台</strong>：本案例庫尚無直接揭露 FireHydrant 使用細節的事故；可參照的閱讀脈絡是「企業套件 + 跨產品 IR」與「service ownership-heavy enterprise 跨產品依賴」的事故。</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>對應主題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/08-incident-response/cases/microsoft-365/" data-link-title="Microsoft 365" data-link-desc="Microsoft 365 SaaS 套件事故與企業客戶影響">Microsoft 365 cases</a></td>
          <td>Teams + 套件級事故的 IR 協作對照、ServiceNow ticket join 場景</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/08-incident-response/cases/azure-ad/" data-link-title="Azure AD / Entra ID" data-link-desc="Microsoft Identity 控制面失效與 cascading 影響">Azure AD cases</a></td>
          <td>身份控制面事故的跨產品依賴對照、SSO drift 跟 service catalog ownership 失準對應</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/08-incident-response/cases/atlassian/" data-link-title="Atlassian" data-link-desc="Atlassian 多租戶事故時間線與架構脈絡">Atlassian cases</a></td>
          <td>Jira / Confluence 生態事故、retrospective action item 寫回流程的失敗模式</td>
      </tr>
  </tbody>
</table>
<p>待補 candidate：Snyk / Vercel / 大型 Microsoft 生態 customer 公開 story。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/08-incident-response/drills-and-oncall-readiness/" data-link-title="8.6 演練與值班能力建設" data-link-desc="用演練與值班訓練提升事故反應品質">Drills and On-call Readiness</a></li>
<li>平行：<a href="/blog/backend/08-incident-response/vendors/incident-io/" data-link-title="incident.io" data-link-desc="Slack-native IR 平台、整合 paging / response / retro">incident.io</a>、<a href="/blog/backend/08-incident-response/vendors/rootly/" data-link-title="Rootly" data-link-desc="IR 自動化平台、no-code workflow &#43; AI investigation、Slack-native &#43; 200&#43; integration">Rootly</a></li>
<li>下游：<a href="/blog/backend/08-incident-response/incident-evidence-write-back/" data-link-title="8.22 Incident Evidence Write-back" data-link-desc="把事故證據、決策與復盤結論回寫到 observability、reliability 與 runbook">8.22 Incident Evidence Write-back</a></li>
</ul>
]]></content:encoded></item><item><title>KeyDB</title><link>https://tarrragon.github.io/blog/backend/02-cache-redis/vendors/keydb/</link><pubDate>Tue, 16 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/02-cache-redis/vendors/keydb/</guid><description>&lt;p>KeyDB 是 Redis 的 multi-threaded fork、承擔三個責任：把 Redis 的命令執行從單執行緒改成多執行緒（不只 I/O、連命令處理都多核）、提供 active-active 多主複製（兩個 master 互相同步、都可寫）、維持 Redis protocol 相容（drop-in 替換）。設計取捨偏向「沿用 Redis 生態 + 單實例榨多核 + 多主寫入」、是 Redis 單執行緒撞牆但又不想重寫 client 的中間選項。&lt;/p>
&lt;p>對「單 key 極熱、Redis Cluster 切不開、需要單實例多執行緒撐單 partition」這條路徑、KeyDB 是值得評估的 fork。&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/snap-gcp-keydb-cross-cloud/" data-link-title="9.C35 Snap：GCP &amp;#43; KeyDB 在 multi-cloud 架構下的低延遲快取" data-link-desc="Snap 用 GCP 上的 KeyDB cluster 減少跨 cloud cache 延遲、用 TPU 訓練廣告推薦模型">Snap 在 GCP 上用 KeyDB&lt;/a> 是這條路線最大的公開採用者——但要注意該案例的主因是 multi-cloud 架構下的 cross-cloud latency 治理（把 cache 跟 application 放同一個 cloud），KeyDB 的 multi-threaded 單實例吞吐是附帶優勢、不是 Snap 採用的主要驅動。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>跑起 KeyDB、用 redis-cli 驗證 protocol 相容&lt;/li>
&lt;li>評估 multi-threaded 命令執行跟 Redis I/O threads 的差異&lt;/li>
&lt;li>判斷 active-active 多主複製適用與衝突風險&lt;/li>
&lt;li>評估 KeyDB on FLASH 對大 dataset 的成本意義&lt;/li>
&lt;li>區分 KeyDB 跟 DragonflyDB / Redis Cluster 的選用判讀，並評估 Snap 收購後的治理風險&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑5-分鐘把-keydb-跑起來">最短路徑：5 分鐘把 KeyDB 跑起來&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 1. 啟動 KeyDB（--server-threads 開多執行緒、命令執行也多核）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">docker run -d --name keydb -p 6379:6379 &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> eqalpha/keydb keydb-server --server-threads &lt;span class="m">4&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">&lt;span class="c1"># 2. 用 redis-cli 驗證（KeyDB 100% Redis protocol 相容）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">redis-cli SET foo bar &lt;span class="c1"># → OK&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">redis-cli GET foo &lt;span class="c1"># → bar&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="c1"># 3. 確認版本（KeyDB 回報 redis_version、client 以此判斷相容性）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">redis-cli INFO server &lt;span class="p">|&lt;/span> grep -E &lt;span class="s2">&amp;#34;redis_version|redis_mode&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">&lt;span class="c1"># redis_version:6.3.4 ← KeyDB 的版本方案、client library 以此協商相容&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">&lt;span class="c1"># redis_mode:standalone&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>實機驗證於 eqalpha/keydb image、最後檢查日 2026-06-16；&lt;code>--server-threads&lt;/code> 是啟動參數（不在 &lt;code>CONFIG GET&lt;/code> 內、改值要重啟）。多主複製見&lt;a href="#active-active-%e5%a4%9a%e4%b8%bb%e8%a4%87%e8%a3%bd">進階主題&lt;/a>。&lt;/p>
&lt;h2 id="日常操作與決策形狀">日常操作與決策形狀&lt;/h2>
&lt;h3 id="cli-與-client-api">CLI 與 client API&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>直接用 redis-cli / 所有 Redis client library（KeyDB 維持 Redis protocol）&lt;/li>
&lt;li>&lt;code>--server-threads N&lt;/code> 設命令執行的執行緒數、對齊 CPU 核數&lt;/li>
&lt;li>&lt;code>INFO server&lt;/code> 確認 redis_version（KeyDB 的版本對應 Redis 哪個 base）&lt;/li>
&lt;/ul>
&lt;h3 id="multi-threaded-命令執行">Multi-threaded 命令執行&lt;/h3>
&lt;p>KeyDB 跟 Redis I/O threads 的差異是核心賣點。子議題：&lt;/p></description><content:encoded><![CDATA[<p>KeyDB 是 Redis 的 multi-threaded fork、承擔三個責任：把 Redis 的命令執行從單執行緒改成多執行緒（不只 I/O、連命令處理都多核）、提供 active-active 多主複製（兩個 master 互相同步、都可寫）、維持 Redis protocol 相容（drop-in 替換）。設計取捨偏向「沿用 Redis 生態 + 單實例榨多核 + 多主寫入」、是 Redis 單執行緒撞牆但又不想重寫 client 的中間選項。</p>
<p>對「單 key 極熱、Redis Cluster 切不開、需要單實例多執行緒撐單 partition」這條路徑、KeyDB 是值得評估的 fork。<a href="/blog/backend/09-performance-capacity/cases/snap-gcp-keydb-cross-cloud/" data-link-title="9.C35 Snap：GCP &#43; KeyDB 在 multi-cloud 架構下的低延遲快取" data-link-desc="Snap 用 GCP 上的 KeyDB cluster 減少跨 cloud cache 延遲、用 TPU 訓練廣告推薦模型">Snap 在 GCP 上用 KeyDB</a> 是這條路線最大的公開採用者——但要注意該案例的主因是 multi-cloud 架構下的 cross-cloud latency 治理（把 cache 跟 application 放同一個 cloud），KeyDB 的 multi-threaded 單實例吞吐是附帶優勢、不是 Snap 採用的主要驅動。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>跑起 KeyDB、用 redis-cli 驗證 protocol 相容</li>
<li>評估 multi-threaded 命令執行跟 Redis I/O threads 的差異</li>
<li>判斷 active-active 多主複製適用與衝突風險</li>
<li>評估 KeyDB on FLASH 對大 dataset 的成本意義</li>
<li>區分 KeyDB 跟 DragonflyDB / Redis Cluster 的選用判讀，並評估 Snap 收購後的治理風險</li>
</ol>
<h2 id="最短路徑5-分鐘把-keydb-跑起來">最短路徑：5 分鐘把 KeyDB 跑起來</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># 1. 啟動 KeyDB（--server-threads 開多執行緒、命令執行也多核）</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">docker run -d --name keydb -p 6379:6379 <span class="se">\
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="se"></span>  eqalpha/keydb keydb-server --server-threads <span class="m">4</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="c1"># 2. 用 redis-cli 驗證（KeyDB 100% Redis protocol 相容）</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">redis-cli SET foo bar    <span class="c1"># → OK</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">redis-cli GET foo        <span class="c1"># → bar</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="c1"># 3. 確認版本（KeyDB 回報 redis_version、client 以此判斷相容性）</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">redis-cli INFO server <span class="p">|</span> grep -E <span class="s2">&#34;redis_version|redis_mode&#34;</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="c1"># redis_version:6.3.4    ← KeyDB 的版本方案、client library 以此協商相容</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="c1"># redis_mode:standalone</span></span></span></code></pre></div><p>實機驗證於 eqalpha/keydb image、最後檢查日 2026-06-16；<code>--server-threads</code> 是啟動參數（不在 <code>CONFIG GET</code> 內、改值要重啟）。多主複製見<a href="#active-active-%e5%a4%9a%e4%b8%bb%e8%a4%87%e8%a3%bd">進階主題</a>。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="cli-與-client-api">CLI 與 client API</h3>
<p>子議題：</p>
<ul>
<li>直接用 redis-cli / 所有 Redis client library（KeyDB 維持 Redis protocol）</li>
<li><code>--server-threads N</code> 設命令執行的執行緒數、對齊 CPU 核數</li>
<li><code>INFO server</code> 確認 redis_version（KeyDB 的版本對應 Redis 哪個 base）</li>
</ul>
<h3 id="multi-threaded-命令執行">Multi-threaded 命令執行</h3>
<p>KeyDB 跟 Redis I/O threads 的差異是核心賣點。子議題：</p>
<ul>
<li>Redis 6+ 的 I/O threads 只分擔 socket 讀寫、命令仍在 main thread；KeyDB 連命令執行都多執行緒</li>
<li><code>--server-threads</code> 對齊核數、單實例吞吐隨核數擴展</li>
<li>多執行緒下單 key 的並發保護由 KeyDB 內部處理、application 端語意不變</li>
</ul>
<h3 id="active-active-多主複製">Active-active 多主複製</h3>
<p>子議題：</p>
<ul>
<li>兩個（含以上）KeyDB master 互相複製、都可接受寫入</li>
<li>衝突解決用 last-write-wins（依時間戳）、不是強一致</li>
<li>適合跨 AZ / 跨 region 的讀寫就近、但要接受最終一致與衝突覆蓋風險</li>
</ul>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<h3 id="active-active-多主複製-1">Active-active 多主複製</h3>
<p>子議題：</p>
<ul>
<li><code>replicaof</code> + <code>active-replica yes</code> 開雙向複製</li>
<li>衝突語意：同 key 並發寫入、last-write-wins、可能丟其中一側的寫入</li>
<li>適用：跨區讀寫就近、可容忍最終一致的 cache；不適用：需要強一致的 counter / lock</li>
</ul>
<h3 id="keydb-on-flash">KeyDB on FLASH</h3>
<p>子議題：</p>
<ul>
<li>把冷資料放 SSD、熱資料留記憶體、降低大 dataset 的記憶體成本</li>
<li>對應 <a href="/blog/backend/02-cache-redis/cases/meta-cachelib-kangaroo-tiered-cache/" data-link-title="2.C4 Meta：CacheLib / Kangaroo 分層快取" data-link-desc="快取從 DRAM-only 轉向分層快取架構的實務案例。">Meta CacheLib + Kangaroo</a> 的 DRAM + flash 分層思路</li>
<li>代價：FLASH 路徑延遲高於純記憶體、適合冷熱分明的 workload</li>
</ul>
<h3 id="跟-dragonflydb--garnet-的對比">跟 DragonflyDB / Garnet 的對比</h3>
<p>子議題：</p>
<ul>
<li>KeyDB：Redis fork（沿用 Redis code base、相容度高、base 版本較舊）</li>
<li>DragonflyDB：C++ 從零重寫（架構更激進、shared-nothing、相容核心但非 fork）</li>
<li>Garnet（Microsoft）：研究型高吞吐 store、生態淺</li>
<li>對應 <a href="/blog/backend/02-cache-redis/vendors/dragonflydb/shared-nothing-multicore-architecture/" data-link-title="DragonflyDB shared-nothing 多核架構：用 scale-up 取代 Redis Cluster" data-link-desc="Redis 要靠 Cluster 分片才能用滿一台多核機器，DragonflyDB 賭的是相反方向——單一進程 thread-per-core、shared-nothing、把單機推到 Redis 要好幾個 shard 才達到的規模。本文展開 thread-per-core 與 dashtable 的架構、fork-less snapshot、5 個把架構假設寫成 production 事故的踩坑，以及 scale-up 撞牆該回 Cluster 的邊界">DragonflyDB 多核架構 deep article</a> 的 fork vs 重寫光譜</li>
</ul>
<h3 id="治理風險snap-收購後">治理風險（Snap 收購後）</h3>
<p>子議題：</p>
<ul>
<li>KeyDB 公司 2022 年被 Snap 收購、開源版本的後續投入與 roadmap 不確定</li>
<li>評估採用前確認專案活躍度（commit 頻率、release cadence）</li>
<li>對長期依賴敏感的場景、Redis fork 光譜上的 <a href="/blog/backend/02-cache-redis/vendors/valkey/" data-link-title="Valkey" data-link-desc="Redis fork、Linux Foundation 託管、BSD 授權">Valkey</a>（Linux Foundation 治理）治理更穩</li>
</ul>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<h3 id="多執行緒下吞吐沒提升">多執行緒下吞吐沒提升</h3>
<p>操作原則：先確認 <code>--server-threads</code> 對齊 CPU 核數、再看是否 CPU 密集 workload。判讀：thread &lt; core → 沒用滿多核；單 key 極熱 → 仍受單 partition 限制。</p>
<h3 id="active-active-衝突丟資料">Active-active 衝突丟資料</h3>
<p>操作原則：last-write-wins 下並發寫同 key 會覆蓋。判讀：跨區同 key 高頻寫入要改設計（key 分區到不同 master）、或改用強一致儲存。</p>
<h3 id="protocol-相容問題">Protocol 相容問題</h3>
<p>操作原則：KeyDB base 版本較舊（redis_version 6.x），用到 Redis 7+ 新命令會不支援。判讀：<code>INFO server</code> 確認 base 版本、對照 application 用到的命令。</p>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>要最新 Redis 功能 / 治理穩定</td>
          <td><a href="/blog/backend/02-cache-redis/vendors/valkey/" data-link-title="Valkey" data-link-desc="Redis fork、Linux Foundation 託管、BSD 授權">Valkey</a>（Linux Foundation、跟上 Redis）</td>
      </tr>
      <tr>
          <td>更激進的多核 / 記憶體效率</td>
          <td><a href="/blog/backend/02-cache-redis/vendors/dragonflydb/" data-link-title="DragonflyDB" data-link-desc="高效能 Redis / Memcached 相容替代、多核架構">DragonflyDB</a>（重寫、shared-nothing）</td>
      </tr>
      <tr>
          <td>需要 Redis Cluster sharding</td>
          <td><a href="/blog/backend/02-cache-redis/vendors/redis/" data-link-title="Redis" data-link-desc="OSS in-memory data structure store、cache 主流">Redis</a> / Valkey Cluster</td>
      </tr>
      <tr>
          <td>純 KV、極簡運維</td>
          <td><a href="/blog/backend/02-cache-redis/vendors/memcached/" data-link-title="Memcached" data-link-desc="純記憶體 key-value cache、無持久化">Memcached</a></td>
      </tr>
      <tr>
          <td>AWS managed</td>
          <td><a href="/blog/backend/02-cache-redis/vendors/aws-elasticache/" data-link-title="AWS ElastiCache" data-link-desc="AWS managed Redis / Valkey / Memcached">AWS ElastiCache</a>（無 managed KeyDB）</td>
      </tr>
      <tr>
          <td>需要強一致 + durability</td>
          <td>AWS MemoryDB</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>KeyDB 完整 command reference（沿用 Redis、查 redis.io/commands）</li>
<li>各語言 client API（用 Redis client 即可）</li>
<li>KeyDB on FLASH 詳細調參</li>
<li>Active-replication 內部複製協定細節</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<h3 id="直接相關案例">直接相關案例</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>對 KeyDB 的對應</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/cases/snap-gcp-keydb-cross-cloud/" data-link-title="9.C35 Snap：GCP &#43; KeyDB 在 multi-cloud 架構下的低延遲快取" data-link-desc="Snap 用 GCP 上的 KeyDB cluster 減少跨 cloud cache 延遲、用 TPU 訓練廣告推薦模型">9.C35 Snap KeyDB cross-cloud</a></td>
          <td>Snap 在 GCP 部署 KeyDB cluster、主因是 multi-cloud 的 cross-cloud latency 治理（cache 與 application 共置同 cloud）；9.C35 另記 KeyDB multi-threaded「單實例 throughput 提升 5-10x」（通則、依 workload）</td>
      </tr>
  </tbody>
</table>
<p><strong>待補 KeyDB-specific 案例</strong>：Snap 收購後的公開技術分享、KeyDB on FLASH 的 production 成本案例、active-active 多主複製的跨區衝突治理實例。</p>
<h3 id="跨-vendor-對照">跨 vendor 對照</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>對 KeyDB 的對應</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/meta-cachelib-kangaroo-tiered-cache/" data-link-title="2.C4 Meta：CacheLib / Kangaroo 分層快取" data-link-desc="快取從 DRAM-only 轉向分層快取架構的實務案例。">2.C4 Meta CacheLib + Kangaroo</a></td>
          <td>KeyDB on FLASH 對應 DRAM + flash 分層的成本決策</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/failure-cache-stampede-rollout-regression/" data-link-title="2.C9 反例：快取切換引發 Stampede 回歸" data-link-desc="快取策略切換若缺乏保護，會導致回源壓力與錯誤率連鎖上升。">2.C9 Cache Stampede</a></td>
          <td>TTL jitter / singleflight 通用、KeyDB 多執行緒不消除 stampede 風險</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/contrast-cache-strategy-by-scale/" data-link-title="2.C10 對照：規模差異下的快取策略" data-link-desc="同一快取策略在小中大型服務下會產生不同風險。">2.C10 規模對照</a></td>
          <td>KeyDB 是「單實例多核撐大」的選項、介於 Redis Cluster 與 DragonflyDB 之間</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>deep article：<a href="/blog/backend/02-cache-redis/vendors/keydb/active-active-replication/" data-link-title="KeyDB active-active 多主複製：last-write-wins 會默默吃掉哪一筆寫入" data-link-desc="KeyDB 的 active-active 讓兩個 master 都能寫、互相同步，聽起來解決了跨區寫入的所有問題——直到兩邊同時寫同一個 key，last-write-wins 默默丟掉其中一筆。本文展開 active-active 的複製機制與衝突語意、實機驗證雙向同步、5 個把多主複製寫成資料遺失與迴圈的 production 踩坑，以及哪些資料能放 active-active、哪些不能的邊界">KeyDB active-active 多主複製</a>（last-write-wins 衝突與跨區寫入）</li>
<li>上游概念：<a href="/blog/backend/02-cache-redis/high-concurrency-access/" data-link-title="2.1 高併發下的 Redis 讀寫邊界" data-link-desc="說明高併發服務如何共用 Redis client、控制 pipeline 與避免 cache stampede">2.6 high concurrency</a>（單執行緒邊界的四個選項）</li>
<li>平行 vendor：<a href="/blog/backend/02-cache-redis/vendors/dragonflydb/" data-link-title="DragonflyDB" data-link-desc="高效能 Redis / Memcached 相容替代、多核架構">DragonflyDB</a>、<a href="/blog/backend/02-cache-redis/vendors/valkey/" data-link-title="Valkey" data-link-desc="Redis fork、Linux Foundation 託管、BSD 授權">Valkey</a>、<a href="/blog/backend/02-cache-redis/vendors/redis/" data-link-title="Redis" data-link-desc="OSS in-memory data structure store、cache 主流">Redis</a></li>
<li>下游能力：<a href="/blog/backend/02-cache-redis/cache-copy-freshness-boundary/" data-link-title="2.7 Cache Copy Boundary 與 Freshness" data-link-desc="說明快取何時只是可重建副本，何時會影響交易、權限或配額正確性。">2.7 cache copy boundary</a>（跨區資料引力）</li>
<li>回退路徑：<a href="/blog/backend/02-cache-redis/vendors/keydb/migrate-to-redis/" data-link-title="KeyDB → Redis / Valkey：從多線程 fork 回歸主線的遷移路徑" data-link-desc="從 KeyDB 遷回 Redis 或 Valkey，處理 active-active replication 拆除、多線程 → 單線程效能差異、FLASH storage 移除與 Sentinel/Cluster 對齊">KeyDB → Redis/Valkey</a></li>
</ul>
]]></content:encoded></item><item><title>Azure Key Vault</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/azure-key-vault/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/azure-key-vault/</guid><description>&lt;p>Azure Key Vault 是 Azure 平台把 &lt;em>secret&lt;/em>、&lt;em>cryptographic key&lt;/em>、&lt;em>X.509 certificate&lt;/em> 三類資產 &lt;em>合進同一個 service&lt;/em> 的設計。Vault instance 本身是 first-class ARM resource、有 FQDN endpoint（&lt;code>https://&amp;lt;vault-name&amp;gt;.vault.azure.net&lt;/code>）、跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/azure-rbac/" data-link-title="Azure RBAC &amp;#43; Entra ID" data-link-desc="Azure 雙層身份/權限體系、Entra ID（IdP）&amp;#43; Azure RBAC（resource permission）、Conditional Access、PIM、Managed Identity">Azure RBAC&lt;/a> 跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/azure-rbac/" data-link-title="Azure RBAC &amp;#43; Entra ID" data-link-desc="Azure 雙層身份/權限體系、Entra ID（IdP）&amp;#43; Azure RBAC（resource permission）、Conditional Access、PIM、Managed Identity">Entra ID&lt;/a> Managed Identity 深度整合 — 每個 Vault 自己一個邊界、區別於 region-wide service 的模型。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Azure Key Vault 的核心定位是 &lt;em>三合一 secret + key + cert service 加 Azure-native secret-less 取用&lt;/em>。AWS 是 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-secrets-manager/" data-link-title="AWS Secrets Manager" data-link-desc="AWS 原生 secret store &amp;#43; 內建 RDS / Redshift rotation Lambda、Resource Policy 跨帳號共享、KMS 加密">Secrets Manager&lt;/a> + &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-kms/" data-link-title="AWS KMS" data-link-desc="AWS 原生 key management service、envelope encryption / digital signing / Multi-Region Key、Key Policy &amp;#43; Grant 雙軌授權">KMS&lt;/a> + &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-acm/" data-link-title="AWS ACM" data-link-desc="AWS-managed certificate provisioning、DNS validation &amp;#43; auto-renewal、整合 ELB / CloudFront / API Gateway、Private CA 後端">ACM&lt;/a> 三個獨立 service、職責邊界清楚但要管三套權限；GCP 是 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/google-secret-manager/" data-link-title="Google Secret Manager" data-link-desc="GCP 原生 secret store、CMEK &amp;#43; Workload Identity Federation 整合、rotation 走自寫 Cloud Function 而非 built-in Lambda">Google Secret Manager&lt;/a> + &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/google-cloud-kms/" data-link-title="Google Cloud KMS" data-link-desc="GCP 原生 key management service、KeyRing / CryptoKey Version 設計、CMEK 整合 &amp;#43; Cloud HSM &amp;#43; External Key Manager">Cloud KMS&lt;/a> + Certificate Authority Service 三個獨立；Azure 把這三件事合在 Key Vault — 同一 RBAC role 可同時管 secret / key / cert、減少 IAM 維護成本、但治理上需要在 Vault 內用 &lt;em>naming convention + 多 Vault instance&lt;/em> 自己劃分敏感度邊界（例：production secret / cert 分開不同 Vault、admin access 分人）。&lt;/p></description><content:encoded><![CDATA[<p>Azure Key Vault 是 Azure 平台把 <em>secret</em>、<em>cryptographic key</em>、<em>X.509 certificate</em> 三類資產 <em>合進同一個 service</em> 的設計。Vault instance 本身是 first-class ARM resource、有 FQDN endpoint（<code>https://&lt;vault-name&gt;.vault.azure.net</code>）、跟 <a href="/blog/backend/07-security-data-protection/vendors/azure-rbac/" data-link-title="Azure RBAC &#43; Entra ID" data-link-desc="Azure 雙層身份/權限體系、Entra ID（IdP）&#43; Azure RBAC（resource permission）、Conditional Access、PIM、Managed Identity">Azure RBAC</a> 跟 <a href="/blog/backend/07-security-data-protection/vendors/azure-rbac/" data-link-title="Azure RBAC &#43; Entra ID" data-link-desc="Azure 雙層身份/權限體系、Entra ID（IdP）&#43; Azure RBAC（resource permission）、Conditional Access、PIM、Managed Identity">Entra ID</a> Managed Identity 深度整合 — 每個 Vault 自己一個邊界、區別於 region-wide service 的模型。</p>
<h2 id="服務定位">服務定位</h2>
<p>Azure Key Vault 的核心定位是 <em>三合一 secret + key + cert service 加 Azure-native secret-less 取用</em>。AWS 是 <a href="/blog/backend/07-security-data-protection/vendors/aws-secrets-manager/" data-link-title="AWS Secrets Manager" data-link-desc="AWS 原生 secret store &#43; 內建 RDS / Redshift rotation Lambda、Resource Policy 跨帳號共享、KMS 加密">Secrets Manager</a> + <a href="/blog/backend/07-security-data-protection/vendors/aws-kms/" data-link-title="AWS KMS" data-link-desc="AWS 原生 key management service、envelope encryption / digital signing / Multi-Region Key、Key Policy &#43; Grant 雙軌授權">KMS</a> + <a href="/blog/backend/07-security-data-protection/vendors/aws-acm/" data-link-title="AWS ACM" data-link-desc="AWS-managed certificate provisioning、DNS validation &#43; auto-renewal、整合 ELB / CloudFront / API Gateway、Private CA 後端">ACM</a> 三個獨立 service、職責邊界清楚但要管三套權限；GCP 是 <a href="/blog/backend/07-security-data-protection/vendors/google-secret-manager/" data-link-title="Google Secret Manager" data-link-desc="GCP 原生 secret store、CMEK &#43; Workload Identity Federation 整合、rotation 走自寫 Cloud Function 而非 built-in Lambda">Google Secret Manager</a> + <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-kms/" data-link-title="Google Cloud KMS" data-link-desc="GCP 原生 key management service、KeyRing / CryptoKey Version 設計、CMEK 整合 &#43; Cloud HSM &#43; External Key Manager">Cloud KMS</a> + Certificate Authority Service 三個獨立；Azure 把這三件事合在 Key Vault — 同一 RBAC role 可同時管 secret / key / cert、減少 IAM 維護成本、但治理上需要在 Vault 內用 <em>naming convention + 多 Vault instance</em> 自己劃分敏感度邊界（例：production secret / cert 分開不同 Vault、admin access 分人）。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a> 相比、Azure Key Vault 是 Azure-only 的 <em>static-focused</em> 服務 — 沒有 dynamic credential engine、沒有 transit encryption-as-a-service、沒有跨雲統一介面。優勢是 <em>零運維</em> + <em>Managed Identity 取用免 client secret</em> + <em>Premium tier 直接 HSM-backed</em>。Azure-heavy + 一站式 secret/key/cert + secret-less workload 取用是 Key Vault 的甜蜜點。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>哪些 secret / key / cert 適合放 Key Vault、哪些該走 <a href="https://learn.microsoft.com/azure/key-vault/managed-hsm/overview">Managed HSM</a>（FIPS 140-2 Level 3 需求）</li>
<li>Access Policy 跟 Azure RBAC 兩種授權模型的差異與 migration 路徑</li>
<li>Soft Delete + Purge Protection 的 <em>防誤刪</em> 與 <em>防勒索</em> 邊界</li>
<li>何時用 Key Vault、何時改走 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a>（跨雲 + dynamic credential）的取捨</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Azure Key Vault deployment 是否健康、最少看四件事：</p>
<ul>
<li><strong>誰能 access</strong>：Vault 用 Access Policy 還是 Azure RBAC、是否還有 legacy Access Policy 沒清掉、Managed Identity 的 role assignment 是否最小化（Key Vault Secrets User 而非 Key Vault Administrator）</li>
<li><strong>RBAC vs Access Policy 模型</strong>：production 應該全走 Azure RBAC（跟 <a href="/blog/backend/07-security-data-protection/vendors/azure-rbac/" data-link-title="Azure RBAC &#43; Entra ID" data-link-desc="Azure 雙層身份/權限體系、Entra ID（IdP）&#43; Azure RBAC（resource permission）、Conditional Access、PIM、Managed Identity">Azure RBAC vendor</a> 同套）、舊 Access Policy 是 migration backlog、不可長期兩軌並存</li>
<li><strong>Soft Delete + Purge Protection</strong>：兩個都應開、Soft Delete 90 天 retention、Purge Protection 開了之後連 owner 都不能立即 purge — 防誤刪 + 防 ransomware 一次性刪光</li>
<li><strong>Diagnostic Logs</strong>：Key Vault <em>預設不記操作 log</em>、必須手動配 Diagnostic Setting 推 Log Analytics / Event Hub / Storage — 沒這層 <code>KeyVaultGet</code> / <code>SecretGet</code> 都沒 audit trail</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">Audit Log</a> 與 <a href="/blog/backend/knowledge-cards/secret-management/" data-link-title="Secret Management" data-link-desc="說明 token、key、password 與憑證如何保存、輪替與撤銷">Secret Management</a> 邊界的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>Vault Standard vs Premium</strong>：Standard 用 software protection（key 存在 Microsoft-managed software boundary）、Premium 用 FIPS 140-2 Level 2 HSM-backed key、key material 在 HSM 內、不可 export。Premium 適合 <em>signing key / wrapping key 等高敏 key</em>、Standard 適合 <em>application secret + 常規 envelope encryption key</em>。要 FIPS 140-2 Level 3、Standard 跟 Premium 都不夠、必須用 Managed HSM。</p>
<p><strong>Access Policy vs Azure RBAC（兩種授權）</strong>：Access Policy 是 Key Vault legacy 模型 — 在 Vault 物件上掛一張 capability 表（Get / List / Set / Delete / Encrypt / Sign 等細粒度權限）、跟 Azure RBAC 體系獨立。Azure RBAC 模型是新版 — 用 Azure built-in role（Key Vault Secrets User / Key Vault Crypto User / Key Vault Administrator）走 <a href="/blog/backend/07-security-data-protection/vendors/azure-rbac/" data-link-title="Azure RBAC &#43; Entra ID" data-link-desc="Azure 雙層身份/權限體系、Entra ID（IdP）&#43; Azure RBAC（resource permission）、Conditional Access、PIM、Managed Identity">Entra ID</a> 統一身份治理。production 全走 RBAC、舊 Vault 的 Access Policy 是 migration backlog — 兩軌並存會出現 <em>RBAC 拒絕但 Access Policy 允許</em> 的權限漏洞。</p>
<p><strong>Managed Identity 取用（secret-less）</strong>：Azure VM / Function / App Service / AKS pod 走 <em>Managed Identity</em> 直接呼叫 Key Vault API — 不需要存 client secret 或 cert。Workload 拿 IMDS token、token 帶 Entra ID identity、Key Vault 端用 RBAC role assignment 驗證 — 這是 Azure-native 的 secret-less 取用模式、跟 <a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM Role for Service Account</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">GCP Workload Identity</a> 同類設計。production 應該 <em>只允許</em> Managed Identity 取用、禁用 service principal + client secret。</p>
<p><strong>Secret rotation（手動 / event-driven）</strong>：Key Vault Secret <em>沒有像 <a href="/blog/backend/07-security-data-protection/vendors/aws-secrets-manager/" data-link-title="AWS Secrets Manager" data-link-desc="AWS 原生 secret store &#43; 內建 RDS / Redshift rotation Lambda、Resource Policy 跨帳號共享、KMS 加密">AWS Secrets Manager</a> 內建的 rotation Lambda</em>。Rotation 走兩條路：手動更新 secret version（app 端拉新版）、或 Event Grid 通知 secret 過期 + Azure Function 觸發 rotation。後者需要自己寫 rotation logic、Key Vault 只提供 <em>版本管理</em> 跟 <em>過期通知</em>、不負責執行 rotation。</p>
<p><strong>Key Rotation Policy</strong>：Key（不是 Secret）有 native Rotation Policy — Vault 在 key 到期前自動生成新版、舊版保留可解密但不再 encrypt。policy 設 <code>rotationPeriod</code> + <code>notifyBeforeExpiry</code>、Key Vault 自動跑、不需要外部觸發。Secret 沒這功能、Key 才有。</p>
<p><strong>Certificate auto-renewal</strong>：Certificate object 可整合 <em>Issuer</em>（DigiCert / GlobalSign / 自簽）做 auto-issue + auto-renew — Key Vault 在到期前自動跑 CSR、向 Issuer 申請新 cert、寫回同一個 Certificate object（保留歷史版本）。比起手動跑 OpenSSL + 寫進 <a href="/blog/backend/07-security-data-protection/vendors/aws-acm/" data-link-title="AWS ACM" data-link-desc="AWS-managed certificate provisioning、DNS validation &#43; auto-renewal、整合 ELB / CloudFront / API Gateway、Private CA 後端">AWS ACM</a>、Certificate object 的優勢是 <em>Issuer 在 Vault 端統一治理</em> — 不過只支援整合過的 public CA。</p>
<p><strong>Soft Delete + Purge Protection</strong>：Soft Delete 預設開（2020 後新 Vault 強制開）、delete 後 90 天 retention、Recover 可救回。Purge Protection 是 <em>額外</em> 開關 — 開了之後 retention 內任何人（包含 subscription owner）都不能 <code>purge</code> 立即清除、必須等 90 天到期才會物理刪除。這是 <em>防勒索</em> 的關鍵 — 沒 Purge Protection、attacker 拿到 owner role 可以 delete + purge 一次性清光。</p>
<p><strong>Private Endpoint</strong>：Key Vault 預設是 public endpoint（FQDN 走 internet）。Private Endpoint 把 Vault 拉進 VNet、只走內網存取 — 高敏 Vault 應該關 public access、強制走 Private Endpoint + Firewall rule（IP 白名單）。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Azure Key Vault</th>
          <th>AWS（拆三個）</th>
          <th>GCP（拆三個）</th>
          <th>HashiCorp Vault</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>部署模型</td>
          <td>Azure managed、三合一</td>
          <td>AWS managed、Secrets Manager + KMS + ACM 各獨立</td>
          <td>GCP managed、GSM + Cloud KMS + CAS 各獨立</td>
          <td>自管或 HCP managed</td>
      </tr>
      <tr>
          <td>服務邊界</td>
          <td>一個 Vault 內 secret/key/cert 共用 ACL</td>
          <td>三個 service 各自 IAM policy、邊界清楚</td>
          <td>三個 service 各自 IAM policy</td>
          <td>一個 cluster 內 path-based policy</td>
      </tr>
      <tr>
          <td>Secret-less 取用</td>
          <td>Managed Identity 原生</td>
          <td>IAM Role for Service Account / IRSA</td>
          <td>Workload Identity Federation</td>
          <td>AppRole / K8s / cloud IAM auth</td>
      </tr>
      <tr>
          <td>Dynamic credential</td>
          <td>無 — 純 static</td>
          <td>部分（RDS rotation Lambda）</td>
          <td>較弱（依靠 IAM impersonation）</td>
          <td>強 — database / cloud / SSH engine</td>
      </tr>
      <tr>
          <td>HSM 等級</td>
          <td>Standard 軟體 / Premium FIPS 140-2 Level 2 / Managed HSM Level 3</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/aws-kms/" data-link-title="AWS KMS" data-link-desc="AWS 原生 key management service、envelope encryption / digital signing / Multi-Region Key、Key Policy &#43; Grant 雙軌授權">KMS</a> Level 3 / <a href="/blog/backend/07-security-data-protection/vendors/cloudhsm/" data-link-title="AWS CloudHSM" data-link-desc="Single-tenant dedicated HSM（FIPS 140-2 Level 3）、AWS 不持 Crypto User credential、合規 &#43; 資料主權場景的 key custody">CloudHSM</a> Level 3</td>
          <td>Cloud KMS HSM Level 3 / Cloud HSM Level 3</td>
          <td>走後端 KMS（AWS / GCP / Azure）</td>
      </tr>
      <tr>
          <td>Certificate auto-renew</td>
          <td>內建（整合 DigiCert / GlobalSign）</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/aws-acm/" data-link-title="AWS ACM" data-link-desc="AWS-managed certificate provisioning、DNS validation &#43; auto-renewal、整合 ELB / CloudFront / API Gateway、Private CA 後端">ACM</a> auto-renew、限 AWS-issued</td>
          <td>CAS + Public CA 整合</td>
          <td>PKI engine 自簽 + <a href="/blog/backend/07-security-data-protection/vendors/cert-manager/" data-link-title="cert-manager" data-link-desc="K8s 原生 certificate lifecycle automation、支援 Let&#39;s Encrypt / Vault PKI / Venafi 等多 issuer、auto-renewal &#43; Challenge solver">cert-manager</a></td>
      </tr>
      <tr>
          <td>跨雲</td>
          <td>弱 — Azure-only</td>
          <td>弱 — AWS-only</td>
          <td>弱 — GCP-only</td>
          <td>強 — 跨雲統一介面</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>Azure-heavy + 三合一一站式 + Managed Identity</td>
          <td>AWS-heavy + 職責拆分 + RDS 自動 rotation</td>
          <td>GCP-heavy + Workload Identity Federation</td>
          <td>跨雲 + dynamic credential + 內部 PKI</td>
      </tr>
  </tbody>
</table>
<p>選 Azure Key Vault 的核心訴求：<em>Azure-only</em>、需要 <em>secret + key + cert</em> 一站式、workload 走 <em>Managed Identity</em> secret-less 取用、可接受 <em>無 dynamic credential</em>。需要跨雲統一 secret 控制面、或要 dynamic database credential、走 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a>。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Managed HSM（dedicated）</strong>：Managed HSM 是 <em>dedicated single-tenant HSM cluster</em>、FIPS 140-2 Level 3、跟 multi-tenant 的 Key Vault Premium 是不同 service。Managed HSM 適合 <em>主權合規</em>（key material 完全自有控制權、Microsoft 也不可存取）、<em>金融 / 醫療 / 政府場景</em>。代價是 <em>貴</em> 跟 <em>初始化要走 ceremony</em>（多人持有 activation key、Microsoft 不可單方面操作）— 不是 Premium 的簡單升級、是另一條 product line。</p>
<p><strong>Premium tier HSM-backed Key</strong>：Premium tier 的 key 有 <code>HSM-protected</code> 屬性、key material 在 multi-tenant HSM 內、API call 還是走標準 Key Vault endpoint、但 cryptographic operation 在 HSM 跑。比 Standard 慢一點、價格高、適合 <em>signing key / wrapping key / root encryption key</em> — 一般 application secret 還是 Standard 即可。</p>
<p><strong>Certificate Issuer 整合</strong>：Vault 內可註冊 Issuer（DigiCert / GlobalSign / Entrust）、提供 API credential、Vault 在 Certificate 到期前自動跑 CSR、向 Issuer 申請、Issuer 簽完寫回 Vault。Self-signed / Unknown Issuer 也支援、後者表示 <em>Vault 產 CSR、人或 pipeline 拿去外部 CA 簽完再 import 回 Vault</em>。</p>
<p><strong>Cross-tenant key access（federated identity）</strong>：Key Vault 可允許跨 Entra ID tenant 的 service principal 取用 — 透過 Federated Identity Credential（Workload Identity Federation）、外部 tenant 的 identity（甚至 GitHub Actions OIDC、AWS workload）拿 token 來 Key Vault 驗證。這是 cross-cloud workload 拉 Azure secret 的方式、不需要存 Azure service principal credential。</p>
<p><strong>跟 <a href="/blog/backend/07-security-data-protection/vendors/azure-rbac/" data-link-title="Azure RBAC &#43; Entra ID" data-link-desc="Azure 雙層身份/權限體系、Entra ID（IdP）&#43; Azure RBAC（resource permission）、Conditional Access、PIM、Managed Identity">Entra ID</a> Conditional Access 整合</strong>：Key Vault 用 Azure RBAC 模型時、可走 Conditional Access policy — <em>特定 IP</em>、<em>已 enrolled 裝置</em>、<em>MFA 已驗證</em> 才能取用 secret / key。production 高敏 Vault 應該疊 Conditional Access、避免單純 RBAC 在 token leak 時就直接被存取。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Diagnostic Setting 沒開</strong>：production Vault 啟用後忘了配 Diagnostic Setting 推 log、事故發生時無 <code>SecretGet</code> / <code>KeyDecrypt</code> 紀錄 — 啟動 checklist 必含「Diagnostic Setting → Log Analytics」、Azure Policy 強制全 subscription Vault 都配</li>
<li><strong>Access Policy 跟 RBAC 兩軌並存</strong>：migration 過程中 RBAC 已切換但舊 Access Policy 沒清、出現 <em>RBAC 拒絕但 Access Policy 允許</em> — migration 一次切斷、跑 <code>az keyvault update --enable-rbac-authorization true</code> 後清空所有 Access Policy</li>
<li><strong>Soft Delete 沒開 / Purge Protection 沒開</strong>：誤刪 secret 救不回、或 attacker 拿到 owner role 一次 purge 清光 — 新 Vault 兩個都強制開、Azure Policy 阻擋 <code>enablePurgeProtection: false</code> 的 Vault 建立</li>
<li><strong>Managed Identity role 過寬</strong>：給 workload identity <code>Key Vault Administrator</code> 而非 <code>Key Vault Secrets User</code> — workload 拿到 admin role 等於可改 ACL — role assignment 走 least privilege built-in role</li>
<li><strong>Premium key 跑非 HSM operation</strong>：Premium key 配錯 attribute、key 變成 software-protected 而非 HSM-protected — 建 key 時明示 <code>--protection hsm</code>、CI 驗證 key attribute</li>
<li><strong>Certificate auto-renew Issuer credential 過期</strong>：Vault 內 DigiCert API credential 過期、auto-renew 默默失敗、cert 到期前才發現 — Issuer credential 也要 rotation + monitor</li>
<li><strong>Public access 開著</strong>：Vault 沒關 public endpoint、secret 暴露在 internet（雖然有 RBAC、但 attack surface 多一層）— 高敏 Vault 強制 Private Endpoint + Firewall rule</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>跨雲統一 secret 控制面</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a></td>
      </tr>
      <tr>
          <td>Dynamic database / cloud credential</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a>（database / cloud secret engine）</td>
      </tr>
      <tr>
          <td>FIPS 140-2 Level 3 HSM</td>
          <td><a href="https://learn.microsoft.com/azure/key-vault/managed-hsm/overview">Managed HSM</a> / <a href="/blog/backend/07-security-data-protection/vendors/cloudhsm/" data-link-title="AWS CloudHSM" data-link-desc="Single-tenant dedicated HSM（FIPS 140-2 Level 3）、AWS 不持 Crypto User credential、合規 &#43; 資料主權場景的 key custody">CloudHSM</a></td>
      </tr>
      <tr>
          <td>內部 PKI workload mTLS</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/cert-manager/" data-link-title="cert-manager" data-link-desc="K8s 原生 certificate lifecycle automation、支援 Let&#39;s Encrypt / Vault PKI / Venafi 等多 issuer、auto-renewal &#43; Challenge solver">cert-manager</a> + Vault PKI / SPIRE</td>
      </tr>
      <tr>
          <td>公開 web cert 自動更新（非 Azure-issued）</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/letsencrypt/" data-link-title="Let&#39;s Encrypt" data-link-desc="免費 &#43; 自動化的公共 ACME CA、90 天 TTL 強制自動化、跨雲跨平台 public TLS cert 的事實基礎">Let&rsquo;s Encrypt</a> + cert-manager</td>
      </tr>
      <tr>
          <td>Entra ID 身份治理 / Conditional Access</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/azure-rbac/" data-link-title="Azure RBAC &#43; Entra ID" data-link-desc="Azure 雙層身份/權限體系、Entra ID（IdP）&#43; Azure RBAC（resource permission）、Conditional Access、PIM、Managed Identity">Azure RBAC</a></td>
      </tr>
      <tr>
          <td>Secret rotation 證據鏈</td>
          <td><a href="/blog/backend/07-security-data-protection/credential-rotation-scoped-evidence/" data-link-title="7.27 Credential Rotation with Scoped Evidence 實作示範" data-link-desc="以 webhook/API credential 輪替示範 scope map、證據欄位與回退窗口如何一起設計。">7.5 Credential Rotation Scoped Evidence</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Key Vault REST API / Azure CLI 完整 reference</li>
<li>Managed HSM activation ceremony 完整步驟</li>
<li>Bicep / Terraform 配置 Key Vault 的完整 IaC 範例</li>
<li>Certificate Issuer（DigiCert / GlobalSign）的合約與計價細節</li>
<li>每個 Entra ID role 的細粒度 permission map</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 Azure Key Vault 的關係</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/cases/azure-ad-identity-control-plane-2021/" data-link-title="7.C3 Azure AD：2021 Identity Control-plane 事件" data-link-desc="身分控制面事件如何影響多服務信任鏈與回復優先序。">Azure AD Identity Control Plane 2021</a></td>
          <td>Key Vault 是身份控制面下游、Entra ID 出事時 Managed Identity 取 Vault 也失敗 — 需要 fallback access plan（emergency Access Policy + separate identity 走 break-glass）</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/cases/microsoft-storm-0558-signing-key-2023/" data-link-title="7.C4 Microsoft：Storm-0558 簽章金鑰事件" data-link-desc="簽章金鑰事件如何回寫 identity 信任邊界與觀測證據鏈。">Microsoft Storm-0558 Signing Key 2023</a></td>
          <td>Key Vault Premium / Managed HSM 把 signing key 鎖硬體、key 不離保護邊界、跟 HSM-bound 同 mindset — signing key 必上 Premium 或 Managed HSM、不放 Standard</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/microsoft-storm-0558-2023-signing-key-chain/" data-link-title="7.R7.1.5 Microsoft Storm-0558 2023：簽章金鑰鏈與郵件存取" data-link-desc="從簽章金鑰保護失效到雲端郵件存取，拆解身分信任鏈的關鍵控制點">Microsoft Storm-0558 Signing Key Chain (red-team)</a></td>
          <td>Asymmetric Key + Diagnostic Logs 是「誰用 key」的稽核基礎 — production Vault 必開 Diagnostic Setting 推 SIEM、不然 key 被誰用過完全沒紀錄</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/cases/failure-credential-rotation-without-scope/" data-link-title="7.C9 反例：憑證輪替未分 Scope" data-link-desc="憑證輪替若未分域分批，容易造成跨系統連鎖中斷。">Failure: Credential Rotation Without Scope</a></td>
          <td>Key Vault Secret 跨 service 共用時 rotation 要分域 — Vault 端用 Event Grid 通知 + app 端訂閱 rotation event、不能一次 push 全域更新</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/secrets-and-machine-credential-governance/" data-link-title="7.6 秘密管理與機器憑證治理" data-link-desc="以問題驅動方式整理 secret、token、key 與機器身份治理">7.6 秘密管理與機器憑證治理</a>、<a href="/blog/backend/07-security-data-protection/transport-trust-and-certificate-lifecycle/" data-link-title="7.5 傳輸信任與憑證生命週期" data-link-desc="以問題驅動方式整理傳輸信任鏈、會話完整性與憑證節奏">7.5 傳輸信任與憑證生命週期</a>（Key Vault Certificate + Managed HSM 為 TLS / signing key 的 root custodian）、<a href="/blog/backend/07-security-data-protection/identity-access-boundary/" data-link-title="7.2 身分與授權邊界" data-link-desc="以問題驅動方式整理身分、授權、會話與供應商身分鏈">7.2 身分與授權邊界</a></li>
<li>平行（secret store）：<a href="/blog/backend/07-security-data-protection/vendors/aws-secrets-manager/" data-link-title="AWS Secrets Manager" data-link-desc="AWS 原生 secret store &#43; 內建 RDS / Redshift rotation Lambda、Resource Policy 跨帳號共享、KMS 加密">AWS Secrets Manager</a>、<a href="/blog/backend/07-security-data-protection/vendors/google-secret-manager/" data-link-title="Google Secret Manager" data-link-desc="GCP 原生 secret store、CMEK &#43; Workload Identity Federation 整合、rotation 走自寫 Cloud Function 而非 built-in Lambda">Google Secret Manager</a>、<a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a></li>
<li>平行（KMS-class）：<a href="/blog/backend/07-security-data-protection/vendors/aws-kms/" data-link-title="AWS KMS" data-link-desc="AWS 原生 key management service、envelope encryption / digital signing / Multi-Region Key、Key Policy &#43; Grant 雙軌授權">AWS KMS</a>、<a href="/blog/backend/07-security-data-protection/vendors/google-cloud-kms/" data-link-title="Google Cloud KMS" data-link-desc="GCP 原生 key management service、KeyRing / CryptoKey Version 設計、CMEK 整合 &#43; Cloud HSM &#43; External Key Manager">Google Cloud KMS</a>、<a href="/blog/backend/07-security-data-protection/vendors/cloudhsm/" data-link-title="AWS CloudHSM" data-link-desc="Single-tenant dedicated HSM（FIPS 140-2 Level 3）、AWS 不持 Crypto User credential、合規 &#43; 資料主權場景的 key custody">CloudHSM</a>（Key Vault 是跨類 vendor、同時是 secret store 跟 key management）</li>
<li>下游：<a href="/blog/backend/07-security-data-protection/vendors/azure-rbac/" data-link-title="Azure RBAC &#43; Entra ID" data-link-desc="Azure 雙層身份/權限體系、Entra ID（IdP）&#43; Azure RBAC（resource permission）、Conditional Access、PIM、Managed Identity">Azure RBAC</a>（Managed Identity + RBAC 取用模型）</li>
<li>下游：<a href="/blog/backend/07-security-data-protection/vendors/cert-manager/" data-link-title="cert-manager" data-link-desc="K8s 原生 certificate lifecycle automation、支援 Let&#39;s Encrypt / Vault PKI / Venafi 等多 issuer、auto-renewal &#43; Challenge solver">cert-manager</a>（K8s workload cert 自動化、可整合 Key Vault Certificate）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（Key Vault 事件如何 routing 進 IR 流程）</li>
<li>官方：<a href="https://learn.microsoft.com/azure/key-vault/">Azure Key Vault Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>Dependabot</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/dependabot/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/dependabot/</guid><description>&lt;p>Dependabot 是 GitHub 內建的 &lt;em>依賴更新自動化&lt;/em> 工具、原為 Dependabot Inc.、2019 年被 GitHub 收購後改為 GitHub native feature、目前 public repo 免費、private repo 部分功能 (Alerts / Security Update) 也免費、Version Update 跟進階治理納入 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &amp;#43; Secret Scanning &amp;#43; Dependency Review &amp;#43; Dependabot、跟 PR / Security tab 深度整合">GitHub Advanced Security&lt;/a> 套餐。它做三件事：&lt;em>Dependabot version updates&lt;/em>（定期 PR 升級依賴到最新 compatible 版本）、&lt;em>Dependabot security updates&lt;/em>（CVE 觸發的緊急 PR 升級到 fix version）、&lt;em>Dependabot alerts&lt;/em>（看到漏洞列在 Security tab、不一定自動 PR）。它的設計目標 &lt;em>狹窄而深&lt;/em> — 只做 GitHub repo 的依賴 PR 自動化、不做容器掃描、不做 IaC 掃描、不跨 SCM。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Dependabot 的核心定位是 &lt;em>把依賴升級從人工 ritual 變成 PR review 工作流&lt;/em>。它把「找新版」「跑 manifest update」「開 PR」「附 release note」自動化、剩下的 &lt;em>是否合併&lt;/em> 留給人類 / CI 判斷。這跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &amp;#43; Code (SAST) &amp;#43; Container &amp;#43; IaC &amp;#43; Cloud (CSPM)、Reachability analysis">Snyk&lt;/a> 看似重疊 — 兩者都會自動發升級 PR — 但 Snyk 是 &lt;em>跨 SCM + 多 stack&lt;/em>（GitHub / GitLab / Bitbucket、SCA + 容器 + IaC + Code）、Dependabot 是 &lt;em>GitHub-only + 純依賴&lt;/em>。多數組織選一個、混用兩者會在同一個 manifest 上各自開 PR、造成 noise。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &amp;#43; Secret Scanning &amp;#43; Dependency Review &amp;#43; Dependabot、跟 PR / Security tab 深度整合">GHAS&lt;/a> 的關係比較細：Dependabot Alerts 跟 Security Updates 本身是 GHAS &lt;em>Dependabot&lt;/em> 子模組的核心、但功能上 &lt;em>Alerts 對所有 repo 免費&lt;/em>、Security Update 也免費自動發 PR、Version Update 也免費；GHAS 提供的是 &lt;em>Dependency Review&lt;/em>（PR-time gate、阻擋 PR 引入新漏洞依賴）、&lt;em>Security Overview&lt;/em>（org-wide dashboard）跟 enterprise-level 控制。Dependabot 是 &lt;em>background PR 工廠&lt;/em>、GHAS Dependency Review 是 &lt;em>PR-time blocker&lt;/em>、兩者互補不重疊。&lt;/p></description><content:encoded><![CDATA[<p>Dependabot 是 GitHub 內建的 <em>依賴更新自動化</em> 工具、原為 Dependabot Inc.、2019 年被 GitHub 收購後改為 GitHub native feature、目前 public repo 免費、private repo 部分功能 (Alerts / Security Update) 也免費、Version Update 跟進階治理納入 <a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GitHub Advanced Security</a> 套餐。它做三件事：<em>Dependabot version updates</em>（定期 PR 升級依賴到最新 compatible 版本）、<em>Dependabot security updates</em>（CVE 觸發的緊急 PR 升級到 fix version）、<em>Dependabot alerts</em>（看到漏洞列在 Security tab、不一定自動 PR）。它的設計目標 <em>狹窄而深</em> — 只做 GitHub repo 的依賴 PR 自動化、不做容器掃描、不做 IaC 掃描、不跨 SCM。</p>
<h2 id="服務定位">服務定位</h2>
<p>Dependabot 的核心定位是 <em>把依賴升級從人工 ritual 變成 PR review 工作流</em>。它把「找新版」「跑 manifest update」「開 PR」「附 release note」自動化、剩下的 <em>是否合併</em> 留給人類 / CI 判斷。這跟 <a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk</a> 看似重疊 — 兩者都會自動發升級 PR — 但 Snyk 是 <em>跨 SCM + 多 stack</em>（GitHub / GitLab / Bitbucket、SCA + 容器 + IaC + Code）、Dependabot 是 <em>GitHub-only + 純依賴</em>。多數組織選一個、混用兩者會在同一個 manifest 上各自開 PR、造成 noise。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GHAS</a> 的關係比較細：Dependabot Alerts 跟 Security Updates 本身是 GHAS <em>Dependabot</em> 子模組的核心、但功能上 <em>Alerts 對所有 repo 免費</em>、Security Update 也免費自動發 PR、Version Update 也免費；GHAS 提供的是 <em>Dependency Review</em>（PR-time gate、阻擋 PR 引入新漏洞依賴）、<em>Security Overview</em>（org-wide dashboard）跟 enterprise-level 控制。Dependabot 是 <em>background PR 工廠</em>、GHAS Dependency Review 是 <em>PR-time blocker</em>、兩者互補不重疊。</p>
<p>跟 <a href="https://docs.renovatebot.com/">Renovate</a>（Mend 維護的 OSS）的差異：Renovate 配置更彈性、跨 SCM、支援 ecosystem 數量多（含 Helm chart、Docker tag、ArgoCD 等）、Grouped Updates 規則更細；Dependabot 整合 GitHub 原生 UI（Security tab、Dependency graph、PR diff）更深、設定簡單。需要 <em>跨 SCM</em> 或 <em>Helm / ArgoCD / 自訂 ecosystem</em> 走 Renovate；單純 GitHub-only 加 npm / Maven / pip 等主流 ecosystem、Dependabot 配置成本更低。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>Dependabot 在 supply chain 防護裡承擔哪一段（背景 PR 升級）、哪些不在它責任內（容器掃描、IaC 掃描、PR-time gate）</li>
<li><code>dependabot.yml</code> 的關鍵配置面：ecosystem、schedule、open-pull-requests-limit、groups、reviewers</li>
<li>Version Update vs Security Update vs Alerts 三個功能何時開、PR noise 怎麼控制</li>
<li>Auto-merge 政策的邊界：哪種更新可以全自動、哪種要保留 human approval</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷一個 repo 的 Dependabot 配置是否健康、最少看四件事：</p>
<ul>
<li><strong><code>dependabot.yml</code> 配置</strong>：repo 是否有 <code>.github/dependabot.yml</code>、ecosystem 是否覆蓋所有 manifest（npm / Maven / pip / Docker / GitHub Actions / Terraform）、<code>directory</code> 路徑對不對（monorepo 各 sub-package 是否獨立配置）</li>
<li><strong>Update Schedule</strong>：<code>schedule.interval</code> 是 daily / weekly / monthly、<code>open-pull-requests-limit</code> 是否合理（預設 5、太低會卡住 backlog、太高會 PR noise）、Grouped Updates 是否啟用（減少 minor / patch PR 數量）</li>
<li><strong>Auto-merge 政策</strong>：branch protection 是否設「CI green + required reviewer」、auto-merge 是否限定 <em>patch + minor</em> 自動、<em>major</em> 強制 human review、production 跟 staging branch 是否有差異化規則</li>
<li><strong>Token 治理</strong>：repo secrets 是否被 Dependabot PR 誤用、Dependabot secrets（私有 registry credential）是否獨立配置、PR 觸發的 Actions 是否假設 read-only token</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">Supply Chain Integrity</a> 邊界的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong><code>dependabot.yml</code> 是版控的配置檔</strong>：放在 <code>.github/dependabot.yml</code>、跟 manifest 同 repo、所有變更走 PR review。不在 GitHub UI 直接改 — UI 只能 <em>啟用 / 停用</em> Dependabot 本身、細節必須 commit 進 repo。Monorepo 結構（例：<code>/services/api</code>、<code>/services/web</code> 各自 <code>package.json</code>）每個 sub-package 寫一個 entry、<code>directory</code> 指到 sub-package 根目錄、<code>package-ecosystem</code> 標 manifest 類型。<code>schedule.interval</code> 一般 weekly 開始、daily 適合高活躍度團隊但 PR noise 高、monthly 適合穩定 lib 但 CVE 延遲風險高。</p>
<p><strong>Version Update vs Security Update 分開</strong>：Version Update 是 <em>定期掃 manifest 看有沒有 newer compatible 版本</em>、不分 CVE、是 hygiene 工作；Security Update 是 <em>Dependabot 偵測到 CVE 且 manifest 指到 vulnerable 範圍時自動發 PR 升級到 fix version</em>、是 incident 工作。多數組織開 Security Update 全 repo + 選擇性開 Version Update（核心服務開、archived repo 不開）— 避免 PR noise 淹沒緊急 PR。Security Update 預設啟用、Version Update 要 explicit 在 <code>dependabot.yml</code> 寫 entry 才會跑。</p>
<p><strong>Grouped Updates</strong>：2023 推出、單一 PR 含多個 minor / patch 升級（例：一個 PR 升 10 個 npm package）、PR 數量從 10 個降到 1 個。配置在 <code>dependabot.yml</code> 的 <code>groups</code> 區、可以按 dependency name pattern（例：<code>@types/*</code> 一組、<code>eslint*</code> 一組）或 update-type（<code>patch</code> / <code>minor</code> 分組）。Major version 仍分開 PR — 因 breaking change 風險、需要單獨 review。Grouped Updates 配 auto-merge 是 <em>minor / patch 全自動</em> 的標準配置。</p>
<p><strong>Auto-merge 是 PR 級、不是 commit 級</strong>：Dependabot 發 PR、搭配 GitHub branch protection 設「CI green + 1 approver」就 auto-merge — GitHub <code>gh pr merge --auto</code> 或 Actions workflow（<code>peter-evans/enable-pull-request-automerge</code>）都行。production 環境應該保留 human approval（至少對 major version）、staging / dev 可以全自動。常見模式：staging branch 全自動合（patch + minor）+ 自動 deploy；production branch 走 staging → cherry-pick / promote 流程、human approve。</p>
<p><strong>Reviewer / Assignee / Label 自動標記</strong>：<code>dependabot.yml</code> 的 <code>reviewers</code> / <code>assignees</code> / <code>labels</code> 欄位讓 Dependabot 開 PR 時自動標 reviewer 跟 label。實務上配 <code>labels: [&quot;dependencies&quot;]</code> 讓 Dependabot PR 在 PR list 跟一般 feature PR 分開、CI workflow 可以針對 <code>dependencies</code> label 跑特化 lint（例：跑完整 e2e、不只 unit test）。</p>
<p><strong>Token 治理</strong>：Dependabot PR 跑 GitHub Actions 時、<code>secrets.GITHUB_TOKEN</code> 是 <em>read-only</em>（GitHub 設計上限制、防 PR 觸發 supply chain attack）— 這代表 Dependabot PR 不能跑需要 write permission 的 job（推 image / 改 status / comment）。需要的話用 <code>pull_request_target</code> event（用 base branch 的 workflow + 完整 secrets）、但這也是 supply chain attack 高風險面、必須 <em>最少 permission</em>。私有 registry credential（npm private registry token、Maven private repo password）用 <em>Dependabot secrets</em>（org / repo level）配置、跟 GitHub Actions secrets 是 <em>不同 namespace</em>、不會互相讀到。</p>
<p><strong>跟 GHAS Dependency Review 搭配</strong>：<a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GHAS Dependency Review</a> 在 PR-time 看 manifest diff 阻擋 <em>引入新漏洞依賴</em>、Dependabot Security Update 在 background <em>升級舊有漏洞依賴</em>、兩個方向互補。production repo 標準配置：GHAS Dependency Review 設 high severity block + Dependabot Security Update 全開 + Dependabot Version Update 選擇性開。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Dependabot</th>
          <th>Snyk</th>
          <th>Renovate</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>SCM 範圍</td>
          <td>GitHub only</td>
          <td>GitHub / GitLab / Bitbucket / Azure DevOps</td>
          <td>GitHub / GitLab / Bitbucket / Azure DevOps / Gitea</td>
      </tr>
      <tr>
          <td>涵蓋面</td>
          <td>純依賴（SCA）</td>
          <td>SCA + 容器 + IaC + Code</td>
          <td>純依賴（SCA）+ Docker tag / Helm / 自訂</td>
      </tr>
      <tr>
          <td>Ecosystem 數量</td>
          <td>主流（npm / Maven / pip / Docker / Actions / Terraform 等 20+）</td>
          <td>主流相近 + 商業資料庫優先</td>
          <td>多（含 Helm / ArgoCD / preCommit / 自訂 regex）</td>
      </tr>
      <tr>
          <td>Grouped Updates</td>
          <td>有（2023+、按 pattern / update-type）</td>
          <td>有（按 type）</td>
          <td>有（規則最細、按 manager / depType / pattern）</td>
      </tr>
      <tr>
          <td>Auto-merge</td>
          <td>走 GitHub branch protection + auto-merge</td>
          <td>Snyk 自家 PR + 走 SCM auto-merge</td>
          <td>內建 <code>automerge</code> 配置、規則細</td>
      </tr>
      <tr>
          <td>漏洞資料庫</td>
          <td>GitHub Advisory Database（公開 + 私有）</td>
          <td>Snyk Intel（商業、揭露快、加入專屬 advisory）</td>
          <td>OSV / NVD / GitHub Advisory（聚合）</td>
      </tr>
      <tr>
          <td>PR 整合深度</td>
          <td>GitHub Security tab / Dependency graph 原生</td>
          <td>Snyk UI 為主、SCM PR 是延伸</td>
          <td>SCM PR 原生、Renovate dashboard issue 集中管理</td>
      </tr>
      <tr>
          <td>設定方式</td>
          <td><code>dependabot.yml</code>（簡單）</td>
          <td>UI + <code>.snyk</code> policy file（漏洞例外）</td>
          <td><code>renovate.json</code>（極彈性、配置複雜）</td>
      </tr>
      <tr>
          <td>商業成本</td>
          <td>GitHub 免費（Version Update / Security Update / Alerts 都免費）</td>
          <td>商業授權（含免費 tier、規模上來付費）</td>
          <td>OSS 免費、Mend 商業版加分析 dashboard</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>GitHub-only + 純依賴 + 設定要簡單</td>
          <td>跨 SCM、要容器 / IaC、商業 advisory 加值</td>
          <td>跨 SCM 或要 Helm / ArgoCD / 自訂 ecosystem</td>
      </tr>
  </tbody>
</table>
<p>選 Dependabot 的核心訴求：<em>GitHub-only</em> + 只要依賴 PR 自動化、不要容器 / IaC scan、配置成本要低、整合 GitHub Security tab。要跨 SCM 或多 stack 走 Snyk、要彈性 ecosystem / Helm chart / ArgoCD 走 Renovate。混用 Dependabot + Snyk 對同一 manifest 自動 PR 會 noise、二選一。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Multi-ecosystem repo</strong>：一個 repo 同時有 npm + Docker + Terraform + GitHub Actions、<code>dependabot.yml</code> 寫四個 entry、各自 schedule。實務常見配置：application 依賴（npm / pip）weekly、base image（Docker）weekly、IaC（Terraform provider）monthly、GitHub Actions（CI workflow）weekly。Actions ecosystem 要特別注意 — Dependabot 升級 <code>uses:</code> 指向的 action version、可以同時 pin commit hash（防 tag re-publish 攻擊）、但 pin hash 後 release note 看不到 — 取捨 <em>安全 vs 可讀性</em>。</p>
<p><strong>Private registry support</strong>：私有 npm registry（GitHub Packages / Artifactory / Nexus）、私有 Maven repo、私有 PyPI mirror、私有 container registry 都要在 <code>dependabot.yml</code> 配置 <code>registries</code> 區、credential 走 Dependabot secrets。Dependabot 從私有 registry 抓 package metadata 跟 release info、否則只能看 public registry、會誤判 internal lib 沒新版。Org-level Dependabot secrets 適合共用 credential、repo-level 適合特殊 credential 隔離。</p>
<p><strong>Self-hosted runner 隔離</strong>：Dependabot PR 觸發的 Actions 預設跑在 GitHub-hosted runner、跟 Dependabot 本身的 sandbox 不同。如果 CI 跑在 self-hosted runner（內網資源 / 大 build cache）、Dependabot PR 也會跑在 self-hosted runner — 要確認 runner 不會被 PR 注入的惡意 manifest 攻擊（npm install 跑 postinstall script 是經典攻擊路徑）。Mitigation：Dependabot PR 用 ephemeral runner（每次新 VM）、隔離 build cache、不掛 sensitive volume。</p>
<p><strong>Auto-merge 風險</strong>：auto-merge 加速合併、但也放寬 <em>攻擊者升級 dep 攻擊我</em> 的窗口。<a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/xz-backdoor-2024-open-source-supply-chain/" data-link-title="7.R7.2.4 XZ Backdoor 2024：開源供應鏈長期滲透" data-link-desc="開源維護鏈遭滲透後，為何會直接影響廣泛 Linux 發行流程">XZ Backdoor 2024</a> 的攻擊路徑就是攻擊者花兩年取得 upstream maintainer 信任、發 release 帶 backdoor — 如果下游 auto-merge 升級、攻擊就直達 production。Mitigation：major version 永不 auto-merge、critical infra dep（auth / crypto / network 函式庫）pin commit hash + 手動 review、auto-merge 範圍縮到 patch + minor + low-criticality dep。</p>
<p><strong>GitHub Actions 跟 Dependabot 互動</strong>：Dependabot PR 觸發的 workflow 預設 <code>GITHUB_TOKEN</code> 是 <em>read-only</em>、<code>secrets.*</code> 是 <em>empty</em>（Dependabot context）— 防止 PR 注入腳本竊取 secret。需要在 Dependabot PR 跑帶 secret 的 job、用 <code>pull_request_target</code> event（workflow 從 base branch 取、有完整 secret）— 但這會 <em>讀 PR 的 code 跑 workflow</em>、必須先 <code>checkout</code> base 然後最小化 PR code 的執行（不跑 PR 的 install script、只跑既有 lint）。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>PR noise 淹沒緊急 PR</strong>：Version Update 全開 + 沒 Grouped Updates、一週 30+ PR — 啟用 <code>groups</code> 按 pattern 分組（<code>@types/*</code> / <code>eslint*</code> / <code>dev-dependencies</code>）、<code>open-pull-requests-limit</code> 設 5、archived repo 關 Version Update</li>
<li><strong>Security Update 沒發 PR</strong>：CVE 公告了但 Dependabot 沒動 — 確認 manifest 真的指到 vulnerable 範圍、<code>dependabot.yml</code> 沒 <code>ignore</code> 該 dependency、Security Updates 在 repo settings 是啟用、Dependency graph 有抓到該 manifest</li>
<li><strong>私有 registry 抓不到</strong>：Dependabot 在私有 npm / Maven repo 失敗 — <code>dependabot.yml</code> 配 <code>registries</code> 區、credential 進 Dependabot secrets（不是 Actions secrets）、URL 跟 token 範圍對齊</li>
<li><strong>Auto-merge 不觸發</strong>：PR 開了 CI 也綠了但沒合 — 確認 branch protection required check 跟 CI workflow 名稱對齊、<code>gh pr merge --auto</code> 在 PR comment / workflow 有觸發、reviewer count 達標</li>
<li><strong>Dependabot PR 跑 Actions 失敗</strong>：PR 的 workflow 報 permission denied — <code>GITHUB_TOKEN</code> 在 Dependabot context read-only、改用 <code>pull_request_target</code> 或拆 job（push secret 的部分跑在 merge 後 main branch event）</li>
<li><strong>Major version 被 auto-merge</strong>：規則沒寫對、major 也自動合進 production — <code>dependabot.yml</code> 的 <code>ignore</code> 加 <code>update-types: [&quot;version-update:semver-major&quot;]</code> 或 auto-merge 條件改 <code>${{ steps.metadata.outputs.update-type == 'version-update:semver-minor' }}</code></li>
<li><strong>Monorepo 漏掃</strong>：<code>/services/api/package.json</code> 沒掃 — <code>dependabot.yml</code> 每個 sub-package 寫一個 entry、<code>directory</code> 指到正確路徑、不是只在 root 一個 entry</li>
<li><strong>GitHub Actions ecosystem 升級拿掉 commit hash pin</strong>：原本 <code>uses: actions/checkout@a12b3c4</code> 被升成 <code>uses: actions/checkout@v5</code> — Dependabot 會 follow 既有 reference 風格、想要 hash pin 設 <code>dependabot.yml</code> 的 ecosystem-level config 但目前限制較多、實務常另用 <a href="https://github.com/suzuki-shunsuke/pinact">pinact</a> 或 Renovate 處理 Actions hash pinning</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>跨 SCM（GitLab / Bitbucket）</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk</a> / <a href="https://docs.renovatebot.com/">Renovate</a></td>
      </tr>
      <tr>
          <td>容器 / IaC scan</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk</a> / <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a></td>
      </tr>
      <tr>
          <td>Helm / ArgoCD / 自訂 ecosystem</td>
          <td><a href="https://docs.renovatebot.com/">Renovate</a></td>
      </tr>
      <tr>
          <td>PR-time block 引入新漏洞</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GHAS Dependency Review</a></td>
      </tr>
      <tr>
          <td>SAST / Code scanning</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GHAS Code Scanning</a> / <a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk Code</a></td>
      </tr>
      <tr>
          <td>SBOM 生成 / 簽章</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/syft-grype/" data-link-title="Syft &#43; Grype" data-link-desc="Anchore 開源姐妹工具：Syft 產 SBOM (CycloneDX / SPDX) &#43; Grype scan 漏洞、Unix philosophy、cosign attestation 整合">Syft / Grype</a>（含 Sigstore cosign 整合段落）</td>
      </tr>
      <tr>
          <td>Secret scanning</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GHAS Secret Scanning</a> / GitGuardian</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li><code>dependabot.yml</code> 完整欄位 reference（看 <a href="https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file">GitHub 官方文件</a>）</li>
<li>GitHub Advisory Database 詳細運作（CVE 來源、curation 流程）</li>
<li>GHAS 其他模組（Code Scanning / Secret Scanning / Dependency Review）細節 — 看 <a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GHAS 頁</a></li>
<li>Renovate / Snyk 完整配置 — 看各自 vendor 頁</li>
<li>Container base image 升級的 multi-stage Dockerfile 處理</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>Dependabot 沒有自身 vendor-level case、但在 supply chain case 中是 <em>標準 mitigation</em> 或 <em>風險面</em>：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 Dependabot 的關係</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/log4shell-cve-2021-44228-component-chain/" data-link-title="7.R7.2.7 Log4Shell 2021：共用元件風險與修補鏈" data-link-desc="共用元件漏洞如何同步影響多服務，並迫使團隊建立依賴治理 workflow">Log4Shell CVE-2021-44228</a></td>
          <td>對照啟示 — Dependabot Security Update 在 Log4Shell 期間自動發 log4j-core 升級 PR、auto-merge 必須有 functional + security 雙重 CI verify、不能單看 build pass</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/github-oauth-2022-token-supply-chain/" data-link-title="7.R7.2.2 GitHub OAuth 2022：第三方 token 供應鏈風險" data-link-desc="第三方整合 token 被竊後，如何形成跨組織存取風險">GitHub OAuth 2022 Token Supply Chain</a></td>
          <td>對照啟示 — Dependabot 自己用 GitHub token、需確認 Dependabot PR 不能讀 production secrets（GitHub 設計上已 read-only / empty secrets）</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/circleci-2023-secrets-rotation/" data-link-title="7.R7.2.3 CircleCI 2023：CI secrets 輪替壓力" data-link-desc="工程端點入侵後，CI 平台 secrets 如何成為高風險擴散點">CircleCI 2023 Secrets Rotation</a></td>
          <td>對照啟示 — CI 出事時 Dependabot secrets（私有 registry credential）也要 rotate、不是只 rotate Actions secrets</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/xz-backdoor-2024-open-source-supply-chain/" data-link-title="7.R7.2.4 XZ Backdoor 2024：開源供應鏈長期滲透" data-link-desc="開源維護鏈遭滲透後，為何會直接影響廣泛 Linux 發行流程">XZ Backdoor 2024</a></td>
          <td>對照啟示 — Dependabot auto-merge 隱含 maintainer trust、攻擊者控制 upstream 後升級 = 自動進 production；major 不 auto-merge + 重要 dep pin commit hash</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">7.12 供應鏈完整性與 Artifact 信任</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GitHub Advanced Security</a>、<a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk</a></li>
<li>下游：<a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a>（容器 scan）、<a href="/blog/backend/07-security-data-protection/vendors/syft-grype/" data-link-title="Syft &#43; Grype" data-link-desc="Anchore 開源姐妹工具：Syft 產 SBOM (CycloneDX / SPDX) &#43; Grype scan 漏洞、Unix philosophy、cosign attestation 整合">Syft / Grype</a>（SBOM）</li>
<li>跨類：artifact 簽章（Sigstore cosign）見 <a href="/blog/backend/07-security-data-protection/vendors/syft-grype/" data-link-title="Syft &#43; Grype" data-link-desc="Anchore 開源姐妹工具：Syft 產 SBOM (CycloneDX / SPDX) &#43; Grype scan 漏洞、Unix philosophy、cosign attestation 整合">Syft / Grype 頁的 SBOM attestation 段</a></li>
<li>跨模組：<a href="/blog/backend/06-reliability/" data-link-title="模組六：可靠性驗證流程" data-link-desc="用 SRE 領域詞彙建問題節點、以服務級案例庫累積驗證脈絡，先建概念與案例庫再進實作交接">6 可靠性驗證流程</a>（Dependabot PR 進 release flow 的 gate 設計）、<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a></li>
<li>官方：<a href="https://docs.github.com/en/code-security/dependabot">Dependabot Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>Google Cloud IAM</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/google-cloud-iam/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/google-cloud-iam/</guid><description>&lt;p>Google Cloud IAM 是 GCP 的 cloud resource permission engine、把 &lt;em>誰能對哪個 resource 做什麼&lt;/em> 統一成一個模型：Principal + Role + Resource scope 三件事拼成一個 &lt;em>role binding&lt;/em>。它跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta&lt;/a> 等 IdP 是兩層責任 — Okta 回答「這個人是誰」、Google IAM 回答「這個身份能對 GCP resource 做什麼」。設計上比 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM&lt;/a> 統一、沒有 resource-based policy vs identity-based policy 雙軌、也沒有 SCP / Permission Boundary 多層覆蓋、policy 評估路徑短而可預測。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Google Cloud IAM 的核心抽象是 &lt;em>role binding on a resource scope&lt;/em>：把 role grant 給 principal、生效範圍是某個 Organization / Folder / Project / 個別 resource、沿 resource hierarchy 向下繼承。同一個 principal 在不同 scope 可以有不同 role、有效權限是所有 binding 的 union。這跟 AWS IAM 的「identity policy + resource policy + SCP + boundary 多層 intersect / union」相比、推理成本低、但也意味著 &lt;em>guardrail 必須走 Organization Policy 這另一個系統&lt;/em> — 不是 IAM grant 的一部分。&lt;/p>
&lt;p>跟 Azure RBAC 相比、兩者都是 scope-based、都靠 hierarchy 繼承。差異在 &lt;em>Service Account 是 GCP 的 first-class identity&lt;/em>：有自己的 email、可被 impersonate、可以 grant role 給它也可以 grant &lt;code>iam.serviceAccountUser&lt;/code> 讓人類 act-as 它。Azure 的對應是 Managed Identity、語義接近但 impersonation chain 的表達更隱晦。選 GCP（= 用 Google Cloud IAM）的核心訴求通常是：BigQuery / Vertex AI / GKE workload、想用 Workload Identity Federation 取代 long-lived key、團隊偏好較統一的 policy 模型。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本頁、讀者能判斷：&lt;/p>
&lt;ol>
&lt;li>Google Cloud IAM 該承擔哪一段權限（resource access、service-to-service、cross-cloud federation）、哪一段該交給 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta&lt;/a> / IdP&lt;/li>
&lt;li>Role 的選擇順序（Predefined &amp;gt; Custom &amp;gt; Basic）與 IAM Conditions 何時補上&lt;/li>
&lt;li>Service Account / Workload Identity Federation 的信任邊界、何時不該再發 service account key&lt;/li>
&lt;li>何時改走 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/azure-rbac/" data-link-title="Azure RBAC &amp;#43; Entra ID" data-link-desc="Azure 雙層身份/權限體系、Entra ID（IdP）&amp;#43; Azure RBAC（resource permission）、Conditional Access、PIM、Managed Identity">Azure RBAC&lt;/a> / Organization Policy / VPC Service Controls&lt;/li>
&lt;/ol>
&lt;h2 id="最短判讀路徑">最短判讀路徑&lt;/h2>
&lt;p>判斷一個 GCP project 的 IAM 配置是否健康、最少看五件事：&lt;/p></description><content:encoded><![CDATA[<p>Google Cloud IAM 是 GCP 的 cloud resource permission engine、把 <em>誰能對哪個 resource 做什麼</em> 統一成一個模型：Principal + Role + Resource scope 三件事拼成一個 <em>role binding</em>。它跟 <a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a> 等 IdP 是兩層責任 — Okta 回答「這個人是誰」、Google IAM 回答「這個身份能對 GCP resource 做什麼」。設計上比 <a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM</a> 統一、沒有 resource-based policy vs identity-based policy 雙軌、也沒有 SCP / Permission Boundary 多層覆蓋、policy 評估路徑短而可預測。</p>
<h2 id="服務定位">服務定位</h2>
<p>Google Cloud IAM 的核心抽象是 <em>role binding on a resource scope</em>：把 role grant 給 principal、生效範圍是某個 Organization / Folder / Project / 個別 resource、沿 resource hierarchy 向下繼承。同一個 principal 在不同 scope 可以有不同 role、有效權限是所有 binding 的 union。這跟 AWS IAM 的「identity policy + resource policy + SCP + boundary 多層 intersect / union」相比、推理成本低、但也意味著 <em>guardrail 必須走 Organization Policy 這另一個系統</em> — 不是 IAM grant 的一部分。</p>
<p>跟 Azure RBAC 相比、兩者都是 scope-based、都靠 hierarchy 繼承。差異在 <em>Service Account 是 GCP 的 first-class identity</em>：有自己的 email、可被 impersonate、可以 grant role 給它也可以 grant <code>iam.serviceAccountUser</code> 讓人類 act-as 它。Azure 的對應是 Managed Identity、語義接近但 impersonation chain 的表達更隱晦。選 GCP（= 用 Google Cloud IAM）的核心訴求通常是：BigQuery / Vertex AI / GKE workload、想用 Workload Identity Federation 取代 long-lived key、團隊偏好較統一的 policy 模型。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>Google Cloud IAM 該承擔哪一段權限（resource access、service-to-service、cross-cloud federation）、哪一段該交給 <a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a> / IdP</li>
<li>Role 的選擇順序（Predefined &gt; Custom &gt; Basic）與 IAM Conditions 何時補上</li>
<li>Service Account / Workload Identity Federation 的信任邊界、何時不該再發 service account key</li>
<li>何時改走 <a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM</a> / <a href="/blog/backend/07-security-data-protection/vendors/azure-rbac/" data-link-title="Azure RBAC &#43; Entra ID" data-link-desc="Azure 雙層身份/權限體系、Entra ID（IdP）&#43; Azure RBAC（resource permission）、Conditional Access、PIM、Managed Identity">Azure RBAC</a> / Organization Policy / VPC Service Controls</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷一個 GCP project 的 IAM 配置是否健康、最少看五件事：</p>
<ul>
<li><strong>Principal 級別</strong>：誰是 Owner / Editor / Viewer（Basic Role 應該幾乎為空）、Service Account 是否獨立列管、有沒有 user 直接 grant 沒走 group</li>
<li><strong>Role 種類</strong>：Predefined Role 是 baseline、Custom Role 收斂 least privilege、Basic Role 視為待修；user-managed Service Account key 是否存在（理想是 0）</li>
<li><strong>Impersonation chain 展平稽核</strong>：誰有 <code>iam.serviceAccountTokenCreator</code> / <code>iam.serviceAccountUser</code> 對哪個 SA、間接 chain（A → B → C）展平後 <em>誰最終能 act as 高權限 SA</em>。這是 GCP IAM 最容易漏稽核的一條 — 直接 binding 看 Role、但 lateral movement 走 impersonation chain</li>
<li><strong>IAM Conditions</strong>：高敏 resource（prod bucket、KMS key、BigQuery dataset）是否用 condition expression 補 attribute-level 限制（resource name prefix、request time、IP）</li>
<li><strong>Audit Logs</strong>：Admin Activity 預設開、Data Access logs 在 sensitive resource 是否手動開、System Log 是否同步到 SIEM 並 alert role 變更與 service account key 建立</li>
</ul>
<p>五件事任一缺失、就是 <a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">Audit Log</a> 與 <a href="/blog/backend/knowledge-cards/authorization/" data-link-title="Authorization" data-link-desc="說明授權如何判斷誰能對哪些資源執行哪些操作">Authorization</a> 邊界的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>Role 選擇順序</strong>：Predefined Role 是 baseline、覆蓋 80% 場景；Custom Role 用於收斂 least privilege（例如只給 <code>bigquery.dataViewer</code> 的特定子集）；Basic Role（Owner / Editor / Viewer）幾乎不該再用 — Editor 預設帶寫權限到幾乎所有資源類型、Owner 還能改 IAM policy 本身、粒度過粗。Project 建立預設給的 Owner role 是 <em>人類自己 grant 自己</em>、不是無法避免的 baseline。</p>
<p><strong>Principal type</strong>：人類用 Google Workspace user / external user，群組走 Google Group（grant 給 group 比 grant 給 user 更穩、離職 lifecycle 由 IdP / HRIS 推 group 變更即可）。Service Account 是 <em>第一級身份</em>、跟 user 同等、有自己的 email（<code>name@project.iam.gserviceaccount.com</code>）、可被 grant role 也可被 impersonate。Workload identity（K8s SA、外部 OIDC subject）是 federation 層、不在 IAM 內直接列管、但 <em>最後仍 impersonate 一個 Service Account 來拿 GCP 權限</em>。</p>
<p><strong>IAM Conditions</strong>：在 role binding 上加 attribute-based 條件、補純 RBAC 不足。常見 expression：<code>resource.name.startsWith(&quot;projects/_/buckets/prod-&quot;)</code>、<code>request.time &lt; timestamp(&quot;2026-12-31T00:00:00Z&quot;)</code>、<code>resource.type == &quot;storage.googleapis.com/Bucket&quot;</code>。適合 <em>temporary access</em>、<em>resource name 範圍限定</em>、<em>環境隔離</em>；不適合複雜 ABAC 規則（會難以稽核、且 condition 只能用在支援的 resource type 上）。</p>
<p><strong>Service Account impersonation</strong>：人類或另一個 Service Account 透過 <code>iam.serviceAccountTokenCreator</code> role 借用目標 SA 的權限、不需要 SA key。impersonation chain 可以串（A 可 impersonate B、B 可 impersonate C）— 這條鏈是 lateral movement 風險、稽核時要展平看 <em>誰最終能 act as 高權限 SA</em>。對應 <a href="/blog/backend/07-security-data-protection/cases/failure-credential-rotation-without-scope/" data-link-title="7.C9 反例：憑證輪替未分 Scope" data-link-desc="憑證輪替若未分域分批，容易造成跨系統連鎖中斷。">Failure: Credential Rotation Without Scope</a> 的教訓：rotation 沒分域時、單點 SA compromise 會跨環境擴散。</p>
<p><strong>Workload Identity Federation（WIF）</strong>：GCP 接受外部 OIDC / SAML issuer（GitHub Actions、AWS、Azure、自管 K8s OIDC、CircleCI 等）發的 token、在 Workload Identity Pool 設 attribute mapping 後、外部 token 換成 short-lived GCP credential、最後 impersonate 指定 Service Account。是 <em>取代 SA JSON key 的 modern best practice</em>、CI / 跨雲 / 邊緣 workload 都該優先用。Trust 條件要鎖 <em>issuer + audience + subject</em>（例：<code>assertion.repository == &quot;myorg/myrepo&quot;</code>）— 缺一個就可能被同 issuer 下其他 subject 借用，這是 <a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/microsoft-storm-0558-2023-signing-key-chain/" data-link-title="7.R7.1.5 Microsoft Storm-0558 2023：簽章金鑰鏈與郵件存取" data-link-desc="從簽章金鑰保護失效到雲端郵件存取，拆解身分信任鏈的關鍵控制點">Microsoft Storm-0558 Signing Key Chain</a> 對 external OIDC 信任的提醒：發 token 的 issuer 一旦被攻破、所有信任它的 audience 都跟著受害。</p>
<p><strong>Service Account key（避免）</strong>：user-managed JSON key 是 long-lived credential、無 TTL、無 IP 限制、外洩偵測難。應該以 Workload Identity Federation 或 Service Account Impersonation 取代；若必須用、走 Organization Policy <code>iam.disableServiceAccountKeyCreation</code> 預設禁用、例外申請走 ticket、key 進 <a href="/blog/backend/knowledge-cards/secret-management/" data-link-title="Secret Management" data-link-desc="說明 token、key、password 與憑證如何保存、輪替與撤銷">Secret Management</a>、季度盤點未使用 key 刪除。</p>
<p><strong>Organization Policy（guardrail）</strong>：跟 IAM 完全不同層 — 不是 grant、是 <em>限制可以做什麼設定</em>。常用 constraint：<code>iam.disableServiceAccountKeyCreation</code>、<code>iam.allowedPolicyMemberDomains</code>（限制只能 grant 給特定 domain 的 principal）、<code>compute.vmExternalIpAccess</code>（限制 VM external IP）、<code>storage.publicAccessPrevention</code>。Org Policy 在 Organization / Folder / Project 層設定、IAM 即使想 grant 也擋得住。</p>
<p><strong>Audit / handoff</strong>：Admin Activity Log 預設開、不能關、保留 400 天免費；Data Access Log 預設關、開了會大量 log（也大量計費）— 對 sensitive resource（KMS key access、BigQuery dataset read、Secret Manager access）應該手動開；System Event Log 補基礎設施事件。三類都接 Cloud Logging sink 推到 SIEM、特別 alert 三件事 — IAM policy 變更、Service Account key 建立 / 上傳、Workload Identity Pool / Provider 變更。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Google Cloud IAM</th>
          <th>AWS IAM</th>
          <th>Azure RBAC</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Policy 模型</td>
          <td>Role binding on resource scope、單軌</td>
          <td>Identity policy + resource policy + SCP + boundary</td>
          <td>Scope-based、Management Group 階層</td>
      </tr>
      <tr>
          <td>表達力</td>
          <td>中等、IAM Conditions 補 attribute</td>
          <td>最高、policy language 表達 ABAC / 條件 / 否決</td>
          <td>中等、Azure Policy 補 ABAC</td>
      </tr>
      <tr>
          <td>Guardrail 機制</td>
          <td>Organization Policy（獨立系統、constraint）</td>
          <td>SCP（policy 同語法、separate plane）</td>
          <td>Azure Policy（獨立系統、constraint）</td>
      </tr>
      <tr>
          <td>Machine identity</td>
          <td>Service Account first-class + WIF</td>
          <td>IAM Role + STS AssumeRole + OIDC trust</td>
          <td>Managed Identity + Workload Identity Federation</td>
      </tr>
      <tr>
          <td>Cross-cloud federation</td>
          <td>WIF 接外部 OIDC 是 modern best practice</td>
          <td>OIDC trust on IAM Role、表達力強</td>
          <td>Federated credentials、近年補齊</td>
      </tr>
      <tr>
          <td>學習曲線</td>
          <td>較緩、模型統一</td>
          <td>陡、policy 評估順序複雜</td>
          <td>中等、scope inheritance 直覺</td>
      </tr>
      <tr>
          <td>推理 / 稽核成本</td>
          <td>低 — binding union、Org Policy 獨立看</td>
          <td>高 — 多層 intersect / union、需 policy simulator</td>
          <td>中 — scope 繼承明確、policy 分散</td>
      </tr>
  </tbody>
</table>
<p>選 Google Cloud IAM 的核心訴求：<em>已在 GCP 上、或想用 BigQuery / Vertex AI / GKE</em>、團隊偏好較統一的 policy 模型、跨雲場景靠 WIF 對外發 trust 而不維護多套 key。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Workload Identity Federation 的深層應用</strong>：除了 GitHub Actions、AWS、Azure 這類常見 issuer、WIF 也支援自管 K8s OIDC issuer（OSS K8s cluster 跑 GKE workload identity 等價物）、SaaS（Snowflake、Terraform Cloud）發的 OIDC token。trust 設定要鎖 issuer URL、audience、subject pattern 三件事 — 任何一個太寬都是同 issuer 下別人借用你 SA 的入口。</p>
<p><strong>Organization Policy 的 dry-run / 例外</strong>：constraint 可以先設 <code>dryRun</code> 觀察會擋掉哪些操作再 enforce；例外用 <em>exception folder</em>（特定 folder 不繼承上層 constraint）或 <em>condition</em>（特定 resource pattern 不擋）。直接全 org 一次 enforce 通常會打掉既有 workload、要分階段。</p>
<p><strong>IAM Conditions 的有限性</strong>：condition 只能用在支援的 resource type 上、不是全 GCP 通用；複雜 expression 難稽核（CEL 語法、不易讀）；condition 不能否決 — 只能限制 binding 的生效範圍、不能像 AWS policy 那樣寫 <code>Deny</code>。複雜 ABAC 場景該走 Organization Policy + 應用層授權邊界、不是把所有規則塞進 IAM Conditions。</p>
<p><strong>Service Account Impersonation chain 的稽核</strong>：列出 <em>有 <code>serviceAccountTokenCreator</code> 的 principal</em> 是基本；展平 chain（A → B → C）需要 graph walk 工具或 Policy Analyzer；高權限 SA（owner-equivalent custom role、跨 project 寫權限）的 impersonation 來源應該是 <em>寫死的少數 admin SA + break-glass</em>、不該開放給 CI / 一般 service。</p>
<p><strong>VPC Service Controls（資料邊界、跟 IAM 互補）</strong>：在 IAM 之外加 <em>資料 perimeter</em> — 即使 principal 有 IAM 權限、如果請求不是來自 perimeter 內（VPC、特定 IP、特定 service account），仍然會被擋。適合 BigQuery / GCS / Secret Manager 這類存資料的 service、防 <em>合法 credential 從外部 exfiltrate 資料</em>（<a href="/blog/backend/07-security-data-protection/cases/azure-ad-identity-control-plane-2021/" data-link-title="7.C3 Azure AD：2021 Identity Control-plane 事件" data-link-desc="身分控制面事件如何影響多服務信任鏈與回復優先序。">Azure AD Identity Control Plane 2021</a> 場景的下游補位：identity 控制面失守時、資料層仍有獨立 perimeter）。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Basic Role 還在用</strong>：Project Owner / Editor 散落、新人 onboard 直接 Editor — 改 group + Predefined Role、Basic Role 改成 break-glass 限定</li>
<li><strong>Service Account key 散落</strong>：CI 用 JSON key、key 進 git 或環境變數、無 rotation — 改 WIF（GitHub Actions / GitLab CI 都支援）、Org Policy 禁用 SA key 建立</li>
<li><strong>WIF trust 太寬</strong>：只鎖 issuer 沒鎖 subject、同 GitHub org 任何 repo 都能借用 SA — trust 要含 <code>assertion.repository</code>、<code>assertion.ref</code>（main branch only）等 condition</li>
<li><strong>IAM Conditions 越寫越多</strong>：condition expression 過度複雜、稽核時沒人讀得懂 — 簡化條件、把複雜規則上移到應用層或 Org Policy</li>
<li><strong>Data Access Logs 沒開</strong>：sensitive resource 出事時只有 Admin Activity、看不到 <em>誰讀了什麼</em> — KMS key、Secret Manager、BigQuery 高敏 dataset 必開 Data Access Log</li>
<li><strong>Impersonation chain 失控</strong>：太多人有 <code>serviceAccountTokenCreator</code> 到高權限 SA — 用 Policy Analyzer 展平、收斂到必要 admin + break-glass</li>
<li><strong>Org Policy 沒設</strong>：root org 沒有 baseline constraint、新建 project 預設可建 SA key / public IP / public bucket — 至少設 <code>disableServiceAccountKeyCreation</code> + <code>publicAccessPrevention</code> + <code>allowedPolicyMemberDomains</code></li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>人類身份的 SSO / MFA / lifecycle</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a> / IdP</td>
      </tr>
      <tr>
          <td>AWS resource permission</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM</a></td>
      </tr>
      <tr>
          <td>Azure resource permission</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/azure-rbac/" data-link-title="Azure RBAC &#43; Entra ID" data-link-desc="Azure 雙層身份/權限體系、Entra ID（IdP）&#43; Azure RBAC（resource permission）、Conditional Access、PIM、Managed Identity">Azure RBAC</a></td>
      </tr>
      <tr>
          <td>跨雲 unified IAM</td>
          <td>沒有單一答案 — 各雲 IAM + Workload Identity Federation 對接、或外部 PAM（Teleport / Boundary）</td>
      </tr>
      <tr>
          <td>Secret / Service Account key 治理</td>
          <td><a href="/blog/backend/07-security-data-protection/secrets-and-machine-credential-governance/" data-link-title="7.6 秘密管理與機器憑證治理" data-link-desc="以問題驅動方式整理 secret、token、key 與機器身份治理">7.6 秘密管理與機器憑證治理</a></td>
      </tr>
      <tr>
          <td>資料分類 / DLP / 匯出控制</td>
          <td><a href="/blog/backend/07-security-data-protection/data-protection-and-masking-governance/" data-link-title="7.4 資料保護與遮罩治理" data-link-desc="以問題驅動方式整理資料分級、遮罩、匯出與備份治理">7.4 資料保護與遮罩治理</a></td>
      </tr>
      <tr>
          <td>Workload runtime detection（容器、syscall）</td>
          <td>04 + Falco / Cilium Tetragon 類工具</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>各 Predefined Role 的完整權限清單與細部 permission 差異</li>
<li>IAM Conditions CEL 語法的完整 spec</li>
<li>Workload Identity Federation 跟特定 issuer（GitHub / AWS / Azure）的逐步設定教學</li>
<li>BigQuery / GCS / KMS 等服務的 service-specific IAM 行為細節</li>
<li>GCP 計費 / SKU 對 Audit Log 開關的影響</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 Google Cloud IAM 的關係</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/cases/azure-ad-identity-control-plane-2021/" data-link-title="7.C3 Azure AD：2021 Identity Control-plane 事件" data-link-desc="身分控制面事件如何影響多服務信任鏈與回復優先序。">Azure AD Identity Control Plane 2021</a></td>
          <td>Identity 控制面故障不直接打到 Google IAM、但設計啟示是 IAM evaluation 路徑必須 HA、且 VPC Service Controls 等資料 perimeter 是 identity 失守時的下游補位</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/cases/failure-credential-rotation-without-scope/" data-link-title="7.C9 反例：憑證輪替未分 Scope" data-link-desc="憑證輪替若未分域分批，容易造成跨系統連鎖中斷。">Failure: Credential Rotation Without Scope</a></td>
          <td>Service Account key、WIF provider 的 rotation 必須分域 — 跨 project / 跨環境的 SA 共用是 blast radius 放大器</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/microsoft-storm-0558-2023-signing-key-chain/" data-link-title="7.R7.1.5 Microsoft Storm-0558 2023：簽章金鑰鏈與郵件存取" data-link-desc="從簽章金鑰保護失效到雲端郵件存取，拆解身分信任鏈的關鍵控制點">Microsoft Storm-0558 Signing Key Chain</a></td>
          <td>對 WIF 的提醒 — 信任 external OIDC issuer 時、issuer 自己被攻破會打到所有 audience；trust condition 必須鎖 issuer + audience + subject 三件事</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/identity-access-boundary/" data-link-title="7.2 身分與授權邊界" data-link-desc="以問題驅動方式整理身分、授權、會話與供應商身分鏈">7.2 身分與授權邊界</a>、<a href="/blog/backend/07-security-data-protection/secrets-and-machine-credential-governance/" data-link-title="7.6 秘密管理與機器憑證治理" data-link-desc="以問題驅動方式整理 secret、token、key 與機器身份治理">7.6 秘密管理與機器憑證治理</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM</a>、<a href="/blog/backend/07-security-data-protection/vendors/azure-rbac/" data-link-title="Azure RBAC &#43; Entra ID" data-link-desc="Azure 雙層身份/權限體系、Entra ID（IdP）&#43; Azure RBAC（resource permission）、Conditional Access、PIM、Managed Identity">Azure RBAC</a>、<a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a>、<a href="/blog/backend/07-security-data-protection/vendors/aws-iam-identity-center/" data-link-title="AWS IAM Identity Center" data-link-desc="AWS 原生 workforce SSO、前 AWS SSO、Permission Set 跨帳號 access、可串外部 IdP federation">AWS IAM Identity Center</a></li>
<li>下游：<a href="/blog/backend/07-security-data-protection/secrets-and-machine-credential-governance/" data-link-title="7.6 秘密管理與機器憑證治理" data-link-desc="以問題驅動方式整理 secret、token、key 與機器身份治理">7.6 秘密管理與機器憑證治理</a>（Google Secret Manager / Google Cloud KMS 個別 vendor 頁 S2 批次撰寫中）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（GCP IAM 事件如何 routing 進 IR 流程）</li>
<li>官方：<a href="https://cloud.google.com/iam/docs">Google Cloud IAM Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>Microsoft Purview</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/microsoft-purview/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/microsoft-purview/</guid><description>&lt;p>Microsoft Purview 是 Microsoft 在 2022 年把原 Microsoft Information Protection (MIP)、Azure Purview data catalog、Microsoft 365 Compliance Center 合併後的統合品牌、定位是 &lt;em>跨 M365 / Azure / endpoint / 跨平台&lt;/em> 的 data governance + information protection + DLP + audit + insider risk 平台。它跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/google-dlp/" data-link-title="Google DLP" data-link-desc="GCP 原生 Sensitive Data Protection：infoType discovery &amp;#43; transformation (mask / FPE / tokenize / k-anonymity)、整合 BigQuery / GCS / Cloud SQL">Google DLP&lt;/a> 的本質差異在 &lt;em>控制層級&lt;/em>、功能列表反而看起來相似 — Purview 走 &lt;em>information protection&lt;/em>（document / email / collaboration tool 的 sensitivity label + endpoint inline 攔截）、Google DLP 走 &lt;em>infrastructure-level discovery + transformation&lt;/em>（GCS / BigQuery 的 content scan + de-identification）— 兩者層級不同、典型大型 Microsoft + GCP 混合環境會並存而非互斥。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Purview 的核心 first-class concept 是 &lt;em>sensitivity label&lt;/em> — 一個 label 帶動 encryption、access restriction、watermarking、DLP policy 多個控制、可由 user 手動標也可由 trainable classifier 自動標、跨 Office docs / SharePoint / Teams / Power BI / endpoint 繼承。其上的模組包含：&lt;em>Data Loss Prevention (DLP)&lt;/em> — 跨 Exchange / SharePoint / Teams / Endpoint / Microsoft Defender for Cloud Apps (MDA) 的 policy 引擎；&lt;em>Data Map / Data Catalog&lt;/em> — Azure / 多雲資料源 discovery + lineage；&lt;em>Unified Audit Log&lt;/em> — M365 + Azure AD + Defender 統一 audit；&lt;em>Insider Risk Management&lt;/em> — 行為 risk score 偵測內部威脅；&lt;em>Communication Compliance&lt;/em> — Teams / email 內容 review。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/google-dlp/" data-link-title="Google DLP" data-link-desc="GCP 原生 Sensitive Data Protection：infoType discovery &amp;#43; transformation (mask / FPE / tokenize / k-anonymity)、整合 BigQuery / GCS / Cloud SQL">Google DLP&lt;/a> 比、Purview 走 &lt;em>information protection 層 + label-driven + endpoint inline&lt;/em>、Google DLP 走 &lt;em>infrastructure 層 + content-based + transformation pipeline&lt;/em>。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &amp;#43; indexer &amp;#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk&lt;/a> 比、Purview 不是 SIEM — Unified Audit Log 是 &lt;em>event source&lt;/em>、Splunk 或 Microsoft Sentinel 才是 aggregation 平面；Purview audit 進 SIEM 是常見組合。跟&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/cloud-data-policy/" data-link-title="Cloud-native Data Policy (BigQuery &amp;#43; S3)" data-link-desc="BigQuery column / row-level security &amp;#43; S3 bucket policy &amp;#43; Access Points &amp;#43; Macie、雲端原生資料層 access control、跟 DLP / Purview 互補">雲端原生 data policy&lt;/a>（BigQuery Column-Level Security / S3 Block Public Access）比、Purview 跨平台 + label 統一、雲端原生只覆蓋單一雲、不同責任邊界。&lt;/p></description><content:encoded><![CDATA[<p>Microsoft Purview 是 Microsoft 在 2022 年把原 Microsoft Information Protection (MIP)、Azure Purview data catalog、Microsoft 365 Compliance Center 合併後的統合品牌、定位是 <em>跨 M365 / Azure / endpoint / 跨平台</em> 的 data governance + information protection + DLP + audit + insider risk 平台。它跟 <a href="/blog/backend/07-security-data-protection/vendors/google-dlp/" data-link-title="Google DLP" data-link-desc="GCP 原生 Sensitive Data Protection：infoType discovery &#43; transformation (mask / FPE / tokenize / k-anonymity)、整合 BigQuery / GCS / Cloud SQL">Google DLP</a> 的本質差異在 <em>控制層級</em>、功能列表反而看起來相似 — Purview 走 <em>information protection</em>（document / email / collaboration tool 的 sensitivity label + endpoint inline 攔截）、Google DLP 走 <em>infrastructure-level discovery + transformation</em>（GCS / BigQuery 的 content scan + de-identification）— 兩者層級不同、典型大型 Microsoft + GCP 混合環境會並存而非互斥。</p>
<h2 id="服務定位">服務定位</h2>
<p>Purview 的核心 first-class concept 是 <em>sensitivity label</em> — 一個 label 帶動 encryption、access restriction、watermarking、DLP policy 多個控制、可由 user 手動標也可由 trainable classifier 自動標、跨 Office docs / SharePoint / Teams / Power BI / endpoint 繼承。其上的模組包含：<em>Data Loss Prevention (DLP)</em> — 跨 Exchange / SharePoint / Teams / Endpoint / Microsoft Defender for Cloud Apps (MDA) 的 policy 引擎；<em>Data Map / Data Catalog</em> — Azure / 多雲資料源 discovery + lineage；<em>Unified Audit Log</em> — M365 + Azure AD + Defender 統一 audit；<em>Insider Risk Management</em> — 行為 risk score 偵測內部威脅；<em>Communication Compliance</em> — Teams / email 內容 review。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/google-dlp/" data-link-title="Google DLP" data-link-desc="GCP 原生 Sensitive Data Protection：infoType discovery &#43; transformation (mask / FPE / tokenize / k-anonymity)、整合 BigQuery / GCS / Cloud SQL">Google DLP</a> 比、Purview 走 <em>information protection 層 + label-driven + endpoint inline</em>、Google DLP 走 <em>infrastructure 層 + content-based + transformation pipeline</em>。跟 <a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> 比、Purview 不是 SIEM — Unified Audit Log 是 <em>event source</em>、Splunk 或 Microsoft Sentinel 才是 aggregation 平面；Purview audit 進 SIEM 是常見組合。跟<a href="/blog/backend/07-security-data-protection/vendors/cloud-data-policy/" data-link-title="Cloud-native Data Policy (BigQuery &#43; S3)" data-link-desc="BigQuery column / row-level security &#43; S3 bucket policy &#43; Access Points &#43; Macie、雲端原生資料層 access control、跟 DLP / Purview 互補">雲端原生 data policy</a>（BigQuery Column-Level Security / S3 Block Public Access）比、Purview 跨平台 + label 統一、雲端原生只覆蓋單一雲、不同責任邊界。</p>
<p>關鍵張力：<em>label 設計簡單度</em> ↔ <em>自動分類精準度</em> ↔ <em>使用者教育成本</em> 是 Purview 導入時最常踩的三角。label 太細（10+ 層 hierarchical）使用者選不出來、label 太粗（只有 Public / Internal / Confidential）DLP policy 觸發精度不夠。Trainable classifier + auto-labeling 是補救、但要投入訓練樣本維運。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>Purview 在 information protection stack 中承擔哪一段（label / DLP / audit / insider risk）、跟 <a href="/blog/backend/07-security-data-protection/vendors/azure-rbac/" data-link-title="Azure RBAC &#43; Entra ID" data-link-desc="Azure 雙層身份/權限體系、Entra ID（IdP）&#43; Azure RBAC（resource permission）、Conditional Access、PIM、Managed Identity">Azure RBAC + Entra ID</a> / SIEM / cloud-native policy 怎麼分工</li>
<li>Sensitivity label 的層級設計（粗細、auto-label 條件、跨 Office / endpoint / Power BI 一致性）</li>
<li>DLP policy 的 location + condition + action 三軸如何配置、跟 endpoint DLP / MDA 怎麼覆蓋 SaaS shadow IT</li>
<li>Purview 計費分 SKU 的 trap、E3 + add-on vs E5 license 的決策</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Purview deployment 是否健康、最少看四件事：</p>
<ul>
<li><strong>Label 層級設計</strong>：sensitivity label 幾層、是否 hierarchical（parent / sublabel）、是否定義 auto-labeling 條件（含某 SIT、來自某 SharePoint site、某 user group 建立）、跨 Office / endpoint / Power BI / Teams 是否一致繼承</li>
<li><strong>DLP policy coverage</strong>：location 是否涵蓋 Exchange + SharePoint + Teams + Endpoint + MDA、condition 是否用 SIT + label 雙軸（而非只看 SIT）、action 是否依風險分層（block / warn / encrypt / audit-only）</li>
<li><strong>Audit + Insider Risk 證據鏈</strong>：Unified Audit Log retention 是否足夠（預設 180 天、E5 可到 1 年、長期要 archive）、Insider Risk policy 是否定義「離職前 30 天 mass download」「異常時段 access」等 organization-specific pattern、是否 export 進 SIEM</li>
<li><strong>License 跟模組對應</strong>：Information Protection / DLP / Insider Risk / Communication Compliance 屬不同 SKU、是否買到所需模組、E3 + add-on 還是 E5、避免「policy 寫好但 license 沒解鎖功能」</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/07-security-data-protection/data-protection-and-masking-governance/" data-link-title="7.4 資料保護與遮罩治理" data-link-desc="以問題驅動方式整理資料分級、遮罩、匯出與備份治理">Data Protection and Masking Governance</a> 邊界的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>Sensitivity label 是 first-class control</strong>：label 不只是 metadata、而是 <em>單一 identifier 帶動多個控制</em> — 標到 document 後同時觸發 AES encryption（透過 Azure Rights Management）、access restriction（誰能開 / 列印 / 轉寄）、watermarking、DLP policy condition、Power BI dataset 繼承。Hierarchical label（Confidential → Confidential\Finance、Confidential\Legal）讓子部門客製、但層級超過 3 層使用者選擇困難。Label 設計要先決定 <em>跨 BU 共用 base set + 每 BU 自家 sublabel</em> 的拓撲、不是一次列 20 個。</p>
<p><strong>Trainable classifier 補 SIT 不足</strong>：預定義 SIT（Sensitive Information Type、如 credit card / SSN / passport）涵蓋通用 PII / PCI、但 organization-specific 敏感資料（內部 product spec、合約模板、未公開財報草稿）SIT 抓不到。Trainable classifier 用 ML 訓練 — 提供 50-500 個正例 + 反例、Purview 訓 classifier、跑 staging 驗證 precision / recall 達標再 promote。維運成本是樣本要定期 refresh、business 變動時 classifier 會 drift。</p>
<p><strong>DLP policy = location + condition + action</strong>：location（Exchange email / SharePoint site / Teams chat / OneDrive / Endpoint / MDA-managed SaaS）決定 <em>在哪攔</em>、condition（含某 SIT N 次 / 標 Confidential / 來自外部 user / 含某 trainable classifier 命中）決定 <em>何時觸發</em>、action（block + notify / encrypt / quarantine / audit-only / require justification）決定 <em>怎麼處理</em>。production 不該一上來就 block — 先 audit-only 跑 2 週收集 baseline、tune false positive、再 promote 到 warn、最後選擇性 block 高風險 condition。</p>
<p><strong>Endpoint DLP（Windows / macOS）</strong>：透過 Microsoft Defender for Endpoint agent 在端點 inline 攔截 — copy to USB / upload to non-corp cloud（Dropbox / Google Drive personal）/ print / paste to browser、針對標 Confidential 的 document 自動 block 或 warn。跟 <a href="/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &#43; CSPM &#43; CWS &#43; AAP &#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Security</a> 的 Sensitive Data Scanner 不同層 — 後者 scan log / APM payload 事後發現、Endpoint DLP 事前在 user action 攔截。Endpoint DLP 要 Defender for Endpoint license + Purview Endpoint DLP add-on 雙重 license、容易踩計費 trap。</p>
<p><strong>Microsoft Defender for Cloud Apps (MDA) 整合</strong>：MDA 是 Microsoft 的 CASB（Cloud Access Security Broker）、把 Purview DLP policy 延伸到非 Microsoft 的 SaaS（Salesforce / Box / Slack / Google Workspace）。MDA 透過 API connector 或 reverse proxy 攔截 SaaS 上的 sensitive document、套 Purview label / DLP action。覆蓋 shadow IT 跟 third-party SaaS 是 MDA 的價值、但每個 connector 都要單獨配置 + 維運。</p>
<p><strong>Data Map / Data Catalog discovery + lineage</strong>：Purview Data Map 自動掃描 Azure Storage / Synapse / SQL DB / Power BI / 部分 AWS / GCP 資料源、產 metadata + classification + lineage。跟 information protection 模組是不同 surface — Data Map 偏 <em>data governance</em>（誰擁有什麼資料、資料流向哪）、information protection 偏 <em>control</em>（誰能存取、能否 export）。中大型組織通常分開 onboard、不要一次全推。</p>
<p><strong>Unified Audit Log 是 SIEM source</strong>：M365 + Azure AD + Defender + Purview 自身的 audit event 統一進 Unified Audit Log、可透過 Compliance Center search、或 Office 365 Management Activity API export 到 <a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / Sentinel / <a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a>。Purview 自己不做 correlation / alerting、要做跨來源 detection 必須接 SIEM。Retention 預設 180 天、E5 license 1 年、長期合規要走 Audit Premium 或 archive 到 long-term storage。</p>
<p><strong>Insider Risk Management 跟 SIEM 互補</strong>：SIEM 主軸是 <em>external threat + cross-source correlation</em>、Insider Risk 主軸是 <em>single-user 行為 risk score over time</em> — 離職前 30 天 mass download、異常時段存取 sensitive folder、跨 sensitivity tier 大量 access。Risk score 累積到 threshold 觸發 case、進 Compliance officer review queue。預定義 policy template（departing employee、disgruntled employee、data leak）可快速 onboard、organization-specific pattern 要自己定。</p>
<p><strong>跟 <a href="/blog/backend/07-security-data-protection/vendors/azure-rbac/" data-link-title="Azure RBAC &#43; Entra ID" data-link-desc="Azure 雙層身份/權限體系、Entra ID（IdP）&#43; Azure RBAC（resource permission）、Conditional Access、PIM、Managed Identity">Azure RBAC + Entra ID</a> 整合</strong>：Purview policy 的 user / group 引用直接吃 Entra ID identity、sensitivity label 的 access restriction 也走 Entra ID group。Compliance / Information Protection admin 是 Entra ID role、應該收緊到少數人 + 走 PIM (Privileged Identity Management) just-in-time elevation。Break-glass account 要單獨設計、不能跟日常運維混。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Microsoft Purview</th>
          <th>Google DLP</th>
          <th>Splunk</th>
          <th>雲端原生 data policy（BigQuery / S3）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>控制層級</td>
          <td>Information protection（document / label）</td>
          <td>Infrastructure（content scan + transform）</td>
          <td>Detection / aggregation</td>
          <td>Resource policy（column / object 級別）</td>
      </tr>
      <tr>
          <td>核心抽象</td>
          <td>Sensitivity label + DLP policy</td>
          <td>InfoType + de-identification</td>
          <td>SPL + correlation rule</td>
          <td>IAM policy + column tag</td>
      </tr>
      <tr>
          <td>覆蓋面</td>
          <td>M365 + Endpoint + MDA-managed SaaS + Azure</td>
          <td>GCS / BigQuery / Pub/Sub / 任意 API content</td>
          <td>任意 log source</td>
          <td>單一雲服務內</td>
      </tr>
      <tr>
          <td>計費模型</td>
          <td>Per-user license（E3 + add-on / E5、模組分 SKU）</td>
          <td>Per-GB scan + per-API call</td>
          <td>Per-GB ingestion</td>
          <td>多半免費 / 服務內計費</td>
      </tr>
      <tr>
          <td>自動分類</td>
          <td>Trainable classifier + 預定義 SIT</td>
          <td>InfoType detector（150+ 預定義 + custom）</td>
          <td>不做分類</td>
          <td>Column tag 手動 / catalog 工具自動</td>
      </tr>
      <tr>
          <td>Endpoint inline</td>
          <td>強 — Endpoint DLP（Win/macOS）</td>
          <td>無（基礎設施層）</td>
          <td>無（觀測層）</td>
          <td>無</td>
      </tr>
      <tr>
          <td>Shadow IT 覆蓋</td>
          <td>強 — 透過 MDA CASB</td>
          <td>弱 — 限 GCP / API 整合</td>
          <td>無</td>
          <td>無</td>
      </tr>
      <tr>
          <td>退場成本</td>
          <td>高 — label 嵌入 document、跨 M365 黏著</td>
          <td>中 — InfoType pattern 可移植</td>
          <td>高 — SPL / detection content</td>
          <td>低 — IAM policy 較通用</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>M365 / Office / collaboration 為主、insider risk</td>
          <td>Infrastructure data + multi-cloud + GCP</td>
          <td>SIEM / SOC</td>
          <td>單一雲服務內 fine-grained access</td>
      </tr>
  </tbody>
</table>
<p>選 Purview 的核心訴求：<em>M365 / Office / collaboration 為主、需要 label 統一控制跨 document / email / Teams / endpoint、insider risk 是主要威脅、且能買到 E5 或對應 add-on</em>。Non-Microsoft 環境或 infrastructure data 為主（BigQuery / S3）走 <a href="/blog/backend/07-security-data-protection/vendors/google-dlp/" data-link-title="Google DLP" data-link-desc="GCP 原生 Sensitive Data Protection：infoType discovery &#43; transformation (mask / FPE / tokenize / k-anonymity)、整合 BigQuery / GCS / Cloud SQL">Google DLP</a> / cloud-native policy 更直接、不要硬塞 Purview。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Trainable classifier 的 lifecycle</strong>：classifier 不是 train 一次永久用、business context 變化（產品線改、合約模板更新、合規詞彙變）會讓 precision / recall 下降。Production 應定期 review classifier hit / miss、補新樣本 retrain、跟 SIT 互補不是替代 — 通用 PII 走 SIT 穩定、organization-specific 走 trainable classifier。Staging 跑 2 週驗證 false positive &lt; threshold 才 promote。</p>
<p><strong>Endpoint DLP 跟 <a href="/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &#43; CSPM &#43; CWS &#43; AAP &#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Security</a> Sensitive Data Scanner 的不同層</strong>：Endpoint DLP 在 user action 當下攔截（copy / upload / print）、Datadog Sensitive Data Scanner 在 log / APM ingestion 時 scrub。兩者不互斥 — Endpoint DLP 防 <em>資料離開端點</em>、Datadog Scanner 防 <em>PII 寫進觀測 log</em>、典型 Microsoft + Datadog 環境會並存。</p>
<p><strong>Data Loss Prevention for Power BI</strong>：Power BI dataset / report 可繼承 Purview sensitivity label、export to Excel / PDF 時 label 跟著走、DLP policy 可條件 <em>標 Highly Confidential 的 dataset 不能 export</em>。是 Microsoft analytics stack 比 Tableau / Looker 在 information protection 上的關鍵優勢。</p>
<p><strong>Information Barriers（內部 walled garden）</strong>：合規場景（投行 research vs trading desk、law firm 對手客戶）需 organization 內部某 group 不能 Teams 對話 / 不能 share 檔案、Purview Information Barriers 設定 segment + policy 阻擋。是 compliance-specific feature、非合規環境用不到、但金融 / 法律 / 顧問業是 must-have。</p>
<p><strong>E3 + add-on vs E5 的計費決策</strong>：Purview 完整功能（trainable classifier、Endpoint DLP、Insider Risk、Communication Compliance、Audit Premium）要 E5 license、單價約 E3 的 1.5 倍。中小組織從 E3 + 個別 add-on（Information Protection and Governance E5、Insider Risk Management E5）起步、避免一次 E5 全推；大組織直接 E5 反而簡化計費跟 license 管理。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>DLP policy 寫好但沒觸發</strong>：condition 或 location 設錯（policy 只覆蓋 Exchange 沒包 SharePoint）、或 license 沒解鎖該模組（Endpoint DLP 要額外 add-on）— 在 Compliance Center 看 policy match 統計、確認 license 對應</li>
<li><strong>使用者抱怨 label 選不出來 / 選錯</strong>：label 層級太細 + 沒有預設 label、user 不知該選哪個 — 簡化到 3-5 個 base label、用 auto-labeling 補自動分類、加 label tooltip</li>
<li><strong>Trainable classifier false positive 多</strong>：訓練樣本不足 / 正反例失衡 — 補樣本到 50+ per class、retrain、staging 跑 2 週驗證再 promote</li>
<li><strong>Audit log retention 不夠 / 合規查不到</strong>：預設 180 天、合規要 1 年以上 — 升 E5 或 Audit Premium、或 export 到 SIEM / long-term storage</li>
<li><strong>Insider Risk policy 太敏感 / 太多 case</strong>：預設 template 沒 tune organization baseline — 跑 audit-only 模式 30 天統計、調 threshold、加 user group 排除（VIP / legitimate bulk download role）</li>
<li><strong>Endpoint DLP 攔到合法業務操作</strong>：policy 沒區分 corp managed device vs BYOD、或沒給 user override + justification — 加 device compliance condition、設 warn + justification 而非直接 block</li>
<li><strong>MDA connector 落後 SaaS 新功能</strong>：API connector 有 lag、新功能未涵蓋 — 對高風險 SaaS 補 reverse proxy 模式、或在 SaaS 側設原生 DLP</li>
<li><strong>License 模組混亂</strong>：policy 寫好但功能沒解鎖、admin 不知道哪些要 E5 — 維護 license-to-feature 對照表、Compliance Center 警示「需要 license」要直接修</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Infrastructure data（GCS / BigQuery）</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/google-dlp/" data-link-title="Google DLP" data-link-desc="GCP 原生 Sensitive Data Protection：infoType discovery &#43; transformation (mask / FPE / tokenize / k-anonymity)、整合 BigQuery / GCS / Cloud SQL">Google DLP</a></td>
      </tr>
      <tr>
          <td>SIEM / cross-source correlation</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / Microsoft Sentinel</td>
      </tr>
      <tr>
          <td>Observability log PII scrubbing</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &#43; CSPM &#43; CWS &#43; AAP &#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Security</a></td>
      </tr>
      <tr>
          <td>單一雲 column / object 級別權限</td>
          <td>BigQuery Column-Level Security / S3 Block Public Access</td>
      </tr>
      <tr>
          <td>AWS-centric data protection</td>
          <td>AWS Macie / <a href="/blog/backend/07-security-data-protection/vendors/aws-kms/" data-link-title="AWS KMS" data-link-desc="AWS 原生 key management service、envelope encryption / digital signing / Multi-Region Key、Key Policy &#43; Grant 雙軌授權">AWS KMS</a></td>
      </tr>
      <tr>
          <td>Endpoint detection 為主（不只 DLP）</td>
          <td>CrowdStrike Falcon / Microsoft Defender for Endpoint</td>
      </tr>
      <tr>
          <td>Incident routing</td>
          <td><a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Microsoft 365 / Azure AD 完整管理（屬 <a href="/blog/backend/07-security-data-protection/vendors/azure-rbac/" data-link-title="Azure RBAC &#43; Entra ID" data-link-desc="Azure 雙層身份/權限體系、Entra ID（IdP）&#43; Azure RBAC（resource permission）、Conditional Access、PIM、Managed Identity">Azure RBAC + Entra ID</a>）</li>
<li>eDiscovery 跟法律 hold 流程細節</li>
<li>Microsoft Sentinel SIEM 完整配置（屬 SIEM 群、跟 Purview 是互補不是同一頁）</li>
<li>Purview Data Map 對非 Azure 資料源（AWS / GCP / on-prem）的完整 connector 矩陣</li>
<li>Compliance Manager 的法規對照與 scoring 細節</li>
<li>Azure Information Protection (AIP) 舊版 client 的 migration 流程</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>Purview 在 07 案例庫沒有直接 vendor-level 事件、但 information protection + insider risk 角度跟多個案例對照：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 Purview 的關係（對照啟示）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/data-exfiltration/mailchimp-2023-support-tool-abuse/" data-link-title="7.R7.4.4 Mailchimp 2023：支援工具路徑與客戶資料風險" data-link-desc="社交工程進入客服工具後，如何形成特定客戶資料存取風險">Mailchimp 2023 Support Tool Abuse</a></td>
          <td>客服系統客戶資料應標「Customer Confidential」label、DLP policy 自動阻擋大量匯出、Insider Risk Management 偵測異常 operator 行為</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/data-exfiltration/snowflake-2024-credential-abuse/" data-link-title="7.R7.4.2 Snowflake 2024：憑證濫用與資料竊取" data-link-desc="外洩憑證與 MFA 缺口如何在資料平台形成高風險外送事件">Snowflake 2024 Credential Abuse</a></td>
          <td>Endpoint DLP 在 Microsoft 端點攔截從 Snowflake 下載到 USB / personal cloud 的大量資料；對照啟示是「資料平台外洩仍可在 endpoint 端補位攔截」、不是依賴 Snowflake 自身控制</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/cases/okta-support-system-incident-2023/" data-link-title="7.C5 Okta：2023 Support System 事件" data-link-desc="支援系統憑證風險如何擴散到客戶租戶的案例。">Okta Support System 2023</a></td>
          <td>Unified Audit Log 紀錄 support tool 高風險操作、Insider Risk 偵測異常 pattern、跟 SIEM 串接做 cross-source correlation</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/data-protection-and-masking-governance/" data-link-title="7.4 資料保護與遮罩治理" data-link-desc="以問題驅動方式整理資料分級、遮罩、匯出與備份治理">Data Protection and Masking Governance (section)</a></td>
          <td>Sensitivity label + DLP policy 是 information protection 的工具、跟 Google DLP transformation 不同層、可並存</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/audit-trail-and-accountability-boundary/" data-link-title="7.7 稽核追蹤與責任邊界" data-link-desc="以問題驅動方式整理高風險操作追蹤、可回查與責任切分">Audit Trail and Accountability Boundary (section)</a></td>
          <td>Unified Audit Log 是 accountability evidence chain、retention 跟 export 設計是合規證據可用性的關鍵</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/data-protection-and-masking-governance/" data-link-title="7.4 資料保護與遮罩治理" data-link-desc="以問題驅動方式整理資料分級、遮罩、匯出與備份治理">7.4 資料保護與遮罩治理</a>、<a href="/blog/backend/07-security-data-protection/audit-trail-and-accountability-boundary/" data-link-title="7.7 稽核追蹤與責任邊界" data-link-desc="以問題驅動方式整理高風險操作追蹤、可回查與責任切分">7.8 稽核軌跡與責任邊界</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/google-dlp/" data-link-title="Google DLP" data-link-desc="GCP 原生 Sensitive Data Protection：infoType discovery &#43; transformation (mask / FPE / tokenize / k-anonymity)、整合 BigQuery / GCS / Cloud SQL">Google DLP</a>（infrastructure 層 DLP、跟 Purview 並存）、<a href="/blog/backend/07-security-data-protection/vendors/cloud-data-policy/" data-link-title="Cloud-native Data Policy (BigQuery &#43; S3)" data-link-desc="BigQuery column / row-level security &#43; S3 bucket policy &#43; Access Points &#43; Macie、雲端原生資料層 access control、跟 DLP / Purview 互補">Cloud-native Data Policy (BigQuery + S3)</a>（resource-bound access control、跟 Purview label-driven 互補）</li>
<li>下游：<a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / <a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a>（Unified Audit Log export 進 SIEM）</li>
<li>跨類：<a href="/blog/backend/07-security-data-protection/vendors/azure-rbac/" data-link-title="Azure RBAC &#43; Entra ID" data-link-desc="Azure 雙層身份/權限體系、Entra ID（IdP）&#43; Azure RBAC（resource permission）、Conditional Access、PIM、Managed Identity">Azure RBAC + Entra ID</a>（identity 基底）、<a href="/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &#43; CSPM &#43; CWS &#43; AAP &#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Security</a>（log PII scrubbing、不同層互補）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（Insider Risk case → IR routing）</li>
<li>官方：<a href="https://learn.microsoft.com/en-us/purview/">Microsoft Purview Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>SQLite</title><link>https://tarrragon.github.io/blog/backend/01-database/vendors/sqlite/</link><pubDate>Wed, 13 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/01-database/vendors/sqlite/</guid><description>&lt;p>SQLite 是世界上部署最多的 DB（手機、瀏覽器、car、IoT 都有）。傳統定位是 embedded、單檔案與低操作成本資料庫；multi-tenant 網路服務通常會先看 PostgreSQL、MySQL 或 managed SQL。但近年因 Cloudflare D1（serverless SQLite）、Turso（distributed SQLite）、Litestream（SQLite replication）等服務興起，出現「SQLite as production DB」的新場景。&lt;/p>
&lt;h2 id="教學路線單檔正式狀態與-local-first">教學路線：單檔正式狀態與 local-first&lt;/h2>
&lt;p>SQLite 服務頁的教學目標是把單機、單檔案、edge、desktop、test fixture 的正式狀態責任說清楚。讀者讀完後要能判斷 SQLite 何時是 production state，何時要轉向 server database、edge KV 或分散式 SQLite 變體。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>學習段&lt;/th>
 &lt;th>核心問題&lt;/th>
 &lt;th>對應段落&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Embedded state&lt;/td>
 &lt;td>單檔案資料庫如何成為 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/source-of-truth/" data-link-title="Source of Truth" data-link-desc="說明正式資料來源如何決定資料判斷、修復與一致性責任">source of truth&lt;/a>&lt;/td>
 &lt;td>定位、適用場景&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Local-first&lt;/td>
 &lt;td>device、edge、desktop、test fixture 的責任形狀&lt;/td>
 &lt;td>適用場景、案例對照&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Writer boundary&lt;/td>
 &lt;td>single writer、file lock、WAL 如何決定服務上限&lt;/td>
 &lt;td>容量特性、容量規劃要點&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Distributed variants&lt;/td>
 &lt;td>Turso、LiteFS、rqlite、D1 解決哪類同步或 edge 問題&lt;/td>
 &lt;td>跟其他 vendor 的取捨、章節群結構&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>替代路由&lt;/td>
 &lt;td>何時升級 PostgreSQL、MySQL、DynamoDB 或 edge KV&lt;/td>
 &lt;td>不適用場景、下一步路由&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="定位單檔案-embedded--新興分散式-sqlite-生態">定位：單檔案 embedded + 新興分散式 SQLite 生態&lt;/h2>
&lt;p>SQLite 跟 PostgreSQL / MySQL 承擔不同層級的資料責任：&lt;/p>
&lt;ul>
&lt;li>以 function-call API 使用，省掉 server process&lt;/li>
&lt;li>單一檔案（含 schema、data、index、metadata）&lt;/li>
&lt;li>無 user / role / connection 概念&lt;/li>
&lt;li>同 process 同時 read / write 受 file lock 限制&lt;/li>
&lt;/ul>
&lt;p>傳統定位：test fixture、CLI tool data store、mobile app（iOS / Android 內建）、edge device。&lt;/p>
&lt;p>新興定位：edge serverless（Cloudflare D1）、distributed SQLite（Turso、rqlite）、replicated SQLite（Litestream）。&lt;/p>
&lt;h2 id="容量特性">容量特性&lt;/h2>
&lt;p>&lt;strong>單檔案上限&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>DB 最大 281 TB（理論）&lt;/li>
&lt;li>實務上單表 &amp;gt; 100 GB 開始有 vacuum / index 問題&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>並發寫&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>WAL mode：可同時多 reader + 1 writer&lt;/li>
&lt;li>寫入仍由 single writer boundary 控制&lt;/li>
&lt;li>寫吞吐受 disk fsync 限制（通常 &amp;lt; 1K WPS）&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>並發讀&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>WAL mode 多 reader 可同時跑&lt;/li>
&lt;li>read-only workload 可以撐高吞吐&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Cross-process / cross-instance&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>多個 process / instance 同時寫同一檔案會破壞 single writer boundary&lt;/li>
&lt;li>需要分散時用 Litestream（replication）或 Turso（distributed）&lt;/li>
&lt;/ul>
&lt;h2 id="適用場景">適用場景&lt;/h2>
&lt;p>&lt;strong>1. Test fixture / CI 用 DB&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>整合測試需要的 fixed DB&lt;/li>
&lt;li>比 spin up PostgreSQL container 快&lt;/li>
&lt;li>對應 &lt;a href="https://tarrragon.github.io/blog/backend/01-database/repository-adapter/" data-link-title="1.4 Repository Adapter 實作" data-link-desc="Port / Adapter 邊界、row mapping、error translation、ORM vs query builder 選型、contract test 設計">1.4 Repository Adapter&lt;/a> 的 contract test 模式&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>2. CLI tool / desktop app 內建 store&lt;/strong>：&lt;/p></description><content:encoded><![CDATA[<p>SQLite 是世界上部署最多的 DB（手機、瀏覽器、car、IoT 都有）。傳統定位是 embedded、單檔案與低操作成本資料庫；multi-tenant 網路服務通常會先看 PostgreSQL、MySQL 或 managed SQL。但近年因 Cloudflare D1（serverless SQLite）、Turso（distributed SQLite）、Litestream（SQLite replication）等服務興起，出現「SQLite as production DB」的新場景。</p>
<h2 id="教學路線單檔正式狀態與-local-first">教學路線：單檔正式狀態與 local-first</h2>
<p>SQLite 服務頁的教學目標是把單機、單檔案、edge、desktop、test fixture 的正式狀態責任說清楚。讀者讀完後要能判斷 SQLite 何時是 production state，何時要轉向 server database、edge KV 或分散式 SQLite 變體。</p>
<table>
  <thead>
      <tr>
          <th>學習段</th>
          <th>核心問題</th>
          <th>對應段落</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Embedded state</td>
          <td>單檔案資料庫如何成為 <a href="/blog/backend/knowledge-cards/source-of-truth/" data-link-title="Source of Truth" data-link-desc="說明正式資料來源如何決定資料判斷、修復與一致性責任">source of truth</a></td>
          <td>定位、適用場景</td>
      </tr>
      <tr>
          <td>Local-first</td>
          <td>device、edge、desktop、test fixture 的責任形狀</td>
          <td>適用場景、案例對照</td>
      </tr>
      <tr>
          <td>Writer boundary</td>
          <td>single writer、file lock、WAL 如何決定服務上限</td>
          <td>容量特性、容量規劃要點</td>
      </tr>
      <tr>
          <td>Distributed variants</td>
          <td>Turso、LiteFS、rqlite、D1 解決哪類同步或 edge 問題</td>
          <td>跟其他 vendor 的取捨、章節群結構</td>
      </tr>
      <tr>
          <td>替代路由</td>
          <td>何時升級 PostgreSQL、MySQL、DynamoDB 或 edge KV</td>
          <td>不適用場景、下一步路由</td>
      </tr>
  </tbody>
</table>
<h2 id="定位單檔案-embedded--新興分散式-sqlite-生態">定位：單檔案 embedded + 新興分散式 SQLite 生態</h2>
<p>SQLite 跟 PostgreSQL / MySQL 承擔不同層級的資料責任：</p>
<ul>
<li>以 function-call API 使用，省掉 server process</li>
<li>單一檔案（含 schema、data、index、metadata）</li>
<li>無 user / role / connection 概念</li>
<li>同 process 同時 read / write 受 file lock 限制</li>
</ul>
<p>傳統定位：test fixture、CLI tool data store、mobile app（iOS / Android 內建）、edge device。</p>
<p>新興定位：edge serverless（Cloudflare D1）、distributed SQLite（Turso、rqlite）、replicated SQLite（Litestream）。</p>
<h2 id="容量特性">容量特性</h2>
<p><strong>單檔案上限</strong>：</p>
<ul>
<li>DB 最大 281 TB（理論）</li>
<li>實務上單表 &gt; 100 GB 開始有 vacuum / index 問題</li>
</ul>
<p><strong>並發寫</strong>：</p>
<ul>
<li>WAL mode：可同時多 reader + 1 writer</li>
<li>寫入仍由 single writer boundary 控制</li>
<li>寫吞吐受 disk fsync 限制（通常 &lt; 1K WPS）</li>
</ul>
<p><strong>並發讀</strong>：</p>
<ul>
<li>WAL mode 多 reader 可同時跑</li>
<li>read-only workload 可以撐高吞吐</li>
</ul>
<p><strong>Cross-process / cross-instance</strong>：</p>
<ul>
<li>多個 process / instance 同時寫同一檔案會破壞 single writer boundary</li>
<li>需要分散時用 Litestream（replication）或 Turso（distributed）</li>
</ul>
<h2 id="適用場景">適用場景</h2>
<p><strong>1. Test fixture / CI 用 DB</strong>：</p>
<ul>
<li>整合測試需要的 fixed DB</li>
<li>比 spin up PostgreSQL container 快</li>
<li>對應 <a href="/blog/backend/01-database/repository-adapter/" data-link-title="1.4 Repository Adapter 實作" data-link-desc="Port / Adapter 邊界、row mapping、error translation、ORM vs query builder 選型、contract test 設計">1.4 Repository Adapter</a> 的 contract test 模式</li>
</ul>
<p><strong>2. CLI tool / desktop app 內建 store</strong>：</p>
<ul>
<li>Chrome / Firefox（cookies、history、bookmark）、Fossil SCM、iOS app</li>
<li>省掉 server、單檔案攜帶</li>
</ul>
<p><strong>3. Mobile app（iOS / Android）</strong>：</p>
<ul>
<li>iOS Core Data 底層用 SQLite</li>
<li>Android 自帶 SQLite API</li>
<li>offline-first app 的標準</li>
</ul>
<p><strong>4. Single-instance backend（特殊場景）</strong>：</p>
<ul>
<li>流量小 + HA 由備份 / restore / redeploy 流程承擔</li>
<li>例：Sidekick / 個人 SaaS / family-scale app</li>
<li>配合 Litestream 做 backup / DR</li>
</ul>
<p><strong>5. Edge / serverless（新興）</strong>：</p>
<ul>
<li>Cloudflare D1：edge SQLite、跟 Workers 整合</li>
<li>Turso：distributed SQLite、跨 region replication</li>
<li>跟傳統 SQLite 不同等級、是 <em>新的 product</em></li>
</ul>
<p><strong>6. Embedded device / IoT</strong>：</p>
<ul>
<li>沒網路或要降低 server 依賴</li>
<li>SQLite 內建、無 external dependency</li>
</ul>
<h2 id="不適用場景">不適用場景</h2>
<p><strong>1. 多 instance / 多 region web service</strong>：</p>
<ul>
<li>SQLite 的單檔模型以單 instance writer 為主要邊界</li>
<li>替代：PostgreSQL、Aurora、Spanner、CockroachDB</li>
</ul>
<p><strong>2. 高寫入吞吐（&gt; 1K WPS）</strong>：</p>
<ul>
<li>fsync 限制</li>
<li>替代：任何 server-based RDBMS</li>
</ul>
<p><strong>3. Multi-user 權限管理</strong>：</p>
<ul>
<li>無 user / role 概念</li>
<li>替代：PostgreSQL / MySQL</li>
</ul>
<p><strong>4. 跨機器 transaction</strong>：</p>
<ul>
<li>SQLite 是 single-machine</li>
<li>替代：分散式 SQL</li>
</ul>
<p><strong>5. 大規模 production OLTP</strong>：</p>
<ul>
<li>大規模 production OLTP 需要 server database 的 HA、replica、權限與操作邊界</li>
<li>替代：MySQL / PostgreSQL / Aurora</li>
</ul>
<h2 id="跟其他-vendor-的取捨">跟其他 vendor 的取捨</h2>
<p><strong>vs PostgreSQL（作為 test DB）</strong>：</p>
<ul>
<li>SQLite：快 spin up、SQL dialect 接近但有差異</li>
<li>PostgreSQL：跟 production 一致、發現的 bug 真實</li>
<li>選 SQLite：speed of iteration、簡單 query</li>
<li>選 PostgreSQL：catch production-like bug、PostgreSQL-specific 特性測試</li>
</ul>
<p><strong>vs Cloudflare D1</strong>：</p>
<ul>
<li>SQLite（local）：單機、自管</li>
<li>D1：edge serverless、跟 Workers 整合</li>
<li>選 SQLite：embedded / CLI / app 場景</li>
<li>選 D1：edge web service、跟 Cloudflare 生態整合</li>
</ul>
<p><strong>vs Turso（distributed SQLite）</strong>：</p>
<ul>
<li>SQLite：單機、單檔案</li>
<li>Turso：distributed、跨 region replication、SQLite-compatible</li>
<li>選 SQLite：simple use case</li>
<li>選 Turso：需要 SQLite simplicity + 全球分散</li>
</ul>
<p><strong>vs Litestream（replicated SQLite）</strong>：</p>
<ul>
<li>SQLite：單檔案</li>
<li>Litestream：把 SQLite 變成 streaming replicated 到 S3</li>
<li>選 Litestream：想要 SQLite simplicity + DR</li>
</ul>
<p><strong>vs Firebase / Firestore（mobile app）</strong>：</p>
<ul>
<li>SQLite：embedded、offline-first、無 sync</li>
<li>Firestore：realtime、自動 sync、雲端 store</li>
<li>選 SQLite：offline-first、單機</li>
<li>選 Firestore：multi-device sync、realtime</li>
</ul>
<h2 id="容量規劃要點">容量規劃要點</h2>
<p><strong>1. WAL mode 是 production baseline</strong>：</p>
<ul>
<li>default journal mode 是 rollback journal（每寫都 lock）</li>
<li>WAL（Write-Ahead Log）讓多 reader 可同時跑</li>
<li><code>PRAGMA journal_mode = WAL</code></li>
</ul>
<p><strong>2. fsync 配置</strong>：</p>
<ul>
<li><code>PRAGMA synchronous = FULL</code>（durable、慢）</li>
<li><code>PRAGMA synchronous = NORMAL</code>（faster、少數情況可能掉資料）</li>
<li><code>PRAGMA synchronous = OFF</code>（最快、不安全）</li>
</ul>
<p><strong>3. mmap 加速 read</strong>：</p>
<ul>
<li><code>PRAGMA mmap_size = 268435456</code>（256 MB）</li>
<li>把 DB 部分內容 mmap 進 RAM、加速 read</li>
</ul>
<p><strong>4. Cache size</strong>：</p>
<ul>
<li><code>PRAGMA cache_size = -64000</code>（64 MB cache）</li>
<li>大 cache 對 read-heavy workload 有幫助</li>
</ul>
<p><strong>5. Auto-vacuum</strong>：</p>
<ul>
<li>預設 off、delete 後檔案不縮小</li>
<li><code>PRAGMA auto_vacuum = INCREMENTAL</code> + 定期 <code>PRAGMA incremental_vacuum</code></li>
</ul>
<h2 id="章節群結構">章節群結構</h2>
<p>SQLite 章節群的責任是把單檔正式狀態、embedded process、writer boundary、backup / restore、test fixture、local-first 與 edge SQLite 變體拆成可教學路線。完整結構見 <a href="teaching-structure/">SQLite Teaching Structure</a>；下表列出目前已建立的 deep article、hands-on 與 migration route。</p>
<table>
  <thead>
      <tr>
          <th>層級</th>
          <th>文件</th>
          <th>狀態</th>
          <th>教學責任</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>結構總覽</td>
          <td><a href="teaching-structure/">Teaching Structure</a></td>
          <td>已有正文</td>
          <td>對齊 PG / MySQL 與 LLM 架構，固定 SQLite 後續讀法</td>
      </tr>
      <tr>
          <td>Core deep</td>
          <td><a href="file-lifecycle-backup-boundary/">File lifecycle / backup boundary</a></td>
          <td>已有正文</td>
          <td>WAL sidecar、backup API、restore drill、corruption route</td>
      </tr>
      <tr>
          <td>Hands-on</td>
          <td><a href="hands-on/">Hands-on 操作路線</a></td>
          <td>已有正文</td>
          <td>local file、backup restore、WAL busy、migration fixture</td>
      </tr>
      <tr>
          <td>Concurrency</td>
          <td><a href="wal-concurrency-locking/">WAL concurrency / locking</a></td>
          <td>已有正文</td>
          <td>single writer、file lock、<code>SQLITE_BUSY</code>、checkpoint</td>
      </tr>
      <tr>
          <td>Performance</td>
          <td><a href="pragma-tuning-performance/">PRAGMA tuning / performance</a></td>
          <td>已有正文</td>
          <td>journal、sync、cache、mmap、vacuum 的取捨</td>
      </tr>
      <tr>
          <td>Migration</td>
          <td><a href="schema-migration-versioning/">Schema migration / versioning</a></td>
          <td>已有正文</td>
          <td>app release、schema version、rollback、migration evidence</td>
      </tr>
      <tr>
          <td>Testing</td>
          <td><a href="test-fixture-best-practice/">Test fixture best practice</a></td>
          <td>已有正文</td>
          <td>SQLite 測試便利性與 production dialect gap</td>
      </tr>
      <tr>
          <td>Embedded app</td>
          <td><a href="mobile-desktop-embedded-store/">Mobile / desktop embedded store</a></td>
          <td>已有正文</td>
          <td>device local state、privacy、backup、app version</td>
      </tr>
      <tr>
          <td>Sync</td>
          <td><a href="local-first-sync-boundary/">Local-first sync boundary</a></td>
          <td>已有正文</td>
          <td>多裝置同步、conflict、server authority</td>
      </tr>
      <tr>
          <td>Edge variant</td>
          <td><a href="d1-turso-libsql-comparison/">D1 / Turso / libSQL comparison</a></td>
          <td>已有正文</td>
          <td>edge SQLite 產品與 local SQLite 的責任差異</td>
      </tr>
      <tr>
          <td>Replication</td>
          <td><a href="litestream-litefs-replication/">Litestream / LiteFS replication</a></td>
          <td>已有正文</td>
          <td>continuous backup、read replica、failover boundary</td>
      </tr>
      <tr>
          <td>SQL compatibility</td>
          <td><a href="sql-dialect-index-limits/">SQL dialect and index limits</a></td>
          <td>已有正文</td>
          <td>type affinity、index、constraint、PostgreSQL / MySQL gap</td>
      </tr>
      <tr>
          <td>Operations</td>
          <td><a href="observability-runbook/">Observability / runbook</a></td>
          <td>已有正文</td>
          <td>busy errors、WAL growth、backup evidence、incident route</td>
      </tr>
      <tr>
          <td>Migration route</td>
          <td><a href="migrate-to-postgresql/">SQLite to PostgreSQL</a></td>
          <td>已有正文</td>
          <td>多 tenant、權限、HA、audit 出現時的升級路線</td>
      </tr>
      <tr>
          <td>Migration route</td>
          <td><a href="migrate-to-d1-turso/">SQLite to D1 / Turso</a></td>
          <td>已有正文</td>
          <td>edge / serverless 化路線</td>
      </tr>
      <tr>
          <td>Migration route</td>
          <td><a href="migrate-from-postgresql-simplification/">PostgreSQL to SQLite simplification</a></td>
          <td>已有正文</td>
          <td>single-user / embedded 工具的反向簡化路線</td>
      </tr>
  </tbody>
</table>
<p>章節群的讀法是先讀 file lifecycle，再按壓力選 deep article。若問題是 write contention，讀 WAL locking；若問題是測試，讀 test fixture；若問題是 edge / serverless，讀 D1 / Turso comparison；若問題是服務長大，讀 SQLite to PostgreSQL migration。</p>
<h2 id="anti-recommendation-與升級路由">Anti-recommendation 與升級路由</h2>
<p>SQLite 的低操作成本容易讓團隊忽略它的 writer boundary。這一段先說何時維持 SQLite，再說何時升級到 server SQL、edge SQLite 變體或 managed KV。</p>
<table>
  <thead>
      <tr>
          <th>機制 / 路線</th>
          <th>維持簡單設計的條件</th>
          <th>升級訊號</th>
          <th>主要引用路徑</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Local SQLite</td>
          <td>單 process、單 writer、資料可用檔案備份保護</td>
          <td>多 instance 寫入、需要 HA、需要資料層權限</td>
          <td><a href="/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">Database</a>、<a href="/blog/backend/knowledge-cards/source-of-truth/" data-link-title="Source of Truth" data-link-desc="說明正式資料來源如何決定資料判斷、修復與一致性責任">Source of Truth</a></td>
      </tr>
      <tr>
          <td>WAL + file backup</td>
          <td>read-heavy、寫入量低、RPO 可接受定期 snapshot</td>
          <td>restore 演練失敗、WAL growth 失控、RPO / RTO 變嚴格</td>
          <td><a href="/blog/backend/knowledge-cards/rpo/" data-link-title="RPO" data-link-desc="說明恢復點目標如何定義可接受資料損失範圍">RPO</a>、<a href="/blog/backend/knowledge-cards/rto/" data-link-title="RTO" data-link-desc="說明恢復時間目標如何約束事故回復策略">RTO</a></td>
      </tr>
      <tr>
          <td>Litestream / LiteFS</td>
          <td>單 primary 寫入清楚、主要需求是 backup 或 read replica</td>
          <td>需要多地 active write、跨 region transaction</td>
          <td><a href="/blog/backend/knowledge-cards/replication-lag/" data-link-title="Replication Lag" data-link-desc="說明資料副本落後正式來源多久，以及它如何影響讀取正確性">Replication Lag</a>、<a href="/blog/backend/knowledge-cards/stale-read/" data-link-title="Stale Read" data-link-desc="讀取到落後於最新寫入版本的舊資料">Stale Read</a></td>
      </tr>
      <tr>
          <td>Cloudflare D1 / Turso</td>
          <td>edge / serverless 生態已是主平台</td>
          <td>SQL 特性、migration、observability 或 vendor 限制卡住</td>
          <td><a href="/blog/backend/01-database/global-distributed-oltp/" data-link-title="1.11 全球分散式 OLTP" data-link-desc="Spanner / Aurora DSQL / Cosmos DB multi-region write / CockroachDB / TiDB 的全球一致性取捨">1.11 全球分散式 OLTP</a></td>
      </tr>
      <tr>
          <td>PostgreSQL / MySQL</td>
          <td>application 已進入多服務、多 tenant、權限與備份治理需求</td>
          <td>schema migration、connection、audit 與 failover 成主題</td>
          <td><a href="/blog/backend/01-database/vendors/postgresql/" data-link-title="PostgreSQL" data-link-desc="多用途 OLTP 主流關聯式資料庫、MVCC、豐富 SQL 特性、是 Aurora / Cosmos DB / Spanner / CockroachDB / Aurora DSQL 的相容目標">PostgreSQL vendor</a>、<a href="/blog/backend/01-database/vendors/mysql/" data-link-title="MySQL" data-link-desc="高併發網路服務常用關聯式資料庫、Vitess / PlanetScale 分片生態、GitHub / Shopify / Facebook 規模驗證">MySQL vendor</a></td>
      </tr>
  </tbody>
</table>
<p>SQLite 的簡單路徑是讓檔案生命週期成為正式操作流程。只要單一 writer、備份、restore、migration 與 file ownership 都能被 runbook 控制，SQLite 可以是正式狀態，而非臨時 cache。</p>
<p>升級到 server SQL 的訊號是操作責任超過檔案邊界。當團隊需要資料庫帳號、權限分層、read replica、線上 schema migration、集中 audit 或跨 instance failover 時，PostgreSQL / MySQL / Aurora 會比繼續包裝 SQLite 更清楚。</p>
<h2 id="已知-limitation-與後續路由">已知 limitation 與後續路由</h2>
<p>SQLite overview 目前已完成服務判斷與章節群正文路由。File lifecycle、WAL locking、PRAGMA tuning、schema migration、test fixture、local-first sync、edge product 差異、observability、hands-on 與 migration route 都已有對應正文；下一輪審查可集中在案例補強、引用精度與跨章重複整理。</p>
<h2 id="案例對照">案例對照</h2>
<p>SQLite 不在 09 case 庫的「規模化 vendor」類別、但作為 <em>embedded 跟 test</em> 廣泛使用：</p>
<ul>
<li>iOS Core Data：所有 iOS app 的 default DB</li>
<li>Chrome / Firefox：cookie、history、bookmark</li>
<li>Fossil SCM：repository metadata 與 application-file use case</li>
<li>Cloudflare D1：edge serverless（新興 production 場景）</li>
<li>Turso：distributed SQLite（新興 production 場景）</li>
</ul>
<h2 id="常見陷阱">常見陷阱</h2>
<ul>
<li><strong>default journal mode 不改 WAL</strong>：read 跟 write 互相 block、performance 差</li>
<li><strong>多 process / instance 同時寫同檔</strong>：corruption</li>
<li><strong>delete 後檔案沒縮小</strong>：忘了 vacuum</li>
<li><strong>synchronous=OFF 給 production</strong>：power loss 可能掉資料</li>
<li><strong>SQLite 跟 PostgreSQL 行為差異測試不足</strong>：SQLite test 過、PostgreSQL production 出 bug（特別是 date / time、NULL 處理、type coercion）</li>
</ul>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>完整 T1 對照：<a href="/blog/backend/01-database/vendors/" data-link-title="資料庫 Vendor 清單" data-link-desc="規劃 SQL、managed SQL、document、KV 與 distributed SQL 的服務頁撰寫順序與教學大綱">01-database vendors index</a></li>
<li>平行：<a href="/blog/backend/01-database/vendors/postgresql/" data-link-title="PostgreSQL" data-link-desc="多用途 OLTP 主流關聯式資料庫、MVCC、豐富 SQL 特性、是 Aurora / Cosmos DB / Spanner / CockroachDB / Aurora DSQL 的相容目標">PostgreSQL vendor</a> / <a href="/blog/backend/01-database/vendors/mysql/" data-link-title="MySQL" data-link-desc="高併發網路服務常用關聯式資料庫、Vitess / PlanetScale 分片生態、GitHub / Shopify / Facebook 規模驗證">MySQL vendor</a>（production server-based RDBMS）</li>
<li>上游：<a href="/blog/backend/01-database/repository-adapter/" data-link-title="1.4 Repository Adapter 實作" data-link-desc="Port / Adapter 邊界、row mapping、error translation、ORM vs query builder 選型、contract test 設計">1.4 Repository Adapter</a>（test fixture 模式）</li>
<li>結構：<a href="/blog/backend/01-database/vendors/sqlite/teaching-structure/" data-link-title="SQLite Teaching Structure" data-link-desc="SQLite 服務章節群的大綱：從 embedded formal state、WAL、backup、test fixture、local-first、edge SQLite 到遷移路由">SQLite Teaching Structure</a>（完整章節群與寫作順序）</li>
<li>操作：<a href="/blog/backend/01-database/vendors/sqlite/hands-on/" data-link-title="SQLite Hands-on 操作路線" data-link-desc="SQLite local file lab、backup / restore drill、WAL busy reproduction、migration fixture、D1 / Turso preview 的操作型章節設計">SQLite Hands-on</a>（local file、backup restore、WAL busy reproduction、migration fixture、D1 / Turso preview）</li>
<li>深入：<a href="/blog/backend/01-database/vendors/sqlite/file-lifecycle-backup-boundary/" data-link-title="SQLite file lifecycle 與 backup boundary" data-link-desc="把 SQLite 單檔案正式狀態拆成 WAL、backup API、restore drill、corruption recovery 與操作責任邊界">SQLite file lifecycle 與 backup boundary</a>（WAL、backup、restore、file ownership）</li>
<li>官方：<a href="https://sqlite.org/docs.html">SQLite Documentation</a>、<a href="https://litestream.io/">Litestream</a>、<a href="https://turso.tech/">Turso</a>、<a href="https://developers.cloudflare.com/d1/">Cloudflare D1</a></li>
</ul>
]]></content:encoded></item><item><title>AWS ELB（ALB / NLB / CLB）</title><link>https://tarrragon.github.io/blog/backend/05-deployment-platform/vendors/aws-elb/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/05-deployment-platform/vendors/aws-elb/</guid><description>&lt;p>AWS ELB 是 AWS managed load balancer 系列、承擔三個責任：流量入口（HTTP/HTTPS for ALB、TCP/UDP for NLB）、health check + draining、跟 AWS 生態整合（ACM TLS / Target Group / WAF / Lambda）。包含 ALB（L7、HTTP/HTTPS）、NLB（L4、極低延遲）、CLB（legacy、不要選）。設計取捨偏向「managed + AWS-native + integrate with ECS/EKS/Lambda」、跨雲 / 進階 traffic management 是限制。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>建立 ALB / NLB、配置 listener + target group&lt;/li>
&lt;li>設計 health check + connection draining&lt;/li>
&lt;li>用 ACM 自動憑證 + SNI&lt;/li>
&lt;li>用 ALB Ingress Controller / AWS Load Balancer Controller for K8s&lt;/li>
&lt;li>評估 ALB vs NLB vs CloudFront vs API Gateway&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑5-分鐘把-aws-elb-跑起來">最短路徑：5 分鐘把 AWS ELB 跑起來&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 1. 建 ALB&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">aws elbv2 create-load-balancer &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> --name demo-alb &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> --subnets subnet-aaa subnet-bbb &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> --security-groups sg-xxx &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> --scheme internet-facing &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> --type application
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="c1"># 2. 建 target group + register targets&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">aws elbv2 create-target-group &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> --name demo-tg &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> --protocol HTTP --port &lt;span class="m">8080&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> --vpc-id vpc-xxx &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> --target-type instance &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> --health-check-path /health &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> --health-check-interval-seconds &lt;span class="m">15&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl">aws elbv2 register-targets &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> --target-group-arn arn:aws:elasticloadbalancing:...:targetgroup/demo-tg/... &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> --targets &lt;span class="nv">Id&lt;/span>&lt;span class="o">=&lt;/span>i-0abc123 &lt;span class="nv">Id&lt;/span>&lt;span class="o">=&lt;/span>i-0def456
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">22&lt;/span>&lt;span class="cl">&lt;span class="c1"># 3. 建 listener + 驗證&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">23&lt;/span>&lt;span class="cl">aws elbv2 create-listener &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">24&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> --load-balancer-arn arn:aws:elasticloadbalancing:...:loadbalancer/app/demo-alb/... &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">25&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> --protocol HTTP --port &lt;span class="m">80&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">26&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> --default-actions &lt;span class="nv">Type&lt;/span>&lt;span class="o">=&lt;/span>forward,TargetGroupArn&lt;span class="o">=&lt;/span>arn:aws:...
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">27&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">28&lt;/span>&lt;span class="cl">&lt;span class="nv">ALB_DNS&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="k">$(&lt;/span>aws elbv2 describe-load-balancers --names demo-alb &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">29&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> --query &lt;span class="s1">&amp;#39;LoadBalancers[0].DNSName&amp;#39;&lt;/span> --output text&lt;span class="k">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">30&lt;/span>&lt;span class="cl">curl &lt;span class="s2">&amp;#34;http://&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">ALB_DNS&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="日常操作與決策形狀">日常操作與決策形狀&lt;/h2>
&lt;h3 id="alb-vs-nlb-vs-clb">ALB vs NLB vs CLB&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>ALB：L7、path/host routing、WebSocket、gRPC、Lambda target&lt;/li>
&lt;li>NLB：L4、static IP、preserve client IP、極低延遲、TCP/UDP&lt;/li>
&lt;li>CLB：legacy、不要新用&lt;/li>
&lt;li>選擇判讀：HTTP/HTTPS → ALB；TCP/UDP / 高吞吐 → NLB&lt;/li>
&lt;/ul>
&lt;h3 id="target-group--listener-rule">Target group / listener rule&lt;/h3>
&lt;p>子議題：&lt;/p></description><content:encoded><![CDATA[<p>AWS ELB 是 AWS managed load balancer 系列、承擔三個責任：流量入口（HTTP/HTTPS for ALB、TCP/UDP for NLB）、health check + draining、跟 AWS 生態整合（ACM TLS / Target Group / WAF / Lambda）。包含 ALB（L7、HTTP/HTTPS）、NLB（L4、極低延遲）、CLB（legacy、不要選）。設計取捨偏向「managed + AWS-native + integrate with ECS/EKS/Lambda」、跨雲 / 進階 traffic management 是限制。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>建立 ALB / NLB、配置 listener + target group</li>
<li>設計 health check + connection draining</li>
<li>用 ACM 自動憑證 + SNI</li>
<li>用 ALB Ingress Controller / AWS Load Balancer Controller for K8s</li>
<li>評估 ALB vs NLB vs CloudFront vs API Gateway</li>
</ol>
<h2 id="最短路徑5-分鐘把-aws-elb-跑起來">最短路徑：5 分鐘把 AWS ELB 跑起來</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># 1. 建 ALB</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">aws elbv2 create-load-balancer <span class="se">\
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="se"></span>  --name demo-alb <span class="se">\
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="se"></span>  --subnets subnet-aaa subnet-bbb <span class="se">\
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="se"></span>  --security-groups sg-xxx <span class="se">\
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="se"></span>  --scheme internet-facing <span class="se">\
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="se"></span>  --type application
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="c1"># 2. 建 target group + register targets</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">aws elbv2 create-target-group <span class="se">\
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="se"></span>  --name demo-tg <span class="se">\
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="se"></span>  --protocol HTTP --port <span class="m">8080</span> <span class="se">\
</span></span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="se"></span>  --vpc-id vpc-xxx <span class="se">\
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="se"></span>  --target-type instance <span class="se">\
</span></span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="se"></span>  --health-check-path /health <span class="se">\
</span></span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="se"></span>  --health-check-interval-seconds <span class="m">15</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">
</span></span><span class="line"><span class="ln">18</span><span class="cl">aws elbv2 register-targets <span class="se">\
</span></span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="se"></span>  --target-group-arn arn:aws:elasticloadbalancing:...:targetgroup/demo-tg/... <span class="se">\
</span></span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="se"></span>  --targets <span class="nv">Id</span><span class="o">=</span>i-0abc123 <span class="nv">Id</span><span class="o">=</span>i-0def456
</span></span><span class="line"><span class="ln">21</span><span class="cl">
</span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="c1"># 3. 建 listener + 驗證</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">aws elbv2 create-listener <span class="se">\
</span></span></span><span class="line"><span class="ln">24</span><span class="cl"><span class="se"></span>  --load-balancer-arn arn:aws:elasticloadbalancing:...:loadbalancer/app/demo-alb/... <span class="se">\
</span></span></span><span class="line"><span class="ln">25</span><span class="cl"><span class="se"></span>  --protocol HTTP --port <span class="m">80</span> <span class="se">\
</span></span></span><span class="line"><span class="ln">26</span><span class="cl"><span class="se"></span>  --default-actions <span class="nv">Type</span><span class="o">=</span>forward,TargetGroupArn<span class="o">=</span>arn:aws:...
</span></span><span class="line"><span class="ln">27</span><span class="cl">
</span></span><span class="line"><span class="ln">28</span><span class="cl"><span class="nv">ALB_DNS</span><span class="o">=</span><span class="k">$(</span>aws elbv2 describe-load-balancers --names demo-alb <span class="se">\
</span></span></span><span class="line"><span class="ln">29</span><span class="cl"><span class="se"></span>  --query <span class="s1">&#39;LoadBalancers[0].DNSName&#39;</span> --output text<span class="k">)</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">curl <span class="s2">&#34;http://</span><span class="si">${</span><span class="nv">ALB_DNS</span><span class="si">}</span><span class="s2">&#34;</span></span></span></code></pre></div><h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="alb-vs-nlb-vs-clb">ALB vs NLB vs CLB</h3>
<p>子議題：</p>
<ul>
<li>ALB：L7、path/host routing、WebSocket、gRPC、Lambda target</li>
<li>NLB：L4、static IP、preserve client IP、極低延遲、TCP/UDP</li>
<li>CLB：legacy、不要新用</li>
<li>選擇判讀：HTTP/HTTPS → ALB；TCP/UDP / 高吞吐 → NLB</li>
</ul>
<h3 id="target-group--listener-rule">Target group / listener rule</h3>
<p>子議題：</p>
<ul>
<li>Target type：instance / IP / Lambda</li>
<li>Listener rule：path-based / host-based / header-based routing</li>
<li>Priority 排序</li>
<li>對應指令：<code>aws elbv2 modify-rule</code></li>
</ul>
<h3 id="health-check-與-draining">Health check 與 draining</h3>
<p>子議題：</p>
<ul>
<li>Health check：HTTP path / interval / threshold</li>
<li>Connection draining（deregistration delay）：deregister 後等到 in-flight requests 完成</li>
<li>對應 <a href="/blog/backend/05-deployment-platform/cases/failure-platform-cutover-without-drain/" data-link-title="5.C9 反例：平台切流未先 Draining" data-link-desc="切流時忽略連線清退造成請求錯誤與重試風暴。">5.C9 反例 cutover without drain</a></li>
</ul>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<h3 id="tls-termination--sni">TLS termination + SNI</h3>
<p>子議題：</p>
<ul>
<li>ACM 自動憑證 + 續期</li>
<li>SNI：單 ALB 多 domain（最多 25 certificates）</li>
<li>TLS policy（min TLS version）</li>
<li>Mutual TLS（ALB 2023+）</li>
</ul>
<h3 id="alb-ingress-controller--aws-load-balancer-controller">ALB Ingress Controller / AWS Load Balancer Controller</h3>
<p>子議題：</p>
<ul>
<li>在 EKS 內配置 ALB / NLB（Ingress / Service of type LoadBalancer）</li>
<li>IngressClass / annotations</li>
<li>Pod readiness gate（pod 到 ALB target group healthy 才接流量）</li>
<li>對應 <a href="/blog/backend/05-deployment-platform/vendors/kubernetes/" data-link-title="Kubernetes" data-link-desc="Container orchestration 主流、GKE / EKS / AKS / 自管">Kubernetes vendor 頁</a></li>
</ul>
<h3 id="cross-zone-load-balancing">Cross-zone load balancing</h3>
<p>子議題：</p>
<ul>
<li>ALB default enabled、NLB default disabled</li>
<li>Cross-zone 跨 AZ data transfer cost</li>
<li>跟 AZ failover 對應</li>
</ul>
<h3 id="waf-integration">WAF integration</h3>
<p>子議題：</p>
<ul>
<li>AWS WAF on ALB</li>
<li>Rate-based rule / managed rule group</li>
<li>對應 <a href="/blog/backend/07-security-data-protection/" data-link-title="模組七：資安與資料保護" data-link-desc="以問題驅動方式擴充資安知識網：先定義服務環節問題，再以案例作為觸發式參考">07 security WAF</a></li>
</ul>
<h3 id="idle-timeout">Idle timeout</h3>
<p>子議題：</p>
<ul>
<li>ALB default 60s、可調 1-4000s</li>
<li>跟 keep-alive / WebSocket 長連線對應</li>
<li>跟 backend（K8s pod / EC2）的 timeout 對齊</li>
</ul>
<h3 id="cost-模型">Cost 模型</h3>
<p>子議題：</p>
<ul>
<li>LB-hour（per ALB / NLB）</li>
<li>LCU（Load Balancer Capacity Unit）— 多維度計算</li>
<li>Data processing charge</li>
<li>跨 AZ data transfer</li>
</ul>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<h3 id="target-unhealthy">Target unhealthy</h3>
<p>操作原則：health check path 不對 / security group 沒開 / backend 反應慢。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">aws elbv2 describe-target-health <span class="se">\
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="se"></span>  --target-group-arn arn:aws:elasticloadbalancing:...:targetgroup/demo-tg/...
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="c1"># HealthState: unhealthy → 查 Reason（Target.Timeout / Elb.InternalError / Target.ResponseCodeMismatch）</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 常見根因：security group 沒開 health check port、health check path 回 404、backend 回應超過 timeout</span></span></span></code></pre></div><h3 id="504-gateway-timeout">504 Gateway Timeout</h3>
<p>操作原則：backend 超 ALB idle timeout / 60s。判讀：backend log + ALB access log。</p>
<h3 id="cross-zone-imbalance">Cross-zone imbalance</h3>
<p>操作原則：cross-zone disabled、流量集中單 AZ。修法：enable cross-zone（注意 cost）。</p>
<h3 id="draining-卡住">Draining 卡住</h3>
<p>對應 <a href="/blog/backend/05-deployment-platform/cases/failure-platform-cutover-without-drain/" data-link-title="5.C9 反例：平台切流未先 Draining" data-link-desc="切流時忽略連線清退造成請求錯誤與重試風暴。">5.C9 反例</a>。判讀：deregistration delay 太短 / connection 未結束就被斷。</p>
<h3 id="acm-cert-renew-失敗">ACM cert renew 失敗</h3>
<p>操作原則：DNS validation 失敗 / domain ownership 變動。判讀：ACM console 看 cert state。</p>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>跨雲 / 自管</td>
          <td><a href="/blog/backend/05-deployment-platform/vendors/nginx/" data-link-title="nginx" data-link-desc="HTTP server / reverse proxy / LB / ingress">nginx</a> / <a href="/blog/backend/05-deployment-platform/vendors/envoy/" data-link-title="Envoy" data-link-desc="Cloud-native service proxy、xDS dynamic config、Istio / Gateway 底層">Envoy</a></td>
      </tr>
      <tr>
          <td>Service mesh</td>
          <td><a href="/blog/backend/05-deployment-platform/vendors/envoy/" data-link-title="Envoy" data-link-desc="Cloud-native service proxy、xDS dynamic config、Istio / Gateway 底層">Envoy</a> + Istio</td>
      </tr>
      <tr>
          <td>Cloud-native auto-discovery</td>
          <td><a href="/blog/backend/05-deployment-platform/vendors/traefik/" data-link-title="Traefik" data-link-desc="Cloud-native ingress / reverse proxy、auto-discovery">Traefik</a></td>
      </tr>
      <tr>
          <td>CDN / edge</td>
          <td>CloudFront / Cloudflare / Fastly</td>
      </tr>
      <tr>
          <td>API Gateway</td>
          <td>AWS API Gateway / Kong</td>
      </tr>
      <tr>
          <td>極低成本</td>
          <td>自管 <a href="/blog/backend/05-deployment-platform/vendors/nginx/" data-link-title="nginx" data-link-desc="HTTP server / reverse proxy / LB / ingress">nginx</a> on EC2</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>AWS WAF rule 完整 reference</li>
<li>Network Firewall 配置</li>
<li>各 AWS region 限制差異</li>
<li>ELB classic（CLB）細節</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<h3 id="直接相關案例">直接相關案例</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>主討論議題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/05-deployment-platform/cases/tradeshift-self-managed-k8s-to-eks/" data-link-title="5.C1 Tradeshift：self-managed Kubernetes 遷移到 EKS" data-link-desc="零停機平台遷移的分段策略案例。">5.C1 Tradeshift self-managed → EKS</a></td>
          <td>遷 EKS 時 ALB / NLB 是入口、切流批次跟 target group 權重連動</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/05-deployment-platform/cases/conde-nast-platform-modernization-eks/" data-link-title="5.C2 Condé Nast：EKS 平台整併與標準化" data-link-desc="多地區異質 Kubernetes 平台整併為統一控制面的案例。">5.C2 Condé Nast EKS</a></td>
          <td>多集群整併 EKS、AWS Load Balancer Controller 統一 ingress 入口</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/05-deployment-platform/cases/mobileye-workloads-to-eks/" data-link-title="5.C4 Mobileye：Workloads 遷移到 EKS" data-link-desc="大規模工作負載遷移到 managed Kubernetes 的分段治理案例。">5.C4 Mobileye EKS</a></td>
          <td>大規模 workload 遷 EKS、ALB target group health check 是切流驗證點</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/05-deployment-platform/cases/miro-managed-eks-migration/" data-link-title="5.C5 Miro：Managed EKS 遷移" data-link-desc="從自維運平台轉向 managed EKS 的組織與技術協同案例。">5.C5 Miro EKS</a></td>
          <td>Managed EKS 後 ALB / NLB 治理回到平台團隊</td>
      </tr>
  </tbody>
</table>
<h3 id="跨-vendor-對照">跨 vendor 對照</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>對 AWS ELB 的對應</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/05-deployment-platform/cases/failure-platform-cutover-without-drain/" data-link-title="5.C9 反例：平台切流未先 Draining" data-link-desc="切流時忽略連線清退造成請求錯誤與重試風暴。">5.C9 cutover without drain</a></td>
          <td>ALB deregistration delay / NLB connection draining 是切流的關鍵回退面</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/05-deployment-platform/cases/contrast-platform-migration-by-scale/" data-link-title="5.C10 對照：規模差異下的平台遷移" data-link-desc="平台遷移策略在小中大型組織下的差異。">5.C10 規模對照</a></td>
          <td>AWS 生態小型 ALB + EC2 / 中型 ALB + EKS / 大型 NLB + 多 region + WAF</td>
      </tr>
  </tbody>
</table>
<p><strong>待補 AWS ELB 案例</strong>：大規模 AWS Load Balancer Controller 客戶案例、NLB static IP 場景、AWS WAF + ALB 安全整合。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游概念：<a href="/blog/backend/05-deployment-platform/load-balancer-contract/" data-link-title="5.3 load balancer 合約" data-link-desc="整理 idle timeout、draining 與 health check">5.3 LB Contract</a></li>
<li>平行 vendor：<a href="/blog/backend/05-deployment-platform/vendors/nginx/" data-link-title="nginx" data-link-desc="HTTP server / reverse proxy / LB / ingress">nginx</a>、<a href="/blog/backend/05-deployment-platform/vendors/envoy/" data-link-title="Envoy" data-link-desc="Cloud-native service proxy、xDS dynamic config、Istio / Gateway 底層">Envoy</a></li>
<li>下游能力：<a href="/blog/backend/07-security-data-protection/" data-link-title="模組七：資安與資料保護" data-link-desc="以問題驅動方式擴充資安知識網：先定義服務環節問題，再以案例作為觸發式參考">07 security WAF</a>、<a href="/blog/backend/06-reliability/" data-link-title="模組六：可靠性驗證流程" data-link-desc="用 SRE 領域詞彙建問題節點、以服務級案例庫累積驗證脈絡，先建概念與案例庫再進實作交接">6 reliability release gate</a></li>
</ul>
]]></content:encoded></item><item><title>Google Cloud Pub/Sub</title><link>https://tarrragon.github.io/blog/backend/03-message-queue/vendors/google-pubsub/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/03-message-queue/vendors/google-pubsub/</guid><description>&lt;p>Google Cloud Pub/Sub 是 GCP managed pub/sub 服務、承擔三個責任：全球 topic 路由（無 region 概念）、彈性 delivery（push 跟 pull 並存）、GCP 生態整合（BigQuery / Dataflow / Cloud Run）。設計取捨偏向「topic 是 first-class、subscription 各自進度、ack deadline 控制重試」、跟 Kafka 的 partition / consumer group 思路不同。&lt;/p>
&lt;p>對「GCP 生態事件分發、跨 region 全球路由、push HTTP endpoint 接收事件、Dataflow streaming」這條路徑、Pub/Sub 是首選。本頁先給最短路徑、再展開日常 topic / subscription 操作與 ack deadline 設計、最後進階治理（ordering、DLT、push endpoint、IAM）跟排錯。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>用 gcloud CLI 建 topic / subscription、publish / pull 訊息&lt;/li>
&lt;li>區分 push vs pull subscription、選擇對應的 delivery 模型&lt;/li>
&lt;li>設計 ack deadline 與 ackExtension、處理長任務&lt;/li>
&lt;li>配置 dead-letter topic 與 retry policy&lt;/li>
&lt;li>評估 ordering key、Pub/Sub Lite、BigQuery subscription 等延伸場景&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑5-分鐘把-pubsub-跑起來">最短路徑：5 分鐘把 Pub/Sub 跑起來&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 1. 建 topic&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">gcloud pubsub topics create demo-topic
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="c1"># 2. 建 subscription（pull 模式、綁定 topic）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">gcloud pubsub subscriptions create demo-sub --topic&lt;span class="o">=&lt;/span>demo-topic
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">&lt;span class="c1"># 3. publish + pull 驗證&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl">gcloud pubsub topics publish demo-topic --message&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;hello&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">9&lt;/span>&lt;span class="cl">gcloud pubsub subscriptions pull demo-sub --auto-ack&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>最短路徑驗證「topic / subscription 建得起來、能發能收」。實際應用見&lt;a href="#%e6%97%a5%e5%b8%b8%e6%93%8d%e4%bd%9c%e8%88%87%e6%b1%ba%e7%ad%96%e5%bd%a2%e7%8b%80">日常操作&lt;/a>。指令對真實 GCP 需設定 project 與認證；本機要先驗證可啟動 Pub/Sub emulator、用 &lt;code>gcloud config set api_endpoint_overrides/pubsub&lt;/code> 把同一組 CLI 指向 emulator 跑通。&lt;/p>
&lt;h2 id="日常操作與決策形狀">日常操作與決策形狀&lt;/h2>
&lt;h3 id="gcloud-cli-與-client-library">gcloud CLI 與 client library&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>gcloud CLI 指令對照表（topics / subscriptions / publish / pull / ack）&lt;/li>
&lt;li>Client library 配置：credentials / flow control / async vs sync&lt;/li>
&lt;li>Batch publish（提高吞吐、增加延遲的取捨）&lt;/li>
&lt;li>對應指令範例：&lt;code>gcloud pubsub subscriptions describe &amp;lt;sub&amp;gt;&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="topic--subscription-設計">Topic / Subscription 設計&lt;/h3>
&lt;p>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/topic/" data-link-title="Topic" data-link-desc="說明 topic 如何把事件依主題分流給不同訂閱者">Topic&lt;/a> 是 first-class entity、跟 Kafka 不同的是 subscription 才是 consumer 抽象：&lt;/p></description><content:encoded><![CDATA[<p>Google Cloud Pub/Sub 是 GCP managed pub/sub 服務、承擔三個責任：全球 topic 路由（無 region 概念）、彈性 delivery（push 跟 pull 並存）、GCP 生態整合（BigQuery / Dataflow / Cloud Run）。設計取捨偏向「topic 是 first-class、subscription 各自進度、ack deadline 控制重試」、跟 Kafka 的 partition / consumer group 思路不同。</p>
<p>對「GCP 生態事件分發、跨 region 全球路由、push HTTP endpoint 接收事件、Dataflow streaming」這條路徑、Pub/Sub 是首選。本頁先給最短路徑、再展開日常 topic / subscription 操作與 ack deadline 設計、最後進階治理（ordering、DLT、push endpoint、IAM）跟排錯。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>用 gcloud CLI 建 topic / subscription、publish / pull 訊息</li>
<li>區分 push vs pull subscription、選擇對應的 delivery 模型</li>
<li>設計 ack deadline 與 ackExtension、處理長任務</li>
<li>配置 dead-letter topic 與 retry policy</li>
<li>評估 ordering key、Pub/Sub Lite、BigQuery subscription 等延伸場景</li>
</ol>
<h2 id="最短路徑5-分鐘把-pubsub-跑起來">最短路徑：5 分鐘把 Pub/Sub 跑起來</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 1. 建 topic</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">gcloud pubsub topics create demo-topic
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 2. 建 subscription（pull 模式、綁定 topic）</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">gcloud pubsub subscriptions create demo-sub --topic<span class="o">=</span>demo-topic
</span></span><span class="line"><span class="ln">6</span><span class="cl">
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="c1"># 3. publish + pull 驗證</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl">gcloud pubsub topics publish demo-topic --message<span class="o">=</span><span class="s2">&#34;hello&#34;</span>
</span></span><span class="line"><span class="ln">9</span><span class="cl">gcloud pubsub subscriptions pull demo-sub --auto-ack</span></span></code></pre></div><p>最短路徑驗證「topic / subscription 建得起來、能發能收」。實際應用見<a href="#%e6%97%a5%e5%b8%b8%e6%93%8d%e4%bd%9c%e8%88%87%e6%b1%ba%e7%ad%96%e5%bd%a2%e7%8b%80">日常操作</a>。指令對真實 GCP 需設定 project 與認證；本機要先驗證可啟動 Pub/Sub emulator、用 <code>gcloud config set api_endpoint_overrides/pubsub</code> 把同一組 CLI 指向 emulator 跑通。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="gcloud-cli-與-client-library">gcloud CLI 與 client library</h3>
<p>子議題：</p>
<ul>
<li>gcloud CLI 指令對照表（topics / subscriptions / publish / pull / ack）</li>
<li>Client library 配置：credentials / flow control / async vs sync</li>
<li>Batch publish（提高吞吐、增加延遲的取捨）</li>
<li>對應指令範例：<code>gcloud pubsub subscriptions describe &lt;sub&gt;</code></li>
</ul>
<h3 id="topic--subscription-設計">Topic / Subscription 設計</h3>
<p><a href="/blog/backend/knowledge-cards/topic/" data-link-title="Topic" data-link-desc="說明 topic 如何把事件依主題分流給不同訂閱者">Topic</a> 是 first-class entity、跟 Kafka 不同的是 subscription 才是 consumer 抽象：</p>
<ul>
<li>1 topic ↔ N subscription（fan-out 內建）</li>
<li>Subscription 各自進度（無 consumer group 概念）</li>
<li>Subscription expiration policy（閒置 N 天自動刪）</li>
</ul>
<h3 id="push-vs-pull-subscription">Push vs Pull subscription</h3>
<p>子議題：</p>
<ul>
<li>Push：Pub/Sub 主動 POST 到 HTTP endpoint、適合無狀態 worker / Cloud Run</li>
<li>Pull：consumer 主動拉取、適合長 worker / 需要 flow control</li>
<li>Push endpoint 要求（HTTPS、認證）</li>
<li>兩者的可靠性 / latency / cost 對照</li>
</ul>
<h3 id="ack-deadline-與-ack-extension">Ack deadline 與 ack extension</h3>
<p>子議題：</p>
<ul>
<li>Ack deadline：subscription 等待 ack 的時間（預設 10 秒、上限 600 秒）</li>
<li>Modify ack deadline（長任務動態延長）</li>
<li>Client library 的自動 ack extension</li>
<li>跟 SQS visibility timeout 的對照（語意類似、機制不同）</li>
</ul>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<p>ordering key、dead-letter topic 與 schema enforcement 已展開為 deep article：<a href="ordering-dlt-schema/">ordering key / DLT / schema enforcement</a>、<a href="push-pull-ack-flow-control/">push / pull / ack flow control</a>。下列子議題段保留選題判讀入口。</p>
<h3 id="ordering-key">Ordering key</h3>
<p>子議題：</p>
<ul>
<li>啟用 ordering 的限制（subscription 設定 enableMessageOrdering）</li>
<li>Ordering 在 push 跟 pull 的差異</li>
<li>跟 Kafka partition + key 的對照</li>
<li>性能影響（throughput 受限）</li>
</ul>
<h3 id="dead-letter-topic">Dead-letter topic</h3>
<p>子議題：</p>
<ul>
<li>設定 max delivery attempt、超過送到 DLT</li>
<li>DLT 是另一個 topic、可以再訂閱重處理</li>
<li>跟 SQS DLQ 的差異（DLT 是 topic、不是 queue）</li>
</ul>
<h3 id="pubsub-lite">Pub/Sub Lite</h3>
<p>子議題：</p>
<ul>
<li>Pub/Sub Lite vs Pub/Sub（partition-based、zonal、cost 低）</li>
<li>何時用 Lite（高吞吐、確定 region）</li>
<li>何時用 standard（global routing 內建）</li>
</ul>
<h3 id="bigquery-subscription--cloud-storage-subscription">BigQuery subscription / Cloud Storage subscription</h3>
<p>子議題：</p>
<ul>
<li>BigQuery subscription：訊息直接寫入 BQ table（無需 Dataflow）</li>
<li>Cloud Storage subscription：訊息批次寫入 GCS object</li>
<li>適合 streaming analytics / data lake 場景</li>
</ul>
<h3 id="schema-enforcement">Schema enforcement</h3>
<p>子議題：</p>
<ul>
<li>Topic 綁定 schema（Avro / Protobuf）</li>
<li>Schema evolution</li>
<li>跟 Kafka Schema Registry 的對照</li>
</ul>
<h3 id="iam--service-account">IAM / Service Account</h3>
<p>子議題：</p>
<ul>
<li>Pub/Sub IAM role（publisher / subscriber / viewer）</li>
<li>Service Account 認證（push endpoint 用）</li>
<li>VPC Service Controls</li>
</ul>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<h3 id="subscriber-backlogunacked-messages-累積">Subscriber backlog（unacked messages 累積）</h3>
<p>操作原則：先看是 push 還是 pull、再定位 endpoint 失敗 vs flow control 限制。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">gcloud pubsub subscriptions describe &lt;sub&gt;
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># 看 ackDeadlineSeconds（預設 10s）與 messageRetentionDuration（預設 604800s / 7 天）是否符合處理時間與 replay 需求</span></span></span></code></pre></div><p>判讀：Cloud Monitoring metric 的 <code>num_undelivered_messages</code> 與 <code>oldest_unacked_message_age</code>。</p>
<h3 id="push-endpoint-500retry-storm">Push endpoint 500（retry storm）</h3>
<p>操作原則：push endpoint 持續 500、Pub/Sub 會 backoff retry、看 retry policy 設定。判讀：endpoint 健康 vs 訊息毒性。</p>
<h3 id="ordering-key-限制誤用">Ordering key 限制誤用</h3>
<p>操作原則：啟用 ordering 後 throughput 變低、單一 ordering key 是順序的。判讀：throughput 是否被 ordering 限制、可拆 ordering key。</p>
<h3 id="iam-權限錯">IAM 權限錯</h3>
<p>操作原則：publish / pull / ack 各自需要不同 IAM role。判讀：用 Cloud Logging 看 deny 原因。</p>
<h3 id="subscription-expired">Subscription expired</h3>
<p>操作原則：閒置太久 subscription 被 GC。判讀：subscription expiration policy 設定 + 監控 lastReceiveTime。</p>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>需要 streaming + replay long window</td>
          <td><a href="/blog/backend/03-message-queue/vendors/kafka/" data-link-title="Apache Kafka" data-link-desc="Distributed event streaming platform、log-based 模型">Kafka</a> / Confluent Cloud</td>
      </tr>
      <tr>
          <td>需要 partition + consumer group</td>
          <td><a href="/blog/backend/03-message-queue/vendors/kafka/" data-link-title="Apache Kafka" data-link-desc="Distributed event streaming platform、log-based 模型">Kafka</a> / Pub/Sub Lite</td>
      </tr>
      <tr>
          <td>需要複雜 routing</td>
          <td><a href="/blog/backend/03-message-queue/vendors/rabbitmq/" data-link-title="RabbitMQ" data-link-desc="Classic message broker、AMQP routing 為主">RabbitMQ</a> on GKE</td>
      </tr>
      <tr>
          <td>跨雲 / 跨平台</td>
          <td><a href="/blog/backend/03-message-queue/vendors/kafka/" data-link-title="Apache Kafka" data-link-desc="Distributed event streaming platform、log-based 模型">Kafka</a> / <a href="/blog/backend/03-message-queue/vendors/nats/" data-link-title="NATS" data-link-desc="Lightweight messaging、JetStream 加持久化與 streams">NATS</a></td>
      </tr>
      <tr>
          <td>AWS 生態</td>
          <td><a href="/blog/backend/03-message-queue/vendors/aws-sqs/" data-link-title="AWS SQS" data-link-desc="AWS managed queue、簡單可靠、無 ordering（standard）">AWS SQS</a> / SNS</td>
      </tr>
      <tr>
          <td>Workflow + durable execution</td>
          <td>Google Workflows / Temporal</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Dataflow / BigQuery 完整功能（另開 streaming analytics 章節）</li>
<li>Cloud Run / Functions 整合細節</li>
<li>各語言 client 完整 API</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<h3 id="pubsub-專屬案例c60-c69">Pub/Sub 專屬案例（C60-C69）</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>主討論議題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/pubsub-spotify-event-delivery-platform/" data-link-title="3.C60 Spotify：Event Delivery 從 Kafka 遷到 Pub/Sub" data-link-desc="Spotify 全球 event delivery 從 Kafka 遷到 Pub/Sub、~2500 VM、Q1 2019 8M events/s、350TB/day raw、自建 dedup。">3.C60 Spotify Event Delivery</a></td>
          <td>從 Kafka 遷入 / 自建 dedup</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/pubsub-spotify-autoscaling-consumers/" data-link-title="3.C61 Spotify：Autoscaling Pub/Sub consumer 反效果" data-link-desc="Spotify 下游失敗時 consumer 不 ack 仍耗 CPU、autoscaling 越拉越高、解法是 exponential backoff 抑制 CPU。">3.C61 Spotify autoscaling</a></td>
          <td>Backlog ≠ healthy / autoscale 反效果</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/pubsub-spotify-cloud-storage-export/" data-link-title="3.C62 Spotify：Pub/Sub → GCS reliable export" data-link-desc="Spotify 用 Oldest Unacknowledged Message metric 判斷 hourly bucket 何時可安全關閉、ack 綁定下游 commit。">3.C62 Spotify GCS export</a></td>
          <td>Ack = end-to-end commit</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/pubsub-mercari-actionable-history/" data-link-title="3.C63 Mercari Actionable History：ack deadline 是 batch-level" data-link-desc="Merpay 支付流水帳用 Pub/Sub、ack deadline 是整批 batch 而非單訊息、acked 訊息會跟同批 expired 一起 redeliver。">3.C63 Mercari Actionable History</a></td>
          <td>Ack deadline 是 batch-level（陷阱）</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/pubsub-mercari-item-feed-dlt/" data-link-title="3.C64 Mercari Item Feed：DLT 防 poison message 阻塞" data-link-desc="Mercari 商品 feed 同步、ack 整批 / nack 重送、重試多次仍失敗送 DLT、topic 同時當 load-leveling buffer。">3.C64 Mercari Item Feed DLT</a></td>
          <td>DLT 防 poison message 阻塞</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/pubsub-mercari-line-flow-control/" data-link-title="3.C65 Mercari LINE：Pull subscription 對齊外部 RPS" data-link-desc="Mercari LINE webhook 轉 Pub/Sub、worker pull subscription 精確控制 RPS、應 LINE API 限制。">3.C65 Mercari LINE flow control</a></td>
          <td>Pull subscription 對齊外部 RPS</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/pubsub-mercari-b2c-grpc-pusher/" data-link-title="3.C66 Mercari B2C：自建 PubSub gRPC Pusher" data-link-desc="Mercari 全球商品同步、原生 HTTP push 在「長 job &#43; 高吞吐 &#43; 動態 RPS」場景受限、自建 gRPC 版 push。">3.C66 Mercari B2C gRPC pusher</a></td>
          <td>自建 push / 長 job + 動態 RPS</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/pubsub-niantic-pokemon-go-telemetry/" data-link-title="3.C67 Niantic Pokémon GO：Pub/Sub 當 telemetry ingest" data-link-desc="Pokémon GO frontend publish 玩家事件、~1M TPS、Pub/Sub elastic buffer、下游 BigQuery streaming。">3.C67 Niantic Pokémon GO</a></td>
          <td>Elastic buffer / BQ streaming</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/pubsub-wix-clickstream-dashboard/" data-link-title="3.C68 Wix：Pub/Sub decouple &#43; Dataflow &#43; BQ archive" data-link-desc="Wix App Engine 收 clickstream 進 Pub/Sub、Dataflow 進 Datastore &lt; 100ms、BigQuery 並行存 raw recovery。">3.C68 Wix clickstream</a></td>
          <td>Pub/Sub + Dataflow + BQ 教科書組合</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/pubsub-twitter-ad-engagement/" data-link-title="3.C69 Twitter Ad Engagement：把 stream 切成多 topic 做 partition" data-link-desc="Twitter 把 80K msg/s stream 切成 6 個 topic 做 partition、Avro schema、Beam/Dataflow → Bigtable/BQ。">3.C69 Twitter Ad Engagement</a></td>
          <td>多 topic 切分取代 partition</td>
      </tr>
  </tbody>
</table>
<h3 id="跨-vendor-對照">跨 vendor 對照</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>對 Pub/Sub 的對應</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/cloudflare-queues-global-delivery-model/" data-link-title="3.C8 Cloudflare：Queues 全球交付模型" data-link-desc="事件佇列服務在全球網路下的交付語義與治理案例。">3.C8 Cloudflare Queues</a></td>
          <td>全球交付對照：Pub/Sub global routing 內建</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/contrast-queue-model-by-scale/" data-link-title="3.C10 對照：規模差異下的佇列模型" data-link-desc="同一 queue 模型在不同規模下的治理與失敗邊界差異。">3.C10 規模對照</a></td>
          <td>中小型直接用 / 大型考慮 Pub/Sub Lite / 超大跨雲走 Kafka</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/cases/kafka-spotify-event-delivery-exodus/" data-link-title="3.C20 Spotify：Event Delivery 從 Kafka 遷出（反例）" data-link-desc="Spotify Kafka 0.7 MirrorMaker best-effort 會掉資料但回報成功、broker restart 後 producer 無法恢復、決定遷到 GCP Pub/Sub。">3.C20 Spotify 遷出 Kafka</a></td>
          <td>Pub/Sub 遷入的源頭（為何遷出 Kafka）</td>
      </tr>
  </tbody>
</table>
<p><strong>IAM + Service Account 缺直接 customer engineering case</strong>：customer engineering blog 著墨少、建議撰寫該段時依 GCP 官方 IAM 文件 + 通用安全原則。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游概念：<a href="/blog/backend/00-service-selection/async-delivery-selection/" data-link-title="0.3 非同步與事件傳遞選型" data-link-desc="區分背景工作、durable queue、stream、pub/sub 與 outbox 的選型邊界">0.3 非同步選型</a>、<a href="/blog/backend/03-message-queue/broker-basics/" data-link-title="3.1 broker 基礎與投遞模型" data-link-desc="先理解 broker、queue、consumer 與 delivery semantics">3.1 broker basics</a></li>
<li>平行 vendor：<a href="/blog/backend/03-message-queue/vendors/aws-sqs/" data-link-title="AWS SQS" data-link-desc="AWS managed queue、簡單可靠、無 ordering（standard）">AWS SQS</a>、<a href="/blog/backend/03-message-queue/vendors/kafka/" data-link-title="Apache Kafka" data-link-desc="Distributed event streaming platform、log-based 模型">Kafka</a></li>
<li>下游能力：<a href="/blog/backend/03-message-queue/consumer-design/" data-link-title="3.4 consumer 設計與去重" data-link-desc="整理 consumer、checkpoint 與 replay safety">3.4 consumer 設計</a>、<a href="/blog/backend/06-reliability/idempotency-replay/" data-link-title="6.12 Idempotency 與 Replay 驗證" data-link-desc="把重試、重播與冪等性從口頭約定變成可驗證屬性">6.12 idempotency / replay</a></li>
</ul>
]]></content:encoded></item><item><title>Honeycomb</title><link>https://tarrragon.github.io/blog/backend/04-observability/vendors/honeycomb/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/04-observability/vendors/honeycomb/</guid><description>&lt;p>Honeycomb 是 high-cardinality observability SaaS、承擔三個責任：events-based 資料模型（不是 metrics aggregation）、unknown-unknowns 偵錯能力（BubbleUp / Heatmap）、observability-driven SRE 文化代表平台。設計取捨偏向「深度優於廣度」、不追求 Datadog 的 integration 廣度、專注於 high-cardinality + distributed system debugging。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>用 Honeycomb SDK 或 OTel 送 events 到 Honeycomb&lt;/li>
&lt;li>用 BubbleUp 找 outlier 模式（unknown-unknowns）&lt;/li>
&lt;li>設計 SLO + burn rate alert&lt;/li>
&lt;li>配置 Refinery（tail-based sampling）&lt;/li>
&lt;li>評估 Honeycomb vs Datadog 的選用判讀&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑5-分鐘把-honeycomb-跑起來">最短路徑：5 分鐘把 Honeycomb 跑起來&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 1. 應用程式加 instrumentation（Honeycomb SDK 或 OTel SDK）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: HONEYCOMB_API_KEY + dataset 設定&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: 用 Beeline SDK 或 OTel + OTLP exporter&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">&lt;span class="c1"># 2. 送 sample events&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: 觀察 trace 出現在 Honeycomb UI&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl">&lt;span class="c1"># 3. 用 query 介面查詢&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">9&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: SELECT count + visualize by service.name&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="日常操作與決策形狀">日常操作與決策形狀&lt;/h2>
&lt;h3 id="events-vs-metrics-心智模型">Events vs metrics 心智模型&lt;/h3>
&lt;p>Honeycomb 跟 metrics-aggregation 平台不同。子議題：&lt;/p>
&lt;ul>
&lt;li>Event = 一個 trace span（包含 dozens of attributes）&lt;/li>
&lt;li>不預先 aggregate、查詢時 group by 任意 attribute&lt;/li>
&lt;li>High-cardinality 不是問題、是設計目標&lt;/li>
&lt;li>對應 &lt;a href="https://tarrragon.github.io/blog/backend/04-observability/cases/gaming-peak-signal-freshness-and-cardinality/" data-link-title="Gaming：高峰流量下的訊號新鮮度與 Cardinality" data-link-desc="在高峰事件中控制訊號延遲與維度爆炸，維持告警與定位可信度。">4.C2 Gaming peak cardinality&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="instrumentation">Instrumentation&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Honeycomb SDK&lt;/strong>（Beeline）：簡單、Honeycomb-specific、auto-instrumentation 部分&lt;/li>
&lt;li>&lt;strong>OTel SDK + OTLP&lt;/strong>：標準、vendor-neutral、推薦新部署用&lt;/li>
&lt;li>Manual attribute：對 business / domain context attribute 不省略&lt;/li>
&lt;li>Refinery：tail-based sampling proxy&lt;/li>
&lt;/ul>
&lt;h3 id="query-介面">Query 介面&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>Visualize：count / count_distinct / heatmap / p50 / p95 / p99&lt;/li>
&lt;li>Group by：任意 attribute（user_id / region / version 等）&lt;/li>
&lt;li>Filter：WHERE clause&lt;/li>
&lt;li>對應 SLO query：&lt;code>heatmap(duration_ms) GROUP BY service.name WHERE http.status_code = 500&lt;/code>&lt;/li>
&lt;/ul>
&lt;h2 id="deep-article">Deep Article&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="high-cardinality-query-bubbleup/">High-Cardinality Query Model 與 BubbleUp&lt;/a>：event-based 資料模型、high-cardinality 查詢設計、BubbleUp 異常偵測、SLO / burn rate、derived columns、dataset 設計與 OTLP ingestion&lt;/li>
&lt;/ul>
&lt;h2 id="migration-playbook">Migration Playbook&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="migrate-from-sentry/">Sentry 遷移到 Honeycomb&lt;/a>：error tracking 轉 event-based observability&lt;/li>
&lt;/ul>
&lt;h2 id="進階主題按需閱讀">進階主題（按需閱讀）&lt;/h2>
&lt;h3 id="bubbleup-分析">BubbleUp 分析&lt;/h3>
&lt;p>子議題：&lt;/p></description><content:encoded><![CDATA[<p>Honeycomb 是 high-cardinality observability SaaS、承擔三個責任：events-based 資料模型（不是 metrics aggregation）、unknown-unknowns 偵錯能力（BubbleUp / Heatmap）、observability-driven SRE 文化代表平台。設計取捨偏向「深度優於廣度」、不追求 Datadog 的 integration 廣度、專注於 high-cardinality + distributed system debugging。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>用 Honeycomb SDK 或 OTel 送 events 到 Honeycomb</li>
<li>用 BubbleUp 找 outlier 模式（unknown-unknowns）</li>
<li>設計 SLO + burn rate alert</li>
<li>配置 Refinery（tail-based sampling）</li>
<li>評估 Honeycomb vs Datadog 的選用判讀</li>
</ol>
<h2 id="最短路徑5-分鐘把-honeycomb-跑起來">最短路徑：5 分鐘把 Honeycomb 跑起來</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 1. 應用程式加 instrumentation（Honeycomb SDK 或 OTel SDK）</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># TODO: HONEYCOMB_API_KEY + dataset 設定</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="c1"># TODO: 用 Beeline SDK 或 OTel + OTLP exporter</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="c1"># 2. 送 sample events</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="c1"># TODO: 觀察 trace 出現在 Honeycomb UI</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl">
</span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="c1"># 3. 用 query 介面查詢</span>
</span></span><span class="line"><span class="ln">9</span><span class="cl"><span class="c1"># TODO: SELECT count + visualize by service.name</span></span></span></code></pre></div><h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="events-vs-metrics-心智模型">Events vs metrics 心智模型</h3>
<p>Honeycomb 跟 metrics-aggregation 平台不同。子議題：</p>
<ul>
<li>Event = 一個 trace span（包含 dozens of attributes）</li>
<li>不預先 aggregate、查詢時 group by 任意 attribute</li>
<li>High-cardinality 不是問題、是設計目標</li>
<li>對應 <a href="/blog/backend/04-observability/cases/gaming-peak-signal-freshness-and-cardinality/" data-link-title="Gaming：高峰流量下的訊號新鮮度與 Cardinality" data-link-desc="在高峰事件中控制訊號延遲與維度爆炸，維持告警與定位可信度。">4.C2 Gaming peak cardinality</a></li>
</ul>
<h3 id="instrumentation">Instrumentation</h3>
<p>子議題：</p>
<ul>
<li><strong>Honeycomb SDK</strong>（Beeline）：簡單、Honeycomb-specific、auto-instrumentation 部分</li>
<li><strong>OTel SDK + OTLP</strong>：標準、vendor-neutral、推薦新部署用</li>
<li>Manual attribute：對 business / domain context attribute 不省略</li>
<li>Refinery：tail-based sampling proxy</li>
</ul>
<h3 id="query-介面">Query 介面</h3>
<p>子議題：</p>
<ul>
<li>Visualize：count / count_distinct / heatmap / p50 / p95 / p99</li>
<li>Group by：任意 attribute（user_id / region / version 等）</li>
<li>Filter：WHERE clause</li>
<li>對應 SLO query：<code>heatmap(duration_ms) GROUP BY service.name WHERE http.status_code = 500</code></li>
</ul>
<h2 id="deep-article">Deep Article</h2>
<ul>
<li><a href="high-cardinality-query-bubbleup/">High-Cardinality Query Model 與 BubbleUp</a>：event-based 資料模型、high-cardinality 查詢設計、BubbleUp 異常偵測、SLO / burn rate、derived columns、dataset 設計與 OTLP ingestion</li>
</ul>
<h2 id="migration-playbook">Migration Playbook</h2>
<ul>
<li><a href="migrate-from-sentry/">Sentry 遷移到 Honeycomb</a>：error tracking 轉 event-based observability</li>
</ul>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<h3 id="bubbleup-分析">BubbleUp 分析</h3>
<p>子議題：</p>
<ul>
<li>給定 heatmap 異常區、自動找區隔 outlier 跟 baseline 的 attribute</li>
<li>適合「我看到 latency spike、但不知道哪個維度造成」</li>
<li>Unknown-unknowns 偵錯模式</li>
<li>跟 Datadog APM 的 service map 對照</li>
</ul>
<h3 id="slo-與-burn-rate-alert">SLO 與 burn rate alert</h3>
<p>子議題：</p>
<ul>
<li>SLO 配置（service + indicator + objective + window）</li>
<li>Burn rate calculation：multi-window multi-burn-rate alert</li>
<li>跟 <a href="/blog/backend/knowledge-cards/burn-rate/" data-link-title="Burn Rate" data-link-desc="說明 error budget 消耗速度如何支援告警與事故分級">knowledge cards burn-rate</a> 對照</li>
<li>對應 <a href="/blog/backend/04-observability/cases/failure-otel-migration-signal-drift/" data-link-title="4.C9 反例：OTel 遷移後訊號漂移" data-link-desc="雙軌採集未對齊導致告警與 SLO 判讀失真。">4.C9 OTel migration signal drift</a></li>
</ul>
<h3 id="refinerytail-based-sampling">Refinery（tail-based sampling）</h3>
<p>子議題：</p>
<ul>
<li>為什麼需要 tail-based：保留有錯 / 高延遲 trace、丟正常 trace</li>
<li>Refinery 部署模式（gateway in front of Honeycomb）</li>
<li>Sampling rule：error / latency / per-service / dynamic</li>
<li>對應成本：100% ingestion 太貴、tail-based 平衡</li>
</ul>
<h3 id="otlp-integration">OTLP integration</h3>
<p>子議題：</p>
<ul>
<li>Honeycomb 接受 OTLP（gRPC / HTTP）</li>
<li>應用層用 OTel SDK、傳給 Honeycomb 不用改 SDK</li>
<li>Multi-backend 支援：同一份 OTel data 送 Honeycomb + 其他</li>
<li>對應 <a href="/blog/backend/04-observability/cases/datadog-otel-migration-practice/" data-link-title="4.C7 Datadog：OTel 相容遷移實務" data-link-desc="APM 採集從專有代理轉向 OTel 相容模式的治理案例。">4.C7 Datadog OTel migration</a></li>
</ul>
<h3 id="結構化-events-設計">結構化 events 設計</h3>
<p>子議題：</p>
<ul>
<li>哪些 attribute 應加（user_id / request_id / business 維度）</li>
<li>哪些 attribute 不該加（PII / secrets）</li>
<li>Wide events 哲學：一個 event 帶 dozens of attributes、不分散到多 metric</li>
<li>對應 PII redaction strategy</li>
</ul>
<h3 id="observability-driven-development">Observability-driven development</h3>
<p>子議題：</p>
<ul>
<li>Charity Majors 提的 SDLC 模式：production debug 是常態</li>
<li>TDD + observability：寫 code 同時思考可觀測性</li>
<li>跟 SRE 文化整合</li>
</ul>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<h3 id="events-沒到-honeycomb">Events 沒到 Honeycomb</h3>
<p>操作原則：先看 SDK 配置（API key + dataset）、再看 network、最後看 Honeycomb status page。</p>
<h3 id="query-timeout">Query timeout</h3>
<p>操作原則：query window 過大或 attribute cardinality 過高造成 backend slow。判讀：縮 time window、簡化 group by。</p>
<h3 id="sampling-過頭-vs-不足">Sampling 過頭 vs 不足</h3>
<p>操作原則：debug 時找不到 trace（sampling 過頭）vs cost 爆（sampling 不足）。Refinery 提供 dynamic sampling 解決靜態 rate 的不足。</p>
<h3 id="burn-rate-alert-noise">Burn rate alert noise</h3>
<p>操作原則：multi-window 設計避免「短暫 spike 觸發 alert」、低 burn rate window 給長期趨勢。</p>
<h3 id="跟其他-backend-dual-ship-不一致">跟其他 backend dual ship 不一致</h3>
<p>對應 <a href="/blog/backend/04-observability/cases/failure-otel-migration-signal-drift/" data-link-title="4.C9 反例：OTel 遷移後訊號漂移" data-link-desc="雙軌採集未對齊導致告警與 SLO 判讀失真。">4.C9 OTel migration signal drift</a>。判讀：兩個 backend 數據不對齊、看 SDK 是否 dual export、attribute mapping 是否一致。</p>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>廣度大、要 600+ integrations</td>
          <td><a href="/blog/backend/04-observability/vendors/datadog/" data-link-title="Datadog" data-link-desc="All-in-one SaaS 觀測平台、APM / Logs / Metrics / RUM / Security">Datadog</a></td>
      </tr>
      <tr>
          <td>預算敏感</td>
          <td><a href="/blog/backend/04-observability/vendors/grafana-stack/" data-link-title="Grafana Stack" data-link-desc="Grafana / Loki / Tempo / Mimir / Pyroscope 全棧">Grafana Stack</a>（OSS）</td>
      </tr>
      <tr>
          <td>Pure metrics</td>
          <td><a href="/blog/backend/04-observability/vendors/prometheus/" data-link-title="Prometheus" data-link-desc="Pull-based metrics 主流 OSS、PromQL 與 alerting">Prometheus</a></td>
      </tr>
      <tr>
          <td>Logs full-text</td>
          <td><a href="/blog/backend/04-observability/vendors/elastic-stack/" data-link-title="Elastic Stack" data-link-desc="ELK：Elasticsearch / Logstash / Kibana &#43; Beats / APM">Elastic Stack</a></td>
      </tr>
      <tr>
          <td>Error tracking 為主</td>
          <td><a href="/blog/backend/04-observability/vendors/sentry/" data-link-title="Sentry" data-link-desc="Error tracking 主流、APM / Profiling / Session Replay 擴展">Sentry</a></td>
      </tr>
      <tr>
          <td>Cloud-native (AWS / GCP)</td>
          <td><a href="/blog/backend/04-observability/vendors/aws-cloudwatch/" data-link-title="AWS CloudWatch" data-link-desc="AWS 原生觀測性服務、Logs / Metrics / Traces (X-Ray)">CloudWatch</a> / <a href="/blog/backend/04-observability/vendors/gcp-cloud-operations/" data-link-title="GCP Cloud Operations" data-link-desc="GCP 原生觀測性套件（前 Stackdriver）：Logging / Monitoring / Trace / Profiler">Cloud Ops</a></td>
      </tr>
      <tr>
          <td>Self-hosted</td>
          <td>OSS observability（Honeycomb 是 SaaS only）</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Honeycomb SDK 完整 API</li>
<li>BubbleUp 內部演算法</li>
<li>Refinery 詳細配置</li>
<li>Honeycomb pricing 詳細</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<h3 id="直接相關案例">直接相關案例</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>主討論議題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/gaming-peak-signal-freshness-and-cardinality/" data-link-title="Gaming：高峰流量下的訊號新鮮度與 Cardinality" data-link-desc="在高峰事件中控制訊號延遲與維度爆炸，維持告警與定位可信度。">4.C2 Gaming peak cardinality</a></td>
          <td>High-cardinality debug pattern</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/failure-otel-migration-signal-drift/" data-link-title="4.C9 反例：OTel 遷移後訊號漂移" data-link-desc="雙軌採集未對齊導致告警與 SLO 判讀失真。">4.C9 OTel signal drift</a></td>
          <td>（反例）Refinery / dual ship 對齊驗證</td>
      </tr>
  </tbody>
</table>
<h3 id="跨-vendor-對照">跨 vendor 對照</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>對 Honeycomb 的對應</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/datadog-otel-migration-practice/" data-link-title="4.C7 Datadog：OTel 相容遷移實務" data-link-desc="APM 採集從專有代理轉向 OTel 相容模式的治理案例。">4.C7 Datadog OTel migration</a></td>
          <td>從 Datadog APM 遷出時 Honeycomb 是 events 替代</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/airbnb-observability-k8s-scale-signals/" data-link-title="4.C8 Airbnb：Kubernetes 規模化下的觀測訊號治理" data-link-desc="叢集擴縮與工作負載變動如何回寫觀測模型。">4.C8 Airbnb K8s scale signals</a></td>
          <td>動態叢集下 wide events 補 metrics 維度不足</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/contrast-observability-rollout-by-scale/" data-link-title="4.C10 對照：規模差異下的觀測遷移" data-link-desc="觀測遷移在不同規模團隊下的流程與風險差異。">4.C10 規模對照</a></td>
          <td>Honeycomb 適合中大型 + observability-driven team</td>
      </tr>
  </tbody>
</table>
<p><strong>待補 Honeycomb 案例</strong>：Charity Majors 的 production talks、Honeycomb customer engineering blog、Refinery scale-up case。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游概念：<a href="/blog/backend/04-observability/telemetry-data-quality/" data-link-title="4.17 Telemetry Data Quality" data-link-desc="把 missing signal、schema drift、sampling bias 與 timestamp skew 變成資料品質問題">4.17 Telemetry Data Quality</a></li>
<li>平行 vendor：<a href="/blog/backend/04-observability/vendors/opentelemetry/" data-link-title="OpenTelemetry" data-link-desc="可觀測性開放標準、SDK 與 Collector">OpenTelemetry</a>、<a href="/blog/backend/04-observability/vendors/datadog/" data-link-title="Datadog" data-link-desc="All-in-one SaaS 觀測平台、APM / Logs / Metrics / RUM / Security">Datadog</a></li>
<li>下游能力：<a href="/blog/backend/06-reliability/" data-link-title="模組六：可靠性驗證流程" data-link-desc="用 SRE 領域詞彙建問題節點、以服務級案例庫累積驗證脈絡，先建概念與案例庫再進實作交接">06 reliability 模組</a>（SLO / burn rate）、<a href="/blog/backend/04-observability/observability-evidence-package/" data-link-title="4.20 Observability Evidence Package" data-link-desc="把 log、metric、trace、audit 與資料品質限制包成可交接證據">4.20 Evidence Package</a></li>
</ul>
]]></content:encoded></item><item><title>Locust</title><link>https://tarrragon.github.io/blog/backend/06-reliability/vendors/locust/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/06-reliability/vendors/locust/</guid><description>&lt;p>Locust 是 Python-based load test 工具、承擔三個責任：Python class-based test 設計（user behavior 表達力強）、distributed mode（master / worker 內建）、Web UI 即時觀察。設計取捨偏向「Python DX + 高度自訂邏輯 + 任何 Python lib 都可用」、適合 Python 團隊與需要極高自訂邏輯的場景。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>寫 Locust user class + task&lt;/li>
&lt;li>跑 standalone + distributed mode&lt;/li>
&lt;li>自訂 client（非 HTTP、如 gRPC / WebSocket）&lt;/li>
&lt;li>設計 task weight + on_start / on_stop hook&lt;/li>
&lt;li>評估 Locust vs k6 / Gatling 的選用&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑5-分鐘把-locust-跑起來">最短路徑：5 分鐘把 Locust 跑起來&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 1. 安裝&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: pip install locust&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="c1"># 2. 寫 locustfile.py&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: class User(HttpUser): wait_time = ..., @task def hello(self): ...&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">&lt;span class="c1"># 3. 跑&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: locust -f locustfile.py --host=http://target&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">9&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: 瀏覽器 http://localhost:8089 操作&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="日常操作與決策形狀">日常操作與決策形狀&lt;/h2>
&lt;h3 id="user-class--task">User class + task&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>HttpUser / FastHttpUser（FastHttpUser 用 geventhttpclient、效能高）&lt;/li>
&lt;li>@task decorator + weight&lt;/li>
&lt;li>on_start / on_stop（per-VU setup / teardown）&lt;/li>
&lt;li>對應 Python class inheritance&lt;/li>
&lt;/ul>
&lt;h3 id="distributed-mode">Distributed mode&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>master：協調 + 收集 metric&lt;/li>
&lt;li>worker：實際發送 request&lt;/li>
&lt;li>&lt;code>locust --master&lt;/code> / &lt;code>locust --worker --master-host=...&lt;/code>&lt;/li>
&lt;li>多 worker 突破 Python GIL 限制&lt;/li>
&lt;/ul>
&lt;h3 id="web-ui-vs-headless">Web UI vs headless&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>Web UI（dev / interactive）&lt;/li>
&lt;li>Headless（&lt;code>--headless --users N --spawn-rate N --run-time T&lt;/code>）&lt;/li>
&lt;li>對應 CI 整合：CSV report&lt;/li>
&lt;/ul>
&lt;h2 id="進階主題按需閱讀">進階主題（按需閱讀）&lt;/h2>
&lt;h3 id="自訂-client非-http">自訂 client（非 HTTP）&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>任何 Python lib 都可包成 user&lt;/li>
&lt;li>gRPC / WebSocket / database / queue 都行&lt;/li>
&lt;li>request event 手動 fire&lt;/li>
&lt;/ul>
&lt;h3 id="custom-request">Custom request&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>self.client.get/post（HTTP）&lt;/li>
&lt;li>自訂 event emission&lt;/li>
&lt;li>Custom statistics&lt;/li>
&lt;/ul>
&lt;h3 id="locust-plugins-生態">locust-plugins 生態&lt;/h3>
&lt;p>子議題：&lt;/p></description><content:encoded><![CDATA[<p>Locust 是 Python-based load test 工具、承擔三個責任：Python class-based test 設計（user behavior 表達力強）、distributed mode（master / worker 內建）、Web UI 即時觀察。設計取捨偏向「Python DX + 高度自訂邏輯 + 任何 Python lib 都可用」、適合 Python 團隊與需要極高自訂邏輯的場景。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>寫 Locust user class + task</li>
<li>跑 standalone + distributed mode</li>
<li>自訂 client（非 HTTP、如 gRPC / WebSocket）</li>
<li>設計 task weight + on_start / on_stop hook</li>
<li>評估 Locust vs k6 / Gatling 的選用</li>
</ol>
<h2 id="最短路徑5-分鐘把-locust-跑起來">最短路徑：5 分鐘把 Locust 跑起來</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 1. 安裝</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># TODO: pip install locust</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 2. 寫 locustfile.py</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="c1"># TODO: class User(HttpUser): wait_time = ..., @task def hello(self): ...</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="c1"># 3. 跑</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="c1"># TODO: locust -f locustfile.py --host=http://target</span>
</span></span><span class="line"><span class="ln">9</span><span class="cl"><span class="c1"># TODO: 瀏覽器 http://localhost:8089 操作</span></span></span></code></pre></div><h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="user-class--task">User class + task</h3>
<p>子議題：</p>
<ul>
<li>HttpUser / FastHttpUser（FastHttpUser 用 geventhttpclient、效能高）</li>
<li>@task decorator + weight</li>
<li>on_start / on_stop（per-VU setup / teardown）</li>
<li>對應 Python class inheritance</li>
</ul>
<h3 id="distributed-mode">Distributed mode</h3>
<p>子議題：</p>
<ul>
<li>master：協調 + 收集 metric</li>
<li>worker：實際發送 request</li>
<li><code>locust --master</code> / <code>locust --worker --master-host=...</code></li>
<li>多 worker 突破 Python GIL 限制</li>
</ul>
<h3 id="web-ui-vs-headless">Web UI vs headless</h3>
<p>子議題：</p>
<ul>
<li>Web UI（dev / interactive）</li>
<li>Headless（<code>--headless --users N --spawn-rate N --run-time T</code>）</li>
<li>對應 CI 整合：CSV report</li>
</ul>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<h3 id="自訂-client非-http">自訂 client（非 HTTP）</h3>
<p>子議題：</p>
<ul>
<li>任何 Python lib 都可包成 user</li>
<li>gRPC / WebSocket / database / queue 都行</li>
<li>request event 手動 fire</li>
</ul>
<h3 id="custom-request">Custom request</h3>
<p>子議題：</p>
<ul>
<li>self.client.get/post（HTTP）</li>
<li>自訂 event emission</li>
<li>Custom statistics</li>
</ul>
<h3 id="locust-plugins-生態">locust-plugins 生態</h3>
<p>子議題：</p>
<ul>
<li>locust-plugins：第三方 plugin（CSV report enhanced / Postgres / Kafka / etc）</li>
<li>Custom shape（dynamic load profile）</li>
<li>TaskSet / SequentialTaskSet</li>
</ul>
<h3 id="ci-integration">CI integration</h3>
<p>子議題：</p>
<ul>
<li>Headless mode + exit code</li>
<li>CSV / JSON report</li>
<li>對應 <a href="/blog/backend/06-reliability/release-gate/" data-link-title="6.8 Release Gate 與變更節奏" data-link-desc="把驗證、migration、相容性納入放行判準">6.8 Release Gate</a></li>
</ul>
<h3 id="distributed-scaling">Distributed scaling</h3>
<p>子議題：</p>
<ul>
<li>Kubernetes 部署</li>
<li>多 region load source</li>
<li>Result aggregation</li>
</ul>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<h3 id="high-vu-跑不上去">High VU 跑不上去</h3>
<p>操作原則：Python GIL + 單 worker 限制、用 distributed mode。判讀：CPU / network bottleneck？</p>
<h3 id="worker-disconnect">Worker disconnect</h3>
<p>操作原則：master / worker network 不通、heartbeat timeout。判讀：log + master UI。</p>
<h3 id="custom-protocol-報告不正確">Custom protocol 報告不正確</h3>
<p>操作原則：手動 event fire 缺 / metric name 不對。</p>
<h3 id="memory-leak">Memory leak</h3>
<p>操作原則：long run test、user state accumulate。判讀：on_stop cleanup。</p>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>編譯後分發 / 高 VU 單機</td>
          <td><a href="/blog/backend/06-reliability/vendors/k6/" data-link-title="k6" data-link-desc="現代 load test、JS scripting、Grafana Labs">k6</a></td>
      </tr>
      <tr>
          <td>JVM 生態</td>
          <td><a href="/blog/backend/06-reliability/vendors/gatling/" data-link-title="Gatling" data-link-desc="JVM-based load test、Scala / Java / Kotlin DSL、強型別 scenario、HAR-driven recording">Gatling</a></td>
      </tr>
      <tr>
          <td>GUI / 老牌</td>
          <td><a href="/blog/backend/06-reliability/vendors/jmeter/" data-link-title="Apache JMeter" data-link-desc="老牌 load test 工具、GUI &#43; plugins">JMeter</a></td>
      </tr>
      <tr>
          <td>Cloud managed</td>
          <td>k6 Cloud / BlazeMeter / Locust 自管 K8s</td>
      </tr>
      <tr>
          <td>Capacity planning</td>
          <td><a href="/blog/backend/09-performance-capacity/" data-link-title="模組九：效能工程與容量規劃" data-link-desc="把『目前配置能撐多少、要加多少機器』變成可量化、可驗證、可改進的工程流程">09 performance capacity 模組</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Python 語言基礎</li>
<li>gevent / asyncio 內部</li>
<li>locust-plugins 完整列表</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<table>
  <thead>
      <tr>
          <th>案例方向</th>
          <th>對應主題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/06-reliability/cases/linkedin/capacity-headroom-and-oncall-tiering/" data-link-title="LinkedIn：Capacity Headroom 與 On-call 分層" data-link-desc="把容量預測與值班分層綁在一起，降低高峰時段的升級混亂與恢復延遲。">LinkedIn：Capacity 與 On-call 分層</a></td>
          <td>automated load testing 對齊 headroom 預測（Python 場景）</td>
      </tr>
  </tbody>
</table>
<p><strong>Case 庫稀薄</strong>：本 cases/ 目錄目前沒有以 Locust 為主軸的案例。可參考候選方向：</p>
<ul>
<li><strong>待補 Locust customer case</strong>：Python-heavy 團隊 load test 採用案例、distributed Locust 大規模部署案例</li>
<li><strong>候選 case</strong>：Pinterest（ML serving / 推薦系統壓測場景）、Spotify（squad-based 各團隊自管壓測）— 若未來收錄需先在 cases/ 補正文，本欄再寫實際 link</li>
</ul>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游概念：<a href="/blog/backend/06-reliability/performance-regression-gate/" data-link-title="6.13 Performance Regression Gate" data-link-desc="把效能 baseline 從一次性壓測變成持續對齊的 release gate，涵蓋 baseline 設定、判讀方法、variance 控制與退化定位">6.13 Performance Regression Gate</a></li>
<li>平行 vendor：<a href="/blog/backend/06-reliability/vendors/k6/" data-link-title="k6" data-link-desc="現代 load test、JS scripting、Grafana Labs">k6</a>、<a href="/blog/backend/06-reliability/vendors/gatling/" data-link-title="Gatling" data-link-desc="JVM-based load test、Scala / Java / Kotlin DSL、強型別 scenario、HAR-driven recording">Gatling</a></li>
<li>下游能力：<a href="/blog/backend/09-performance-capacity/" data-link-title="模組九：效能工程與容量規劃" data-link-desc="把『目前配置能撐多少、要加多少機器』變成可量化、可驗證、可改進的工程流程">09 performance capacity</a></li>
</ul>
]]></content:encoded></item><item><title>Rootly</title><link>https://tarrragon.github.io/blog/backend/08-incident-response/vendors/rootly/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/08-incident-response/vendors/rootly/</guid><description>&lt;p>Rootly 是 IR 平台、承擔三個責任：no-code workflow builder（拖拉式自動化）、AI 輔助 retrospective + timeline 整理、Slack / Teams 雙平台整合 + integration 數量最廣（200+）。產品迭代快、跟 &lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/vendors/incident-io/" data-link-title="incident.io" data-link-desc="Slack-native IR 平台、整合 paging / response / retro">incident.io&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/vendors/firehydrant/" data-link-title="FireHydrant" data-link-desc="IR &amp;#43; retrospective 平台、Slack / Teams 整合、service catalog &amp;#43; runbook automation 為核心">FireHydrant&lt;/a> 三家構成 modern IR 平台主要選項。2023+ 加入 Rootly AI 模組做 incident enrichment 與 retrospective auto-draft、把 IR 平台從 &lt;em>workflow 自動化&lt;/em> 推到 &lt;em>AI-assisted investigation&lt;/em>。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Rootly 的核心定位是 &lt;em>Slack-native IR platform + no-code automation engine&lt;/em>、目標客戶是「想最大化降低 incident response toil」的 AI-first / engineering-led 組織。產品主軸：&lt;em>no-code workflow builder&lt;/em>（IFTTT-style condition / action 鏈、不需工程 deploy）+ &lt;em>Rootly AI&lt;/em>（incident summarization / enrichment / retrospective auto-draft）+ &lt;em>Slack / Teams 雙平台對等支援&lt;/em>。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/vendors/pagerduty/" data-link-title="PagerDuty" data-link-desc="On-call / alerting 主流 SaaS、IR 平台演化">PagerDuty&lt;/a> 比、PagerDuty 是 alerting-first（on-call schedule + escalation 為核心）、Rootly 是 IR-process-first（incident workflow + retro 為核心）、兩家常一起用（PagerDuty 負責 page、Rootly 接 declare 後的 process）。跟 &lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/vendors/incident-io/" data-link-title="incident.io" data-link-desc="Slack-native IR 平台、整合 paging / response / retro">incident.io&lt;/a> 比、incident.io 走 &lt;em>opinionated minimal&lt;/em>（流程固定、學習快）、Rootly 走 &lt;em>configurable maximal&lt;/em>（workflow 可深度客製、學習曲線稍陡）。跟 &lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/vendors/firehydrant/" data-link-title="FireHydrant" data-link-desc="IR &amp;#43; retrospective 平台、Slack / Teams 整合、service catalog &amp;#43; runbook automation 為核心">FireHydrant&lt;/a> 比、FireHydrant 在 service catalog / runbook 結構更剛、Rootly 在 AI + integration 廣度更領先。&lt;/p>
&lt;p>關鍵張力：&lt;em>no-code 客製深度&lt;/em> ↔ &lt;em>配置複雜度&lt;/em> 是 Rootly 客戶最大的 trade-off — workflow 可以做得很深，但配多了會出現 &lt;em>workflow loop / 通知爆量 / AI summary 失準&lt;/em>，需要有人定期 review workflow inventory。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本頁、讀者能判斷：&lt;/p>
&lt;ol>
&lt;li>用 no-code builder 設計 incident workflow（trigger / condition / action）&lt;/li>
&lt;li>配置 severity matrix + role assignment&lt;/li>
&lt;li>用 Rootly AI 輔助 timeline + retrospective、了解 AI 失準的邊界&lt;/li>
&lt;li>整合 200+ tool（觀測 / cloud / collaboration / ticket / paging）&lt;/li>
&lt;li>評估 Rootly vs incident.io / FireHydrant / PagerDuty 的取捨&lt;/li>
&lt;/ol>
&lt;h2 id="最短判讀路徑">最短判讀路徑&lt;/h2>
&lt;p>判斷 Rootly deployment 是否健康、最少看四件事：&lt;/p></description><content:encoded><![CDATA[<p>Rootly 是 IR 平台、承擔三個責任：no-code workflow builder（拖拉式自動化）、AI 輔助 retrospective + timeline 整理、Slack / Teams 雙平台整合 + integration 數量最廣（200+）。產品迭代快、跟 <a href="/blog/backend/08-incident-response/vendors/incident-io/" data-link-title="incident.io" data-link-desc="Slack-native IR 平台、整合 paging / response / retro">incident.io</a> / <a href="/blog/backend/08-incident-response/vendors/firehydrant/" data-link-title="FireHydrant" data-link-desc="IR &#43; retrospective 平台、Slack / Teams 整合、service catalog &#43; runbook automation 為核心">FireHydrant</a> 三家構成 modern IR 平台主要選項。2023+ 加入 Rootly AI 模組做 incident enrichment 與 retrospective auto-draft、把 IR 平台從 <em>workflow 自動化</em> 推到 <em>AI-assisted investigation</em>。</p>
<h2 id="服務定位">服務定位</h2>
<p>Rootly 的核心定位是 <em>Slack-native IR platform + no-code automation engine</em>、目標客戶是「想最大化降低 incident response toil」的 AI-first / engineering-led 組織。產品主軸：<em>no-code workflow builder</em>（IFTTT-style condition / action 鏈、不需工程 deploy）+ <em>Rootly AI</em>（incident summarization / enrichment / retrospective auto-draft）+ <em>Slack / Teams 雙平台對等支援</em>。</p>
<p>跟 <a href="/blog/backend/08-incident-response/vendors/pagerduty/" data-link-title="PagerDuty" data-link-desc="On-call / alerting 主流 SaaS、IR 平台演化">PagerDuty</a> 比、PagerDuty 是 alerting-first（on-call schedule + escalation 為核心）、Rootly 是 IR-process-first（incident workflow + retro 為核心）、兩家常一起用（PagerDuty 負責 page、Rootly 接 declare 後的 process）。跟 <a href="/blog/backend/08-incident-response/vendors/incident-io/" data-link-title="incident.io" data-link-desc="Slack-native IR 平台、整合 paging / response / retro">incident.io</a> 比、incident.io 走 <em>opinionated minimal</em>（流程固定、學習快）、Rootly 走 <em>configurable maximal</em>（workflow 可深度客製、學習曲線稍陡）。跟 <a href="/blog/backend/08-incident-response/vendors/firehydrant/" data-link-title="FireHydrant" data-link-desc="IR &#43; retrospective 平台、Slack / Teams 整合、service catalog &#43; runbook automation 為核心">FireHydrant</a> 比、FireHydrant 在 service catalog / runbook 結構更剛、Rootly 在 AI + integration 廣度更領先。</p>
<p>關鍵張力：<em>no-code 客製深度</em> ↔ <em>配置複雜度</em> 是 Rootly 客戶最大的 trade-off — workflow 可以做得很深，但配多了會出現 <em>workflow loop / 通知爆量 / AI summary 失準</em>，需要有人定期 review workflow inventory。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>用 no-code builder 設計 incident workflow（trigger / condition / action）</li>
<li>配置 severity matrix + role assignment</li>
<li>用 Rootly AI 輔助 timeline + retrospective、了解 AI 失準的邊界</li>
<li>整合 200+ tool（觀測 / cloud / collaboration / ticket / paging）</li>
<li>評估 Rootly vs incident.io / FireHydrant / PagerDuty 的取捨</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Rootly deployment 是否健康、最少看四件事：</p>
<ul>
<li><strong>Slack workflow 入口統一</strong>：<code>/rootly declare</code> 是否唯一 declare 入口、severity / service / role 是否在 declare 時就 bind、Slack channel naming convention（<code>inc-YYYY-MM-DD-slug</code>）跟 retention 是否設定</li>
<li><strong>No-code automation 治理</strong>：workflow 數量 / owner / 上次 review 時間是否有 inventory、有沒有 staging tenant 跑新 workflow、production workflow change 是否走 PR-like review</li>
<li><strong>AI integration 邊界</strong>：Rootly AI 用在哪些環節（incident summary / timeline enrichment / retrospective draft）、AI 輸出是否標記為 draft 而非 finalized、AI hallucination 的 human review gate 是否定義</li>
<li><strong>SSO + audit + integration health</strong>：SSO（Okta / Azure AD）+ audit log（誰改 workflow / 誰 close incident）是否開、Integration token 是否定期 rotate、Jira / Linear / GitHub PR / PagerDuty / Opsgenie 對接是否雙向同步</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/08-incident-response/drills-and-oncall-readiness/" data-link-title="8.6 演練與值班能力建設" data-link-desc="用演練與值班訓練提升事故反應品質">Drills and On-call Readiness</a> 邊界的待補項目。</p>
<h2 id="最短路徑">最短路徑</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 1. Slack / Teams install Rootly app</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># 2. /rootly declare 建 test incident</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="c1"># 3. 拖拉 workflow（severity → action）</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 4. Close + AI retrospective</span></span></span></code></pre></div><h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="no-code-workflow-builder">No-code workflow builder</h3>
<p>子議題：</p>
<ul>
<li>Trigger（severity / status / time）→ Action（page / message / ticket）</li>
<li>Branch / condition / parallel</li>
<li>Custom field bind</li>
</ul>
<p><strong>IFTTT-style 邏輯</strong>：workflow 是 <em>trigger → condition → action</em> 的 DAG、可以 branch / parallel / loop（loop 要小心、見排錯）。典型 production workflow：「severity SEV1 declared → page on-call via PagerDuty + create Jira ticket + post status page draft + invite security lead to Slack channel」。複雜度上限是「能 express 在 UI 拖拉上」、超過這個複雜度應該寫 webhook 接外部 orchestrator。</p>
<h3 id="ai-retrospective--slackteams-workflow">AI retrospective + Slack/Teams workflow</h3>
<p>子議題：</p>
<ul>
<li>自動 timeline from Slack messages</li>
<li>AI summary（what happened / contributing factor）</li>
<li>同 incident.io / FireHydrant Slack workflow</li>
<li>Teams 平等支援</li>
<li>Mobile app</li>
</ul>
<p><strong>Rootly AI 的能力邊界</strong>：AI 從 Slack channel 訊息抽 timeline、產生 <em>contributing factor</em> draft、列 <em>action item</em> candidate。產出是 <em>draft、不是 finalized retrospective</em> — IR lead 應該逐項驗證再 publish、AI hallucination 在 contributing factor / blame attribution 段最常出現（見排錯段）。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Rootly</th>
          <th>incident.io</th>
          <th>FireHydrant</th>
          <th>PagerDuty</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>核心定位</td>
          <td>No-code workflow + AI investigation</td>
          <td>Opinionated Slack-native IR</td>
          <td>Service catalog + runbook 結構</td>
          <td>Alerting + on-call schedule</td>
      </tr>
      <tr>
          <td>客製化深度</td>
          <td>高 — workflow builder + custom field</td>
          <td>中 — 流程相對固定</td>
          <td>中高 — runbook + catalog 模型清晰</td>
          <td>中 — escalation 配置強、流程較輕</td>
      </tr>
      <tr>
          <td>AI 能力</td>
          <td>Rootly AI（summary / enrich / retro）</td>
          <td>AI 摘要（較新、範圍較窄）</td>
          <td>較少強調 AI</td>
          <td>AIOps（alert grouping）</td>
      </tr>
      <tr>
          <td>平台支援</td>
          <td>Slack + Teams 對等</td>
          <td>Slack-first（Teams 較弱）</td>
          <td>Slack + Teams</td>
          <td>Slack / Teams / Mobile / Email</td>
      </tr>
      <tr>
          <td>Integration 廣度</td>
          <td>200+（業界最廣）</td>
          <td>中（Slack ecosystem 為主）</td>
          <td>中高</td>
          <td>最廣（paging ecosystem）</td>
      </tr>
      <tr>
          <td>學習曲線</td>
          <td>中陡 — 配置選項多</td>
          <td>緩 — 流程少</td>
          <td>中 — service model 要先想清楚</td>
          <td>中 — escalation policy 要先設計</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>AI-first / 想自動化 toil / Slack-heavy</td>
          <td>小到中型、想快上手 + 流程一致</td>
          <td>中大型、service ownership 清楚</td>
          <td>任何需要強 paging 的團隊</td>
      </tr>
      <tr>
          <td>退場成本</td>
          <td>中 — workflow / custom field 量會綁</td>
          <td>低 — 流程相對標準</td>
          <td>中 — service catalog 綁定深</td>
          <td>高 — schedule + integration 量大</td>
      </tr>
  </tbody>
</table>
<p>選 Rootly 的核心訴求：<em>Slack-native IR + 想用 no-code + AI 把 incident process toil 自動化最大化</em>、且能投入時間維護 workflow inventory（避免 workflow sprawl）。需要重 paging 的團隊通常 Rootly + PagerDuty 並用（Rootly 不取代 PagerDuty 的 schedule + escalation）。</p>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<h3 id="rootly-ai-深入">Rootly AI 深入</h3>
<p>子議題：incident summary（給 stakeholder broadcast 用）、enrichment（自動補 service owner / recent deploy / related incident）、retrospective auto-draft（timeline + contributing factor + action item）。AI 輸出是 <em>draft</em>、需要 human review gate 才 publish。對 <a href="/blog/backend/08-incident-response/incident-evidence-write-back/" data-link-title="8.22 Incident Evidence Write-back" data-link-desc="把事故證據、決策與復盤結論回寫到 observability、reliability 與 runbook">Incident Evidence Write-back</a> 的影響是「快、但要驗」、不能把 AI draft 直接當成 source of truth。</p>
<h3 id="no-code-workflow-進階">No-code workflow 進階</h3>
<p>子議題：condition expression（field / value / operator）、parallel branch、wait / delay、custom webhook action 接外部 orchestrator。複雜 workflow 應該 <em>先在 staging tenant 跑</em>、production workflow change 走 review。Workflow loop（A workflow 觸發 B、B 觸發 A）會在 misconfig 時出現、見排錯段。</p>
<h3 id="ticket--pr--paging-integration">Ticket / PR / paging integration</h3>
<p>子議題：Jira / Linear 雙向同步（incident close 同步 ticket、ticket update 帶回 Slack）、GitHub PR 自動連 incident（commit message 含 incident ID）、PagerDuty / Opsgenie alerting layer 對接（page 從 PagerDuty 來、process 在 Rootly 跑）。Integration token 失效是常見 silent failure、需要 monitoring。</p>
<h3 id="integration-廣度">Integration 廣度</h3>
<p>子議題：觀測（Datadog / Grafana / New Relic / Honeycomb）/ Cloud（AWS / GCP / Azure）/ Collaboration（Slack / Teams / Zoom）/ Ticket（Jira / Linear / GitHub）/ Status page</p>
<h3 id="service-catalog--custom-field">Service catalog + Custom field</h3>
<p>子議題：service / team / customer metadata、custom field 帶業務 context、workflow trigger by field</p>
<h3 id="on-call-模組">On-call 模組</h3>
<p>子議題：Rootly OnCall（schedule + escalation）、跟 IR workflow 同 app</p>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<ul>
<li><strong>Workflow 行為不符</strong>：trigger / condition 邏輯錯、看 workflow run log</li>
<li><strong>AI summary / retrospective 失準</strong>：Slack noise 多、AI 對 contributing factor / blame attribution hallucinate — 手動補 timeline、AI 輸出標記為 draft、由 IR lead 逐項驗證才 publish</li>
<li><strong>Workflow loop / 通知爆量</strong>：A workflow 觸發 B、B 又觸發 A、Slack 訊息或 ticket 暴衝 — 在 staging tenant pre-test、production workflow change 走 review、加 rate limit / loop detection</li>
<li><strong>Slack notification overload</strong>：每個 severity 都 broadcast 全公司 channel — 設 severity threshold、SEV3 以下走 team channel、SEV1/2 才 broadcast</li>
<li><strong>Integration token 失效</strong>：rotate / OAuth re-auth、加 integration health monitoring（token expiry alert）</li>
<li><strong>Slack channel 亂</strong>：naming convention（<code>inc-YYYY-MM-DD-slug</code>）/ retention 沒設、舊 incident channel 累積成千</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Slack-only / 簡潔</td>
          <td><a href="/blog/backend/08-incident-response/vendors/incident-io/" data-link-title="incident.io" data-link-desc="Slack-native IR 平台、整合 paging / response / retro">incident.io</a></td>
      </tr>
      <tr>
          <td>Microsoft Teams</td>
          <td><a href="/blog/backend/08-incident-response/vendors/firehydrant/" data-link-title="FireHydrant" data-link-desc="IR &#43; retrospective 平台、Slack / Teams 整合、service catalog &#43; runbook automation 為核心">FireHydrant</a></td>
      </tr>
      <tr>
          <td>Paging-first</td>
          <td><a href="/blog/backend/08-incident-response/vendors/pagerduty/" data-link-title="PagerDuty" data-link-desc="On-call / alerting 主流 SaaS、IR 平台演化">PagerDuty</a></td>
      </tr>
      <tr>
          <td>Learning-focused</td>
          <td><a href="/blog/backend/08-incident-response/vendors/jeli/" data-link-title="Jeli" data-link-desc="Post-incident learning 平台、2023 被 PagerDuty 收購、強調 interview-driven narrative 而非 timeline-only retro">Jeli</a></td>
      </tr>
      <tr>
          <td>自建 Slack workflow</td>
          <td>Slack + GitHub Issues / Linear</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>AI model / training detail / Pricing / 200+ integration 個別 setup</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p><strong>Rootly 主打 Slack-native + AI-assisted IR</strong>：本案例庫尚無直接揭露 Rootly 使用細節的事故；可參照的閱讀脈絡是「Slack-centric 協作 + 自動化 retro + AI-first 組織想 minimize IR toil」的服務事故。</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>對應主題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/08-incident-response/cases/slack/" data-link-title="Slack" data-link-desc="Slack 通訊服務事故與外部狀態頁設計">Slack cases</a></td>
          <td>Slack-native IR 平台在通訊平台自身事故下的回退</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/08-incident-response/cases/reddit/" data-link-title="Reddit" data-link-desc="Reddit Pi Day 2023 k8s 升級事故">Reddit cases</a></td>
          <td>mid-size 平台升級事故的 retro 結構（對照素材）</td>
      </tr>
  </tbody>
</table>
<p>待補 candidate：NVIDIA / Figma / Canva 等 Rootly 公開 customer story。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/08-incident-response/drills-and-oncall-readiness/" data-link-title="8.6 演練與值班能力建設" data-link-desc="用演練與值班訓練提升事故反應品質">Drills and On-call Readiness</a></li>
<li>平行：<a href="/blog/backend/08-incident-response/vendors/incident-io/" data-link-title="incident.io" data-link-desc="Slack-native IR 平台、整合 paging / response / retro">incident.io</a>、<a href="/blog/backend/08-incident-response/vendors/firehydrant/" data-link-title="FireHydrant" data-link-desc="IR &#43; retrospective 平台、Slack / Teams 整合、service catalog &#43; runbook automation 為核心">FireHydrant</a>、<a href="/blog/backend/08-incident-response/vendors/pagerduty/" data-link-title="PagerDuty" data-link-desc="On-call / alerting 主流 SaaS、IR 平台演化">PagerDuty</a></li>
<li>下游：<a href="/blog/backend/08-incident-response/incident-evidence-write-back/" data-link-title="8.22 Incident Evidence Write-back" data-link-desc="把事故證據、決策與復盤結論回寫到 observability、reliability 與 runbook">8.22 Incident Evidence Write-back</a></li>
</ul>
]]></content:encoded></item><item><title>Momento</title><link>https://tarrragon.github.io/blog/backend/02-cache-redis/vendors/momento/</link><pubDate>Tue, 16 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/02-cache-redis/vendors/momento/</guid><description>&lt;p>Momento 是 serverless cache 服務、承擔三個責任：把 cache 變成一個按用量計費的 API（沒有 node、沒有 cluster、不規劃容量）、自動隨流量 scale（尖峰自動擴、閒置不付固定費）、提供原生 SDK 與 Redis / Memcached 相容介面（既有 client 可遷）。設計取捨偏向「把 cache 的容量規劃與維運完全消除、用計費換掉 sizing」、是不想養 cache 叢集又要彈性的選項。&lt;/p>
&lt;p>對「流量不可預測、不想規劃容量與 sizing、團隊沒有 cache 運維資源」這條路徑、Momento 是 serverless 方向的代表。它跟自管 Redis、managed cache 的上層取捨（自管 vs managed vs serverless vs BaaS bundle）見 &lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/capability-buy-vs-build/" data-link-title="0.22 能力級買 vs 建：feature-as-a-service 與 BaaS bundle 選型" data-link-desc="在交付形態決定整個系統要不要自建之後、逐能力判斷該外包還是自建：辨識 managed 基礎設施、feature SaaS 與 BaaS bundle 三種外包深度、no-code 到 dev-tool 的服務光譜、買 vs 建判準與權重浮動、整合接縫與遷出代價">0.22 能力級買 vs 建&lt;/a>。&lt;/p>
&lt;blockquote>
&lt;p>本頁的計費、limit 與功能宣稱以 &lt;a href="https://docs.momentohq.com/">Momento 官方文件&lt;/a> 與 &lt;a href="https://www.gomomento.com/pricing/">Momento 定價&lt;/a> 為準、最後檢查日 2026-06-16。Momento 是 SaaS、需帳號與 API key、無法本機 docker 驗證、指令為依官方文件的範例。&lt;/p>&lt;/blockquote>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>理解 serverless cache 跟 node-based / managed cache 的計費與維運差異&lt;/li>
&lt;li>評估按用量計費（per request + data transfer）對你的流量形狀划不划算&lt;/li>
&lt;li>判斷 Momento 原生 SDK vs Redis 相容介面的遷移路徑&lt;/li>
&lt;li>區分 Momento 跟 ElastiCache Serverless 的定位差異&lt;/li>
&lt;li>判斷哪些 cache 場景適合 serverless、哪些該回 node-based&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑用-sdk-連-momento">最短路徑：用 SDK 連 Momento&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl"># 1. 在 Momento Console 建 cache + 取得 API key（無 node / cluster 配置）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"># 2. 用語言 SDK（以 pseudo-code 示意、實際 API 以官方 SDK 文件為準）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">client = CacheClient(api_key, default_ttl=60s)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">client.set(&amp;#34;my-cache&amp;#34;, &amp;#34;foo&amp;#34;, &amp;#34;bar&amp;#34;) # 寫入、TTL 內有效
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">client.get(&amp;#34;my-cache&amp;#34;, &amp;#34;foo&amp;#34;) # → &amp;#34;bar&amp;#34;&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>最短路徑的重點是「沒有 endpoint / node / sizing 要配」——建 cache 是一個 API 動作、不是 provision 一台機器。實際 SDK 介面以 &lt;a href="https://docs.momentohq.com/">Momento SDK 文件&lt;/a> 為準。&lt;/p>
&lt;h2 id="日常操作與決策形狀">日常操作與決策形狀&lt;/h2>
&lt;h3 id="sdk-與相容介面">SDK 與相容介面&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>原生 SDK（多語言）：gRPC-based、Momento 自有 API&lt;/li>
&lt;li>Redis / Memcached 相容介面：既有 Redis / Memcached client 可遷（相容範圍以官方為準、要驗證）&lt;/li>
&lt;li>沒有 redis-cli 等價的 server 操作（serverless 無 server 可登入）&lt;/li>
&lt;/ul>
&lt;h3 id="計費模型核心決策">計費模型（核心決策）&lt;/h3>
&lt;p>子議題：&lt;/p></description><content:encoded><![CDATA[<p>Momento 是 serverless cache 服務、承擔三個責任：把 cache 變成一個按用量計費的 API（沒有 node、沒有 cluster、不規劃容量）、自動隨流量 scale（尖峰自動擴、閒置不付固定費）、提供原生 SDK 與 Redis / Memcached 相容介面（既有 client 可遷）。設計取捨偏向「把 cache 的容量規劃與維運完全消除、用計費換掉 sizing」、是不想養 cache 叢集又要彈性的選項。</p>
<p>對「流量不可預測、不想規劃容量與 sizing、團隊沒有 cache 運維資源」這條路徑、Momento 是 serverless 方向的代表。它跟自管 Redis、managed cache 的上層取捨（自管 vs managed vs serverless vs BaaS bundle）見 <a href="/blog/backend/00-service-selection/capability-buy-vs-build/" data-link-title="0.22 能力級買 vs 建：feature-as-a-service 與 BaaS bundle 選型" data-link-desc="在交付形態決定整個系統要不要自建之後、逐能力判斷該外包還是自建：辨識 managed 基礎設施、feature SaaS 與 BaaS bundle 三種外包深度、no-code 到 dev-tool 的服務光譜、買 vs 建判準與權重浮動、整合接縫與遷出代價">0.22 能力級買 vs 建</a>。</p>
<blockquote>
<p>本頁的計費、limit 與功能宣稱以 <a href="https://docs.momentohq.com/">Momento 官方文件</a> 與 <a href="https://www.gomomento.com/pricing/">Momento 定價</a> 為準、最後檢查日 2026-06-16。Momento 是 SaaS、需帳號與 API key、無法本機 docker 驗證、指令為依官方文件的範例。</p></blockquote>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>理解 serverless cache 跟 node-based / managed cache 的計費與維運差異</li>
<li>評估按用量計費（per request + data transfer）對你的流量形狀划不划算</li>
<li>判斷 Momento 原生 SDK vs Redis 相容介面的遷移路徑</li>
<li>區分 Momento 跟 ElastiCache Serverless 的定位差異</li>
<li>判斷哪些 cache 場景適合 serverless、哪些該回 node-based</li>
</ol>
<h2 id="最短路徑用-sdk-連-momento">最短路徑：用 SDK 連 Momento</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl"># 1. 在 Momento Console 建 cache + 取得 API key（無 node / cluster 配置）
</span></span><span class="line"><span class="ln">2</span><span class="cl"># 2. 用語言 SDK（以 pseudo-code 示意、實際 API 以官方 SDK 文件為準）
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl">client = CacheClient(api_key, default_ttl=60s)
</span></span><span class="line"><span class="ln">5</span><span class="cl">client.set(&#34;my-cache&#34;, &#34;foo&#34;, &#34;bar&#34;)     # 寫入、TTL 內有效
</span></span><span class="line"><span class="ln">6</span><span class="cl">client.get(&#34;my-cache&#34;, &#34;foo&#34;)            # → &#34;bar&#34;</span></span></code></pre></div><p>最短路徑的重點是「沒有 endpoint / node / sizing 要配」——建 cache 是一個 API 動作、不是 provision 一台機器。實際 SDK 介面以 <a href="https://docs.momentohq.com/">Momento SDK 文件</a> 為準。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="sdk-與相容介面">SDK 與相容介面</h3>
<p>子議題：</p>
<ul>
<li>原生 SDK（多語言）：gRPC-based、Momento 自有 API</li>
<li>Redis / Memcached 相容介面：既有 Redis / Memcached client 可遷（相容範圍以官方為準、要驗證）</li>
<li>沒有 redis-cli 等價的 server 操作（serverless 無 server 可登入）</li>
</ul>
<h3 id="計費模型核心決策">計費模型（核心決策）</h3>
<p>子議題：</p>
<ul>
<li>按用量計費：data transfer（傳輸量）+ 可能的 request / storage 維度（以官方定價為準）</li>
<li>無固定 node 費用：閒置時段不付 idle node 的錢</li>
<li>流量尖峰自動 scale：不需預留容量、但尖峰量直接反映在帳單</li>
</ul>
<h3 id="沒有容量規劃">沒有容量規劃</h3>
<p>子議題：</p>
<ul>
<li>不選 node type、不設 maxmemory、不規劃 shard</li>
<li>scaling 由 Momento 處理、application 端不感知</li>
<li>代價：失去對底層的控制（無法調 eviction policy 等 server 參數）</li>
</ul>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<h3 id="serverless-計費的甜蜜點與陷阱">Serverless 計費的甜蜜點與陷阱</h3>
<p>子議題：</p>
<ul>
<li>甜蜜點：流量不可預測、有大量閒置時段、不想為峰值預留容量</li>
<li>陷阱：穩態高流量下、按用量可能比 node-based + Reserved Instance 貴</li>
<li>跟 <a href="/blog/backend/02-cache-redis/vendors/aws-elasticache/managed-responsibility-boundary/" data-link-title="AWS ElastiCache 的責任邊界：managed 接手了什麼、又默默留下什麼" data-link-desc="ElastiCache 把 failover、patching、snapshot、跨 AZ 複製接走，但 cache stampede、client 重連、key 設計、eviction policy 還是你的事。本文用 shared responsibility 拆解 managed 的真實邊界、展開 engine 選擇與 cluster mode 配置、5 個把『以為 AWS 全包』寫成事故的 production 踩坑，以及 ElastiCache 到 MemoryDB 的 durability 邊界">ElastiCache Serverless 的計費踩坑</a> 同類議題、access pattern 低效會推高帳單</li>
</ul>
<h3 id="momento-vs-elasticache-serverless">Momento vs ElastiCache Serverless</h3>
<p>子議題：</p>
<ul>
<li>Momento：cache-as-API、完全 serverless、跨雲（不綁單一 cloud）</li>
<li>ElastiCache Serverless：AWS 生態內的 node 抽象、仍是 ElastiCache engine、綁 AWS</li>
<li>選擇：要完全擺脫容量規劃 + 跨雲 → Momento；已在 AWS 生態 + 要 engine 控制 → ElastiCache</li>
</ul>
<h3 id="遷移與相容性驗證">遷移與相容性驗證</h3>
<p>子議題：</p>
<ul>
<li>從 Redis / Memcached 遷 Momento：用相容介面或改用原生 SDK</li>
<li>相容範圍要逐項驗證（serverless 不支援 server-side 操作如 SCAN 全庫、Lua 等、以官方為準）</li>
<li>失去的能力：server 參數調校、自管 persistence、module</li>
</ul>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<h3 id="帳單超出預期">帳單超出預期</h3>
<p>操作原則：serverless 帳單反映實際用量、先看 data transfer 與 request 量。判讀：access pattern 低效（大量小請求、大 value）會推高、用批次 / 合併降量；穩態高流量重新評估 node-based。</p>
<h3 id="延遲比自管高">延遲比自管高</h3>
<p>操作原則：serverless cache 多一層 API gateway / 跨網路、延遲可能高於同 VPC 的自管 Redis。判讀：latency-sensitive 且穩態高流量的場景、評估自管或 managed node-based。</p>
<h3 id="相容介面行為差異">相容介面行為差異</h3>
<p>操作原則：Redis 相容介面不等於 100% Redis、server-side 操作可能不支援。判讀：對照官方相容清單、用到的命令逐一驗證。</p>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>穩態高流量、成本敏感</td>
          <td>node-based <a href="/blog/backend/02-cache-redis/vendors/redis/" data-link-title="Redis" data-link-desc="OSS in-memory data structure store、cache 主流">Redis / Valkey</a> + Reserved Instance</td>
      </tr>
      <tr>
          <td>需要 server 參數 / eviction 控制</td>
          <td>自管 Redis / <a href="/blog/backend/02-cache-redis/vendors/aws-elasticache/" data-link-title="AWS ElastiCache" data-link-desc="AWS managed Redis / Valkey / Memcached">ElastiCache</a></td>
      </tr>
      <tr>
          <td>已在 AWS 生態</td>
          <td><a href="/blog/backend/02-cache-redis/vendors/aws-elasticache/" data-link-title="AWS ElastiCache" data-link-desc="AWS managed Redis / Valkey / Memcached">ElastiCache Serverless</a>（同生態）</td>
      </tr>
      <tr>
          <td>需要 Redis data types / module</td>
          <td><a href="/blog/backend/02-cache-redis/vendors/redis/" data-link-title="Redis" data-link-desc="OSS in-memory data structure store、cache 主流">Redis</a>（完整 data types）</td>
      </tr>
      <tr>
          <td>process-local 極低延遲</td>
          <td><a href="/blog/backend/02-cache-redis/vendors/caffeine/" data-link-title="Caffeine" data-link-desc="JVM process-local cache、Window TinyLFU、Guava Cache 後繼">Caffeine</a>（JVM 內、無網路）</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Momento 完整 SDK API（各語言、以官方文件為準）</li>
<li>詳細計費計算（以官方定價為準）</li>
<li>Redis / Memcached 相容介面的完整相容矩陣</li>
<li>Momento Topics（pub/sub）等 cache 以外的產品線</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<h3 id="跨-vendor-對照本模組-case-庫暫無-momento-specific-case">跨 vendor 對照（本模組 case 庫暫無 Momento-specific case）</h3>
<p>Momento 是較新的 serverless cache、本 blog 的 cache case 庫（Meta / Shopify / Netflix / Cloudflare / Tinder / Tubi / Snap）暫無 Momento production case。以下用 serverless 的角度對照既有 case 提供判讀。</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>對 Momento 的對應</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/failure-cache-stampede-rollout-regression/" data-link-title="2.C9 反例：快取切換引發 Stampede 回歸" data-link-desc="快取策略切換若缺乏保護，會導致回源壓力與錯誤率連鎖上升。">2.C9 Cache Stampede</a></td>
          <td>serverless 也會 stampede、client-side jitter / singleflight 仍要自己做</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/cases/tubi-elasticache-ml-feature-store/" data-link-title="9.C25 Tubi：從 ScyllaDB 遷到 ElastiCache、ML feature store 達 sub-10ms p99" data-link-desc="Tubi 把 ML 推薦的 feature store 從 ScyllaDB 遷到 ElastiCache for Redis、99 百分位延遲降到 10ms 以下">9.C25 Tubi feature store</a></td>
          <td>「feature 可重算才選 cache」的判斷對 serverless 一樣適用、不可重建走 durable</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/contrast-cache-strategy-by-scale/" data-link-title="2.C10 對照：規模差異下的快取策略" data-link-desc="同一快取策略在小中大型服務下會產生不同風險。">2.C10 規模對照</a></td>
          <td>serverless 適合早期 / 不可預測流量、規模穩定後評估 node-based 成本</td>
      </tr>
  </tbody>
</table>
<p><strong>待補 Momento-specific 案例</strong>：serverless cache 的成本與彈性 production 個案、從 ElastiCache 遷 Momento 的成本對照、不可預測流量場景的採用分享。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游能力：<a href="/blog/backend/00-service-selection/capability-buy-vs-build/" data-link-title="0.22 能力級買 vs 建：feature-as-a-service 與 BaaS bundle 選型" data-link-desc="在交付形態決定整個系統要不要自建之後、逐能力判斷該外包還是自建：辨識 managed 基礎設施、feature SaaS 與 BaaS bundle 三種外包深度、no-code 到 dev-tool 的服務光譜、買 vs 建判準與權重浮動、整合接縫與遷出代價">0.22 能力級買 vs 建</a>（自管 vs managed vs serverless）、<a href="/blog/backend/00-service-selection/cost-risk-tradeoffs/" data-link-title="0.6 成本、風險與選型取捨" data-link-desc="用人力成本、雲端成本、操作成本與失敗代價判斷後端能力投入順序">0.6 成本取捨</a></li>
<li>平行 vendor：<a href="/blog/backend/02-cache-redis/vendors/aws-elasticache/" data-link-title="AWS ElastiCache" data-link-desc="AWS managed Redis / Valkey / Memcached">AWS ElastiCache</a>（Serverless 選項）、<a href="/blog/backend/02-cache-redis/vendors/caffeine/" data-link-title="Caffeine" data-link-desc="JVM process-local cache、Window TinyLFU、Guava Cache 後繼">Caffeine</a>（另一端：process-local）</li>
<li>上游概念：<a href="/blog/backend/02-cache-redis/cache-aside/" data-link-title="2.2 cache aside 與失效策略" data-link-desc="整理 read-through 思路、cache miss 與 invalidation">2.2 Cache Aside</a></li>
</ul>
]]></content:encoded></item><item><title>AWS CloudHSM</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/cloudhsm/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/cloudhsm/</guid><description>&lt;p>AWS CloudHSM 是 &lt;em>single-tenant dedicated HSM&lt;/em> 服務（FIPS 140-2 Level 3）、客戶獨享一個 HSM cluster、AWS 提供 &lt;em>硬體 + network + provisioning&lt;/em>、客戶自己管 &lt;em>crypto user / partition / key custody / backup&lt;/em>。它跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-kms/" data-link-title="AWS KMS" data-link-desc="AWS 原生 key management service、envelope encryption / digital signing / Multi-Region Key、Key Policy &amp;#43; Grant 雙軌授權">AWS KMS&lt;/a> 是 &lt;em>不同信任模型&lt;/em> — KMS 是 multi-tenant managed、AWS 持有 key custody 與 API plane；CloudHSM 上 &lt;em>AWS 看不到 key、也不能 reset Crypto User password&lt;/em>、客戶丟了 credential 等於 key 永久遺失。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>CloudHSM 的核心定位是 &lt;em>把 cryptographic root of trust 放回客戶手上&lt;/em> — 適合金融、政府、醫療這類有資料主權、FIPS 140-2 Level 3、PCI HSM、HIPAA 合規壓力的場景。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-kms/" data-link-title="AWS KMS" data-link-desc="AWS 原生 key management service、envelope encryption / digital signing / Multi-Region Key、Key Policy &amp;#43; Grant 雙軌授權">AWS KMS&lt;/a> 比、KMS 也滿足 FIPS 140-2 Level 3、但 &lt;em>HSM cluster 是 AWS 多租戶共用&lt;/em>、key material 由 AWS-controlled HSM 持有、控制面 API 也是 AWS。CloudHSM 把 HSM cluster 物理隔離給單一客戶、PKCS#11 / JCE / OpenSSL Dynamic Engine 直接打 HSM、AWS 在資料平面 &lt;em>沒有讀 key 的能力&lt;/em>。&lt;/p>
&lt;p>跟 &lt;em>自管 on-prem HSM&lt;/em>（SafeNet / Thales 自架）比、CloudHSM 把硬體採購、機房、network、firmware patch 交還 AWS、客戶只管 key custody 跟 Crypto User policy；代價是不能完全脫離 AWS region。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault auto-unseal&lt;/a> 整合場景中、CloudHSM 是 &lt;em>Vault master key 的 root custodian&lt;/em> — Vault unseal key 用 CloudHSM 加密、CloudHSM 出事整個 Vault cluster 沒法 unseal、所以可用性設計（cross-AZ cluster、cross-region backup）很關鍵。多數一般 web app / SaaS 用 KMS 即可、不需要 CloudHSM 的物理隔離。&lt;/p></description><content:encoded><![CDATA[<p>AWS CloudHSM 是 <em>single-tenant dedicated HSM</em> 服務（FIPS 140-2 Level 3）、客戶獨享一個 HSM cluster、AWS 提供 <em>硬體 + network + provisioning</em>、客戶自己管 <em>crypto user / partition / key custody / backup</em>。它跟 <a href="/blog/backend/07-security-data-protection/vendors/aws-kms/" data-link-title="AWS KMS" data-link-desc="AWS 原生 key management service、envelope encryption / digital signing / Multi-Region Key、Key Policy &#43; Grant 雙軌授權">AWS KMS</a> 是 <em>不同信任模型</em> — KMS 是 multi-tenant managed、AWS 持有 key custody 與 API plane；CloudHSM 上 <em>AWS 看不到 key、也不能 reset Crypto User password</em>、客戶丟了 credential 等於 key 永久遺失。</p>
<h2 id="服務定位">服務定位</h2>
<p>CloudHSM 的核心定位是 <em>把 cryptographic root of trust 放回客戶手上</em> — 適合金融、政府、醫療這類有資料主權、FIPS 140-2 Level 3、PCI HSM、HIPAA 合規壓力的場景。跟 <a href="/blog/backend/07-security-data-protection/vendors/aws-kms/" data-link-title="AWS KMS" data-link-desc="AWS 原生 key management service、envelope encryption / digital signing / Multi-Region Key、Key Policy &#43; Grant 雙軌授權">AWS KMS</a> 比、KMS 也滿足 FIPS 140-2 Level 3、但 <em>HSM cluster 是 AWS 多租戶共用</em>、key material 由 AWS-controlled HSM 持有、控制面 API 也是 AWS。CloudHSM 把 HSM cluster 物理隔離給單一客戶、PKCS#11 / JCE / OpenSSL Dynamic Engine 直接打 HSM、AWS 在資料平面 <em>沒有讀 key 的能力</em>。</p>
<p>跟 <em>自管 on-prem HSM</em>（SafeNet / Thales 自架）比、CloudHSM 把硬體採購、機房、network、firmware patch 交還 AWS、客戶只管 key custody 跟 Crypto User policy；代價是不能完全脫離 AWS region。跟 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault auto-unseal</a> 整合場景中、CloudHSM 是 <em>Vault master key 的 root custodian</em> — Vault unseal key 用 CloudHSM 加密、CloudHSM 出事整個 Vault cluster 沒法 unseal、所以可用性設計（cross-AZ cluster、cross-region backup）很關鍵。多數一般 web app / SaaS 用 KMS 即可、不需要 CloudHSM 的物理隔離。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>何時需要 CloudHSM 的 dedicated 模型、何時 <a href="/blog/backend/07-security-data-protection/vendors/aws-kms/" data-link-title="AWS KMS" data-link-desc="AWS 原生 key management service、envelope encryption / digital signing / Multi-Region Key、Key Policy &#43; Grant 雙軌授權">AWS KMS</a> 已足夠</li>
<li>CloudHSM cluster 的最低安全 / 可用性需求（cross-AZ、Crypto Officer 分離、Quorum、backup）</li>
<li>Crypto User credential 出事的降級路徑（AWS 不能幫忙、靠 backup + Quorum）</li>
<li>跟 <a href="https://docs.aws.amazon.com/kms/latest/developerguide/custom-key-store-overview.html">KMS Custom Key Store</a> / <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault auto-unseal</a> 整合的取捨</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 CloudHSM deployment 是否健康、最少看四件事：</p>
<ul>
<li><strong>Cluster 拓樸</strong>：production cluster 是否至少 2 個 HSM instance 跨 AZ、cluster 內自動 replicate、單一 AZ 故障時 key 是否仍可用</li>
<li><strong>Crypto User 管理</strong>：Crypto Officer（CO）跟 Crypto User（CU）是否分離、CO password 是否走 break-glass 保管、CU credential 是否走 short-lived 取得 + audit</li>
<li><strong>Quorum-based policy</strong>：高敏 operation（建 CU、改 policy、key export wrapped）是否設 M-of-N approval、避免單一 admin compromise 後 silent abuse</li>
<li><strong>Backup 治理</strong>：automatic 24h backup 跟 manual backup 是否都開、cross-region backup 是否走 explicit copy、restore 流程是否定期演練</li>
</ul>
<p>四件事任一缺失、就是 CloudHSM deployment 待補項目 — 跟 <a href="/blog/backend/knowledge-cards/secret-management/" data-link-title="Secret Management" data-link-desc="說明 token、key、password 與憑證如何保存、輪替與撤銷">secret management</a> 的 evidence 邊界同類。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>Cluster + HSM Instance 拓樸</strong>：CloudHSM 的部署單位是 <em>cluster</em>、cluster 內可以有 1-N 個 <em>HSM instance</em>。production 場景至少 2 個 HSM instance 跨 AZ、cluster 自動把 key material replicate 在所有 instance 上、單一 AZ 失效不影響 cryptographic operation。跨 region 不自動 replicate — 跨 region DR 要靠 backup copy。</p>
<p><strong>Crypto Officer (CO) vs Crypto User (CU)</strong>：CO 是 cluster 管理員、能建 / 刪 CU、設 policy、做 backup；CU 是真的做 cryptographic operation 的 identity（encrypt / decrypt / sign / verify）。production 必須分離 — CO credential 走 break-glass 保管、CU credential 給 application 使用、application compromise 只影響 CU 邊界、不能改 CO policy。</p>
<p><strong>Quorum-based policy（M-of-N approval）</strong>：CloudHSM 支援把高敏操作（建 CU、改 policy、key export wrapped）綁定 <em>M-of-N CO approval</em>。例如 3-of-5 quorum、單一 CO 即使 credential 外洩也不能單獨建後門 CU、必須拿到另外 2 個 CO 的 signed token。對應 <a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/microsoft-storm-0558-2023-signing-key-chain/" data-link-title="7.R7.1.5 Microsoft Storm-0558 2023：簽章金鑰鏈與郵件存取" data-link-desc="從簽章金鑰保護失效到雲端郵件存取，拆解身分信任鏈的關鍵控制點">Storm-0558 signing key chain</a> 啟示：高價值 key custodian 的 admin operation 不該是 <em>單人單 token</em>、必須有第二人簽核才能改變信任根。</p>
<p><strong>Backup 治理</strong>：CloudHSM 每 24 小時自動 backup 整個 cluster state（含 key material）、backup 是 AWS-managed encrypted blob、AWS 自己也不能解密、restore 必須在 CloudHSM cluster context 內進行。可手動 backup、可 copy 到其他 region 做 DR。Backup retention 預設 90 天、可延長。Backup 不是 <em>export</em> — 不能把 key material 從 HSM 拿出來看 plaintext。</p>
<p><strong>Key Replication 跨 region</strong>：CloudHSM cluster 綁定單一 AWS region、跨 region 走 <em>backup → copy → restore</em> 流程、不是 active replication。設計 DR 時要算 RTO：restore 一個 cluster 從 backup 大約小時級、不適合 hot failover、應該 <em>primary region 跑、DR region 備好空 cluster + backup copy</em>。</p>
<p><strong>PKCS#11 / JCE / OpenSSL Dynamic Engine 整合</strong>：application 不用 AWS SDK 講 CloudHSM、而是透過 <em>標準 cryptographic API library</em>（PKCS#11 for C/C++、JCE Provider for Java、OpenSSL Dynamic Engine 走 TLS termination）。好處是 <em>application code 用業界標準介面</em>、未來換 HSM 廠也只需要換 library。代價是 client SDK 要裝在 application host、CU credential 要 deploy 到 host、host security baseline 變成 cryptographic boundary 的一部分。</p>
<p><strong>跟 KMS Custom Key Store 整合</strong>：<a href="https://docs.aws.amazon.com/kms/latest/developerguide/custom-key-store-overview.html">KMS Custom Key Store</a> 把 KMS Key 的 <em>backing material 放在 CloudHSM</em>、API 仍透過 KMS（<code>kms:Encrypt</code> / <code>kms:Decrypt</code>）、application code 不需要改。這是 <em>KMS 易用 + HSM dedicated 雙重</em>：保留 KMS 的 IAM policy / key rotation / audit log（CloudTrail）、又得到 single-tenant HSM 的合規屬性。代價是 CloudHSM 失效時、Custom Key Store backing 的 KMS Key 全部不可用、需要監控 cluster health。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>AWS CloudHSM</th>
          <th>AWS KMS</th>
          <th>Azure Managed HSM</th>
          <th>Google Cloud HSM</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>部署模型</td>
          <td>Single-tenant dedicated cluster</td>
          <td>Multi-tenant managed</td>
          <td>Single-tenant pool</td>
          <td>HSM-backed Cloud KMS（Protection Level=HSM）</td>
      </tr>
      <tr>
          <td>FIPS 140-2</td>
          <td>Level 3（dedicated）</td>
          <td>Level 3（shared cluster）</td>
          <td>Level 3</td>
          <td>Level 3</td>
      </tr>
      <tr>
          <td>AWS / 雲廠持 key？</td>
          <td>不持（CU credential 客戶獨有）</td>
          <td>持（managed key custody）</td>
          <td>不持（HSM admin 客戶獨有）</td>
          <td>不持 plaintext key material</td>
      </tr>
      <tr>
          <td>整合介面</td>
          <td>PKCS#11 / JCE / OpenSSL</td>
          <td>AWS SDK / CLI / KMS API</td>
          <td>Key Vault SDK / REST</td>
          <td>Cloud KMS API</td>
      </tr>
      <tr>
          <td>Quorum 多人簽核</td>
          <td>內建（M-of-N）</td>
          <td>透過 IAM policy + organization SCP</td>
          <td>RBAC + Privileged Identity Management</td>
          <td>IAM Condition + organization policy</td>
      </tr>
      <tr>
          <td>運維成本</td>
          <td>高 — 自管 CU credential / patch / topology</td>
          <td>低</td>
          <td>中</td>
          <td>低</td>
      </tr>
      <tr>
          <td>合規憑證</td>
          <td>FIPS 140-2 L3 + PCI HSM + Common Criteria</td>
          <td>FIPS 140-2 L3 + PCI DSS</td>
          <td>FIPS 140-2 L3 + Common Criteria</td>
          <td>FIPS 140-2 L3</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>金融 / 政府 / 醫療、需要物理隔離 + AWS 不持 key</td>
          <td>一般 AWS-heavy workload、需要 IAM 整合</td>
          <td>Azure-heavy + 合規壓力</td>
          <td>GCP-heavy + 合規壓力</td>
      </tr>
      <tr>
          <td>退場成本</td>
          <td>中 — backup 跨廠不可移植、key 不能 export</td>
          <td>中</td>
          <td>中</td>
          <td>中</td>
      </tr>
  </tbody>
</table>
<p>選 CloudHSM 的核心訴求：<em>合規明文要求 dedicated HSM</em>（PCI HSM、某些國家資料主權法規）、或 <em>trust model 上不接受 AWS 持 key</em>。多數 AWS-heavy workload 用 KMS 即可、加 CloudHSM 反而引入 <em>Crypto User credential 的單點失誤</em>（丟了 = key 永久遺失）。需要 KMS API 但又要 dedicated HSM、走 <a href="https://docs.aws.amazon.com/kms/latest/developerguide/custom-key-store-overview.html">Custom Key Store</a> 是折衷路徑。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Quorum Auth 設計</strong>：production 把 Quorum threshold 設為 <em>3-of-5</em> 或 <em>2-of-3</em>、五位 CO 由不同部門 / 不同地理位置持有、避免單一辦公室 / 單一網路同時被攻陷。Quorum token 有 TTL、單次 operation 用完就失效、防止 replay。建議 quarterly 演練：模擬一個 CO 不在、用剩餘 quorum 完成 emergency operation、驗證流程在事故時跑得通。</p>
<p><strong>KMS Custom Key Store 整合決策</strong>：用 Custom Key Store 的關鍵問題是 <em>availability blast radius</em> — KMS Key 出事影響範圍是 <em>使用該 Key 的 AWS service</em>（S3、EBS、RDS encryption）、Custom Key Store backing 失效會讓這些 service 同步斷。設計時做 <em>分層 key strategy</em>：mass volume 的 S3 / EBS 用 AWS-managed KMS Key、高合規敏感的 database / secret 才用 Custom Key Store backing 的 KMS Key、降低單一 cluster 失效的影響面。</p>
<p><strong>Cross-Region Backup</strong>：DR 要把 backup copy 到第二個 region、走 <code>CopyBackupToRegion</code> API、restore 時建空 cluster + 套 backup。整個 RTO 通常數小時、不適合熱備、設計上是 <em>容忍小時級 outage 換到 BCDR 環境</em>、不是 <em>秒級 failover</em>。對應 <a href="/blog/backend/07-security-data-protection/cases/azure-ad-identity-control-plane-2021/" data-link-title="7.C3 Azure AD：2021 Identity Control-plane 事件" data-link-desc="身分控制面事件如何影響多服務信任鏈與回復優先序。">Azure AD Identity Control Plane 2021</a> 對照啟示：身份 / 加密控制面的單點 outage 影響整個 platform、availability 的 topology 設計跟 confidentiality 同等重要。</p>
<p><strong>跟 Vault auto-unseal 整合</strong>：<a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a> auto-unseal 可用 CloudHSM 作 master key custodian、走 PKCS#11 plugin、Vault unseal 時呼叫 CloudHSM <code>Unwrap</code> master key。比起 <a href="/blog/backend/07-security-data-protection/vendors/aws-kms/" data-link-title="AWS KMS" data-link-desc="AWS 原生 key management service、envelope encryption / digital signing / Multi-Region Key、Key Policy &#43; Grant 雙軌授權">AWS KMS auto-unseal</a> 多一層 dedicated HSM 保證、適合監管特別嚴的場景。代價是 CloudHSM cluster 失效 → Vault 不能 unseal → 下游所有 secret 拿不到、要設計 break-glass 流程。</p>
<p><strong>合規憑證</strong>：CloudHSM 同時持有 FIPS 140-2 Level 3、PCI HSM、Common Criteria EAL4+ 多個認證、可作金融 PIN block 處理、payment 業者的 HSM 上鏈、政府機敏資料加密的 <em>直接合規承諾</em>、不需要客戶端再做 HSM 認證 audit。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Crypto User credential 丟失</strong>：CU password 全公司只有一份、保管人離職 → AWS <em>不能 reset</em>、key material 永久不可用 — CU credential 要走 password manager + 多人持有、CO 有能力 revoke 舊 CU 建新 CU</li>
<li><strong>Cluster 只有單一 HSM instance</strong>：成本省了、單一 instance 故障 cluster 整個失效 — production 強制至少 2 個 instance、跨 AZ</li>
<li><strong>Backup 沒測過 restore</strong>：每天 automatic backup 跑、從未 restore 演練、DR 真要用時發現流程不通 — quarterly 演練 restore 到測試 cluster、驗證 key material 可用</li>
<li><strong>Custom Key Store 沒監控 CloudHSM health</strong>：CloudHSM cluster degraded 時、KMS Custom Key Store 跟著失效、application 看到 KMS 5xx — CloudWatch metric 監 <code>HsmsActive</code> / <code>HsmTemperature</code>、cluster health degrade 立即 alert</li>
<li><strong>PKCS#11 library 版本漂移</strong>：application host 的 client SDK 版本跟 cluster firmware 不相容、cryptographic operation 失敗 — version compatibility matrix 進 deployment pipeline、firmware upgrade 前先測 staging</li>
<li><strong>Quorum CO 全部同地點</strong>：5 個 CO 全在同一個辦公室、辦公室斷網 = quorum 不能組 — CO 跨 region / 跨組織分散</li>
<li><strong>Audit log 沒接 SIEM</strong>：CloudHSM activity 透過 CloudTrail + cluster audit log、沒接 SIEM 就無 forensic — CloudTrail 跟 cluster audit 都 push 到 SIEM（見 <a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">7.13 偵測覆蓋率與訊號治理</a>）</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>一般 AWS workload 加密、無 dedicated 合規</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/aws-kms/" data-link-title="AWS KMS" data-link-desc="AWS 原生 key management service、envelope encryption / digital signing / Multi-Region Key、Key Policy &#43; Grant 雙軌授權">AWS KMS</a></td>
      </tr>
      <tr>
          <td>Azure-heavy + dedicated HSM 合規需求</td>
          <td>Azure Managed HSM（見上方對照表）</td>
      </tr>
      <tr>
          <td>GCP-heavy + dedicated HSM 合規需求</td>
          <td>Google Cloud HSM（Cloud KMS Protection Level=HSM）</td>
      </tr>
      <tr>
          <td>Secret storage + dynamic credential</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a> / <a href="/blog/backend/07-security-data-protection/vendors/aws-secrets-manager/" data-link-title="AWS Secrets Manager" data-link-desc="AWS 原生 secret store &#43; 內建 RDS / Redshift rotation Lambda、Resource Policy 跨帳號共享、KMS 加密">AWS Secrets Manager</a></td>
      </tr>
      <tr>
          <td>Certificate / PKI（不是 key custody）</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/aws-acm/" data-link-title="AWS ACM" data-link-desc="AWS-managed certificate provisioning、DNS validation &#43; auto-renewal、整合 ELB / CloudFront / API Gateway、Private CA 後端">AWS ACM</a> / <a href="/blog/backend/07-security-data-protection/vendors/cert-manager/" data-link-title="cert-manager" data-link-desc="K8s 原生 certificate lifecycle automation、支援 Let&#39;s Encrypt / Vault PKI / Venafi 等多 issuer、auto-renewal &#43; Challenge solver">cert-manager</a></td>
      </tr>
      <tr>
          <td>跨雲 unified key custody</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a> transit engine（雲廠中立）</td>
      </tr>
      <tr>
          <td>Key rotation 證據鏈</td>
          <td><a href="/blog/backend/07-security-data-protection/credential-rotation-scoped-evidence/" data-link-title="7.27 Credential Rotation with Scoped Evidence 實作示範" data-link-desc="以 webhook/API credential 輪替示範 scope map、證據欄位與回退窗口如何一起設計。">7.5 Credential Rotation Scoped Evidence</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>CloudHSM 完整 PKCS#11 / JCE API reference</li>
<li>CloudHSM Classic（舊版、已 EOL）的差異</li>
<li>每種合規法規（PCI HSM、HIPAA、FedRAMP）的逐條對應</li>
<li>CloudHSM CLI 跟 <code>cloudhsm_mgmt_util</code> 詳細指令</li>
<li>應用層使用 HSM-bound key 做 TLS termination 的 nginx / Apache 配置細節</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>CloudHSM 在 07 案例庫沒有直接 vendor-level 事件、以下案例採對照引用：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 CloudHSM 的關係（對照）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/microsoft-storm-0558-2023-signing-key-chain/" data-link-title="7.R7.1.5 Microsoft Storm-0558 2023：簽章金鑰鏈與郵件存取" data-link-desc="從簽章金鑰保護失效到雲端郵件存取，拆解身分信任鏈的關鍵控制點">Microsoft Storm-0558 Signing Key Chain</a></td>
          <td>核心對照 — CloudHSM 設計 <em>AWS 不持 key + key 不能 export</em> 是 Storm-0558 反設計、攻擊者進 cluster 也搬不走 key material、Quorum policy 阻單一 admin compromise</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/cases/failure-credential-rotation-without-scope/" data-link-title="7.C9 反例：憑證輪替未分 Scope" data-link-desc="憑證輪替若未分域分批，容易造成跨系統連鎖中斷。">Failure: Credential Rotation Without Scope</a></td>
          <td>CloudHSM key rotation 需要應用層配合 key alias 切換、不像 KMS 自動 rotation；scope map 跟雙軌驗證窗口更明顯、PKCS#11 client 散落 host 群時 rotation 要分批</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/cases/azure-ad-identity-control-plane-2021/" data-link-title="7.C3 Azure AD：2021 Identity Control-plane 事件" data-link-desc="身分控制面事件如何影響多服務信任鏈與回復優先序。">Azure AD Identity Control Plane 2021</a></td>
          <td>對照啟示 — HSM cluster 是 single point of compromise、cross-AZ topology + cross-region backup 是 <em>availability</em> 的設計依據、不是 confidentiality</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/secrets-and-machine-credential-governance/" data-link-title="7.6 秘密管理與機器憑證治理" data-link-desc="以問題驅動方式整理 secret、token、key 與機器身份治理">7.6 秘密管理與機器憑證治理</a>、<a href="/blog/backend/07-security-data-protection/transport-trust-and-certificate-lifecycle/" data-link-title="7.5 傳輸信任與憑證生命週期" data-link-desc="以問題驅動方式整理傳輸信任鏈、會話完整性與憑證節奏">7.5 傳輸信任與憑證生命週期</a>（HSM 為 CA / signing key 的 FIPS-grade root custodian）、<a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">7.13 偵測覆蓋率與訊號治理</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/aws-kms/" data-link-title="AWS KMS" data-link-desc="AWS 原生 key management service、envelope encryption / digital signing / Multi-Region Key、Key Policy &#43; Grant 雙軌授權">AWS KMS</a>、<a href="/blog/backend/07-security-data-protection/vendors/google-cloud-kms/" data-link-title="Google Cloud KMS" data-link-desc="GCP 原生 key management service、KeyRing / CryptoKey Version 設計、CMEK 整合 &#43; Cloud HSM &#43; External Key Manager">Google Cloud KMS</a>、<a href="/blog/backend/07-security-data-protection/vendors/azure-key-vault/" data-link-title="Azure Key Vault" data-link-desc="Azure 三合一 service（Secret &#43; Key &#43; Certificate）、整合 Managed Identity &#43; Entra ID RBAC、Premium tier 走 HSM">Azure Key Vault</a></li>
<li>整合：<a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a>（CloudHSM 作為 Vault auto-unseal master key custodian）</li>
<li>整合：<a href="https://docs.aws.amazon.com/kms/latest/developerguide/custom-key-store-overview.html">KMS Custom Key Store</a>（KMS API + CloudHSM backing 雙重）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（HSM 失效如何 routing 進 IR 流程）</li>
<li>官方：<a href="https://docs.aws.amazon.com/cloudhsm/">AWS CloudHSM Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>Azure RBAC + Entra ID</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/azure-rbac/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/azure-rbac/</guid><description>&lt;p>Azure 的身份與權限體系是 &lt;em>雙層&lt;/em> — Entra ID（前 Azure AD）是 IdP，承擔人類與 workload 的身份來源、SSO、MFA 與 Conditional Access；Azure RBAC 是 cloud resource 的 permission engine，把 role 指派到 scope（Management Group / Subscription / Resource Group / Resource）上的 principal。兩層責任不同、設定介面不同、出事故時的徵兆也不同 — 把兩者寫成同一件事是 Azure 治理最常見的混淆來源。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Entra ID 是 &lt;em>Microsoft 自有的 workforce IdP&lt;/em>、跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta&lt;/a> 是直接競爭者。M365 / Azure-heavy 的組織通常直接用 Entra ID 當主 IdP；Okta-first 的組織可以把 Entra ID 當下游 SP（federation）、也可以雙 IdP 並存、但雙 IdP 的 break-glass 跟 lifecycle 路徑要重新設計。Entra ID 同時承擔 &lt;em>consumer-side 跟 partner-side 的 multi-tenant app&lt;/em> 信任、跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/auth0/" data-link-title="Auth0" data-link-desc="B2C / B2B Customer Identity Provider、Universal Login、Action / Rule hook、屬 Okta 旗下 Customer Identity Cloud">Auth0&lt;/a> 在 B2C 場景有交集。&lt;/p>
&lt;p>Azure RBAC 是 cloud resource permission engine、跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google Cloud IAM&lt;/a> 同層 — 都在解「身份對 cloud resource 能做什麼」。差異在 &lt;em>scope hierarchy&lt;/em> — Azure 用 Management Group → Subscription → Resource Group → Resource 四層繼承、AWS 用 account + organization、Google 用 organization → folder → project。Azure RBAC 預期 &lt;em>role assignment 沿 scope 向下繼承&lt;/em>、這跟 AWS 在每個 account 重新指派的習慣不一樣、跨雲團隊轉過來常踩到。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本頁、讀者能判斷：&lt;/p>
&lt;ol>
&lt;li>哪一段控制屬於 Entra ID（身份）、哪一段屬於 Azure RBAC（resource permission）、不要把兩層當同一件事&lt;/li>
&lt;li>Entra ID tenant 的最低稽核需求（Global Admin、App Registration、Conditional Access、Managed Identity）&lt;/li>
&lt;li>Azure RBAC 的 scope 設計、Custom Role 跟 PIM 何時必要&lt;/li>
&lt;li>Entra ID 控制面事故的降級路徑、跟 Azure RBAC 出事的徵兆差異&lt;/li>
&lt;/ol>
&lt;h2 id="最短判讀路徑">最短判讀路徑&lt;/h2>
&lt;p>判斷 Azure 雙層體系是否健康、要分兩層各看兩件事、跟「日常操作與決策形狀」段的兩層結構對齊。&lt;/p></description><content:encoded><![CDATA[<p>Azure 的身份與權限體系是 <em>雙層</em> — Entra ID（前 Azure AD）是 IdP，承擔人類與 workload 的身份來源、SSO、MFA 與 Conditional Access；Azure RBAC 是 cloud resource 的 permission engine，把 role 指派到 scope（Management Group / Subscription / Resource Group / Resource）上的 principal。兩層責任不同、設定介面不同、出事故時的徵兆也不同 — 把兩者寫成同一件事是 Azure 治理最常見的混淆來源。</p>
<h2 id="服務定位">服務定位</h2>
<p>Entra ID 是 <em>Microsoft 自有的 workforce IdP</em>、跟 <a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a> 是直接競爭者。M365 / Azure-heavy 的組織通常直接用 Entra ID 當主 IdP；Okta-first 的組織可以把 Entra ID 當下游 SP（federation）、也可以雙 IdP 並存、但雙 IdP 的 break-glass 跟 lifecycle 路徑要重新設計。Entra ID 同時承擔 <em>consumer-side 跟 partner-side 的 multi-tenant app</em> 信任、跟 <a href="/blog/backend/07-security-data-protection/vendors/auth0/" data-link-title="Auth0" data-link-desc="B2C / B2B Customer Identity Provider、Universal Login、Action / Rule hook、屬 Okta 旗下 Customer Identity Cloud">Auth0</a> 在 B2C 場景有交集。</p>
<p>Azure RBAC 是 cloud resource permission engine、跟 <a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google Cloud IAM</a> 同層 — 都在解「身份對 cloud resource 能做什麼」。差異在 <em>scope hierarchy</em> — Azure 用 Management Group → Subscription → Resource Group → Resource 四層繼承、AWS 用 account + organization、Google 用 organization → folder → project。Azure RBAC 預期 <em>role assignment 沿 scope 向下繼承</em>、這跟 AWS 在每個 account 重新指派的習慣不一樣、跨雲團隊轉過來常踩到。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>哪一段控制屬於 Entra ID（身份）、哪一段屬於 Azure RBAC（resource permission）、不要把兩層當同一件事</li>
<li>Entra ID tenant 的最低稽核需求（Global Admin、App Registration、Conditional Access、Managed Identity）</li>
<li>Azure RBAC 的 scope 設計、Custom Role 跟 PIM 何時必要</li>
<li>Entra ID 控制面事故的降級路徑、跟 Azure RBAC 出事的徵兆差異</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Azure 雙層體系是否健康、要分兩層各看兩件事、跟「日常操作與決策形狀」段的兩層結構對齊。</p>
<p><strong>Entra ID 層</strong>（身份控制面）：</p>
<ul>
<li><strong>誰能做什麼</strong>：Global Admin / Privileged Role Administrator 的人數、是否走 <a href="#%e9%80%b2%e9%9a%8e%e4%b8%bb%e9%a1%8c">PIM</a> just-in-time、Conditional Access 是否強制 <a href="/blog/backend/knowledge-cards/authentication/" data-link-title="Authentication" data-link-desc="說明系統如何確認呼叫者身份">phishing-resistant 認證</a>、break-glass 帳號是否 <em>exclude</em> 自所有 CA policy 又單獨監控</li>
<li><strong>入口如何暴露</strong>：App Registration 是否限定 single-tenant、multi-tenant app 的 admin consent 流程是否經審查、Managed Identity 是否取代 service principal client secret</li>
</ul>
<p><strong>Azure RBAC 層</strong>（resource permission）：</p>
<ul>
<li><strong>誰能對 resource 做什麼</strong>：Owner / Contributor 在哪個 scope（Management Group 還是 Subscription）、production 環境是否用 Custom Role 收緊權限、有沒有 standing assignment 該改 PIM</li>
<li><strong>證據是否可回查</strong>：Entra ID Sign-in Log / Audit Log 是否同步到 SIEM、Azure Activity Log 是否設保留與 alert、admin consent / role assignment 變更是否觸發 <a href="/blog/backend/knowledge-cards/alert-runbook/" data-link-title="Alert Runbook" data-link-desc="說明告警如何連到可執行的排障與恢復流程">alert runbook</a></li>
</ul>
<p>兩層任一邊任一條缺失、就是 <a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">Audit Log</a> 與 <a href="/blog/backend/knowledge-cards/authorization/" data-link-title="Authorization" data-link-desc="說明授權如何判斷誰能對哪些資源執行哪些操作">Authorization</a> 邊界的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="entra-id-層">Entra ID 層</h3>
<p><strong>User / Group / lifecycle</strong>：HRIS 推 SCIM 進 Entra ID、Entra ID 同步到下游 SaaS 跟 Azure RBAC group。決策點是 <em>source of truth</em> — 多數組織把 HRIS 設為人員來源、Entra ID 當分發層、避免雙寫造成 stale account。</p>
<p><strong>Conditional Access 是 MFA <em>主要強制機制</em></strong>：MFA 不是設在 user 屬性上、是 Conditional Access policy 在登入時判斷 user / device / location / app / risk 後觸發。常見設定錯誤包含 <em>exclude legacy auth 沒做、break-glass 規則太寬、emergency access 帳號沒獨立監控</em>。Conditional Access 規則設計錯、就是高權限 bypass 的入口。</p>
<p><strong>App Registration vs Enterprise Application</strong>：開發者註冊 multi-tenant app 走 <em>App Registration</em>（app 的定義）、組織 admin 為某 app 設定 SAML SSO / admin consent 走 <em>Enterprise Application</em>（該 tenant 對 app 的信任）。兩者常被混講、但安全意義不同 — App Registration 是「我們做了一個 app」、Enterprise Application 是「我們信任這個 app 用我們的身份」。Consent phishing 攻擊就是針對後者。</p>
<p><strong>Managed Identity</strong>：Azure resource（VM、Function、AKS pod）自帶身份、不需要 service principal client secret、跟 <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google Workload Identity Federation</a> 同概念但 Azure-internal。System-assigned 跟 resource 生命週期綁定、resource 刪掉 identity 跟著刪；User-assigned 獨立、可跨 resource 共用。production 環境的服務存取 Key Vault / Storage 應走 Managed Identity、不該用 client secret。</p>
<p><strong>Workload Identity Federation</strong>：Entra ID 可以 <em>trust 外部 OIDC issuer</em>（GitHub Actions、AWS、Google）、讓外部 workload 直接拿 Entra ID token、不用儲存 client secret。CI/CD 的 OIDC 整合是這層的主用例、比把 client secret 塞進 CI variable 安全很多。</p>
<p><strong>Signing key 是 control plane 託管</strong>：Entra ID 不暴露 signing key、客戶沒有 rotate 它的能力。這層信任邊界一旦失守、客戶側 <em>直接修不了</em>、要等供應商發 patch 或公告 — Storm-0558 揭示了這條依賴的代價。客戶側能做的補強是 <em>下游檢查</em> 而非 <em>上游修復</em>：</p>
<ul>
<li>訂閱 Microsoft Security Advisory（MSRC）+ tenant-specific notification、讓事件公告第一時間進 IR pipeline、不要靠新聞才知道</li>
<li>SIEM alert <em>anomalous token issuance pattern</em>（跨租戶 token 在 Exchange / Graph API 出現異常存取序列）、不能只信 token signature valid</li>
<li>高敏 app 的 token validation 不只看 Entra ID 標準驗證、加 <em>issuer + tenant + audience + nonce</em> 多層比對、攻擊者偽造跨租戶 token 時可能漏掉某層</li>
<li>Conditional Access 配 <em>token protection</em>（token binding to device）、降低 stolen token replay 的命中率</li>
<li>IR playbook 預設 <em>signing key 事件</em> 一條 — 一旦供應商公告、強制 sign-out 高權限 user、token TTL 收短、回頭看 90 天 sign-in log 找異常</li>
</ul>
<h3 id="azure-rbac-層">Azure RBAC 層</h3>
<p><strong>Scope 設計</strong>：role assignment 沿 Management Group → Subscription → Resource Group → Resource 向下繼承。在 Management Group 給 Contributor、底下所有 subscription / RG / resource 都繼承 — 這既是優點（統一治理）也是風險（誤指派擴散範圍大）。設計原則是 <em>指派盡量低、不要對全 Management Group 給 Contributor</em>。</p>
<p><strong>Built-in role vs Custom Role</strong>：Owner（含 user access admin）/ Contributor（不含權限管理）/ Reader 是 built-in、通常太粗。production 環境需要 Custom Role 把 <code>Microsoft.Storage/storageAccounts/listKeys/action</code> 之類的高風險 action 收掉、只留 read。Custom Role 是 <a href="/blog/backend/knowledge-cards/authorization/" data-link-title="Authorization" data-link-desc="說明授權如何判斷誰能對哪些資源執行哪些操作">least privilege</a> 在 Azure 的落實工具、不做就是用 Contributor 當預設、權限過寬。</p>
<p><strong>Privileged Identity Management（PIM）</strong>：高權限角色（Global Admin、Subscription Owner、User Access Administrator）應走 just-in-time activation、需要 MFA 跟 approval、不該 permanent assignment。沒上 PIM 的組織通常會發現 <em>standing Global Admin 超過 10 個</em>、那是 phishing / token theft 的高價值靶。</p>
<p><strong>Service principal vs Managed Identity</strong>：service principal 是 app 在 Entra ID 的代表、可以用 client secret 或 certificate 認證；Managed Identity 是 service principal 的特殊形式、由 Azure 自動管 credential。能用 Managed Identity 就不用 service principal client secret — 後者要自己 rotate、要存 <a href="/blog/backend/knowledge-cards/secret-management/" data-link-title="Secret Management" data-link-desc="說明 token、key、password 與憑證如何保存、輪替與撤銷">secret management</a>、容易 stale。</p>
<p><strong>Azure Policy 是 RBAC 的補位</strong>：RBAC 管 <em>principal 能不能對 resource 做這個 action</em>、Azure Policy 管 <em>允不允許這樣設定 resource</em>（例如 storage account 強制加密、VM 只能用認可的 image）。RBAC 給 Contributor 的人可以建 storage account、但 Azure Policy 可以拒絕未加密的 storage account 建立 — 兩層互補、缺一不可。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<p>Azure 雙層體系的取捨要分開看 — 一張表回答 <em>cloud resource permission 該選哪家</em>（Azure RBAC vs AWS IAM vs Google IAM）、一張表回答 <em>workforce IdP 該選哪家</em>（Entra ID vs Okta）。兩個決策獨立、可以混搭（例如：Okta 當 workforce IdP + federate 到 Entra ID + 走 Azure RBAC 管 Azure resource）。</p>
<h3 id="azure-rbac-vs-aws-iam-vs-google-cloud-iam">Azure RBAC vs AWS IAM vs Google Cloud IAM</h3>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>Azure RBAC</th>
          <th>AWS IAM</th>
          <th>Google Cloud IAM</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Scope</td>
          <td>Management Group → Subscription → RG → Resource</td>
          <td>Account + Organization、policy attach</td>
          <td>Organization → Folder → Project</td>
      </tr>
      <tr>
          <td>繼承模型</td>
          <td>scope 向下繼承</td>
          <td>account boundary 強、跨 account 用 assume role</td>
          <td>scope 向下繼承、condition 強</td>
      </tr>
      <tr>
          <td>自訂角色</td>
          <td>Custom Role（JSON）</td>
          <td>Custom managed policy（JSON）</td>
          <td>Custom Role（YAML / API）</td>
      </tr>
      <tr>
          <td>JIT 機制</td>
          <td>Privileged Identity Management（PIM）內建</td>
          <td>無原生 JIT、要靠 IAM Identity Center / 第三方</td>
          <td>無原生 JIT、要靠 third-party / 自建</td>
      </tr>
      <tr>
          <td>Workload</td>
          <td>Managed Identity（內部）+ Workload Identity Fed</td>
          <td>IAM role + OIDC trust</td>
          <td>Workload Identity Federation</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>Azure-heavy、M365 整合</td>
          <td>AWS-heavy、account isolation 模型成熟</td>
          <td>GCP-heavy、resource hierarchy 治理</td>
      </tr>
  </tbody>
</table>
<h3 id="entra-id-vs-oktaworkforce-idp">Entra ID vs Okta（workforce IdP）</h3>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>Entra ID</th>
          <th>Okta</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>主場</td>
          <td>M365 / Azure 原生、跟 RBAC 共生</td>
          <td>多雲 + SaaS、跨平台 SSO</td>
      </tr>
      <tr>
          <td>MFA 機制</td>
          <td>Conditional Access 觸發、Authenticator app / FIDO2</td>
          <td>Sign-On / Authentication Policy、多 factor 選擇</td>
      </tr>
      <tr>
          <td>Lifecycle</td>
          <td>SCIM + cross-tenant sync</td>
          <td>SCIM + Lifecycle Management、整合更廣</td>
      </tr>
      <tr>
          <td>Workload</td>
          <td>Managed Identity / Workload Identity Federation</td>
          <td>較弱、CI 通常 federate 到雲 IAM</td>
      </tr>
      <tr>
          <td>整合廣度</td>
          <td>M365 / Azure / Office app 深、外部 SaaS 比 Okta 少</td>
          <td>7000+ SaaS app 預建</td>
      </tr>
      <tr>
          <td>第三方風險</td>
          <td>Microsoft 控制面（Storm-0558、Midnight Blizzard）</td>
          <td>Okta 控制面（2022 / 2023 多起）</td>
      </tr>
  </tbody>
</table>
<p>選 Entra ID 的核心訴求：<em>M365 / Azure 重度使用、要跟 RBAC + Managed Identity 直接整合、能接受 Microsoft 控制面風險</em>；選 Okta 的核心訴求看 <a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta vendor 頁</a>。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Conditional Access 進階規則</strong>：除了 user / device / location 基本條件、進階場景包含 <em>risk-based</em>（Identity Protection 給的 user risk / sign-in risk）、<em>token protection</em>（token binding 到 device、防止 token replay）、<em>authentication strength</em>（強制 phishing-resistant factor）。production tenant 至少要有「Global Admin 必須走 phishing-resistant + compliant device」這條規則。</p>
<p><strong>Privileged Identity Management（PIM）的設計細節</strong>：activation 要求 MFA、approval（高權限角色）、justification、時限（預設 8 小時、最長 24）。Access Review 是 PIM 的配套 — 季度檢視 standing assignment 是否還需要、不需要的撤掉。沒做 Access Review 的 PIM 等於只把問題從 standing 推到 <em>誰申請就給</em> — 不是 least privilege。</p>
<p><strong>Workload Identity Federation 跨雲</strong>：Entra ID 可以 trust GitHub Actions / GitLab / AWS / Google 的 OIDC issuer、讓 CI 直接拿 Azure token。同向也成立 — Azure workload 可以拿 Google ID token federate 進 GCP。多雲 CI 不該存任何 client secret、走 federation 比較安全。</p>
<p><strong>Custom Role 設計實務</strong>：用 <code>Microsoft.Authorization/roleDefinitions</code> API 或 portal 定義、<code>actions</code> / <code>notActions</code> / <code>dataActions</code> 各自獨立 — <code>actions</code> 是 control plane、<code>dataActions</code> 是 data plane（讀寫 blob、key vault secret 內容）。常見錯誤是只收 <code>actions</code> 沒收 <code>dataActions</code>、結果 storage account 設定改不了但 blob 內容隨便讀。</p>
<p><strong>Azure Policy 跟 Initiative</strong>：Policy 是單一規則、Initiative 是 policy 的集合（用來組 baseline、例如 CIS、ISO 27001）。Policy effect 有 audit / deny / deployIfNotExists、後者可以自動補洞（例如自動加 diagnostic setting）。RBAC + Policy 一起設計才是完整的 <a href="/blog/backend/knowledge-cards/authorization/" data-link-title="Authorization" data-link-desc="說明授權如何判斷誰能對哪些資源執行哪些操作">Authorization</a> 邊界。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Global Admin 過多</strong>：standing Global Admin 超過 5 個就要警惕 — 上 PIM、把日常運維改用 Privileged Role Administrator + 特定 admin role group</li>
<li><strong>Conditional Access 規則漏 legacy auth</strong>：規則只 cover modern auth、IMAP / POP / SMTP 等 legacy protocol 不走 CA — 用「Block legacy authentication」baseline policy 補</li>
<li><strong>App Registration / Enterprise Application admin consent 沒審查</strong>：使用者自己 consent 把 mail.read 給三方 app、變 consent phishing 入口 — 關閉 user consent、改 admin consent workflow</li>
<li><strong>Service principal client secret 散落</strong>：CI / 服務裡有大量 client secret、rotate 沒節奏 — 改 Managed Identity（內部）或 Workload Identity Federation（跨雲 CI）</li>
<li><strong>Subscription Owner 太多</strong>：subscription 級 Owner 是高風險、應該收到 Management Group 級 Reader + 必要時 PIM activate Owner</li>
<li><strong>Azure Activity Log 沒進 SIEM</strong>：role assignment 變更、Key Vault access policy 變更只在 Azure portal 看得到、沒 alert — 用 Diagnostic Setting 推 Event Hub / Log Analytics、再進 SIEM</li>
<li><strong>Break-glass 帳號 exclude 自所有 CA policy、但沒監控</strong>：emergency access 帳號不能被 CA 鎖、但 <em>任何登入都該 alert</em> — 配對 Sign-in Log alert + 季度驗證可用</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>AWS-only 環境</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM</a></td>
      </tr>
      <tr>
          <td>GCP-only 環境</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google Cloud IAM</a></td>
      </tr>
      <tr>
          <td>多雲 + 大量 SaaS、IdP 中心化</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a></td>
      </tr>
      <tr>
          <td>Customer / B2C identity</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/auth0/" data-link-title="Auth0" data-link-desc="B2C / B2B Customer Identity Provider、Universal Login、Action / Rule hook、屬 Okta 旗下 Customer Identity Cloud">Auth0</a></td>
      </tr>
      <tr>
          <td>自管 IdP / 不接受 SaaS</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/keycloak/" data-link-title="Keycloak" data-link-desc="Open source self-hosted Identity Provider、Red Hat 主導、Realm-based multi-tenancy、適合資料主權與自訂 flow 需求">Keycloak</a></td>
      </tr>
      <tr>
          <td>Secret / Key 管理</td>
          <td><a href="/blog/backend/07-security-data-protection/secrets-and-machine-credential-governance/" data-link-title="7.6 秘密管理與機器憑證治理" data-link-desc="以問題驅動方式整理 secret、token、key 與機器身份治理">7.6 秘密管理與機器憑證治理</a>（Azure Key Vault vendor 頁 S2 批次撰寫中）</td>
      </tr>
      <tr>
          <td>偵測訊號（不只 Entra ID 內部）</td>
          <td>07 SIEM 章節、04 observability</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Entra ID 完整 SAML / OIDC / SCIM 規格細節</li>
<li>Azure RBAC built-in role 完整清單與 action 對照</li>
<li>Conditional Access policy template 細節</li>
<li>Azure Policy 內建 initiative 完整清單</li>
<li>Microsoft 365 / Defender for Identity 等周邊產品</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 Entra ID / Azure RBAC 的關係</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/cases/azure-ad-identity-control-plane-2021/" data-link-title="7.C3 Azure AD：2021 Identity Control-plane 事件" data-link-desc="身分控制面事件如何影響多服務信任鏈與回復優先序。">Azure AD Identity Control Plane 2021</a></td>
          <td>Entra ID 控制面故障外溢到 Teams / SharePoint / Exchange、業務必須有降級與切換策略、不能完全依賴單一 IdP 可用性</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/cases/microsoft-storm-0558-signing-key-2023/" data-link-title="7.C4 Microsoft：Storm-0558 簽章金鑰事件" data-link-desc="簽章金鑰事件如何回寫 identity 信任邊界與觀測證據鏈。">Microsoft Storm-0558 Signing Key 2023</a></td>
          <td>signing key 治理失效會跨租戶影響 token 驗證信任、客戶側只能等供應商修復（MSRC / CSRB 公開報告補充了 crash dump / Exchange Online 等具體外洩路徑、屬 case 檔之外的歷史 reference）</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/microsoft-storm-0558-2023-signing-key-chain/" data-link-title="7.R7.1.5 Microsoft Storm-0558 2023：簽章金鑰鏈與郵件存取" data-link-desc="從簽章金鑰保護失效到雲端郵件存取，拆解身分信任鏈的關鍵控制點">Microsoft Storm-0558 Signing Key Chain (red-team)</a></td>
          <td>HSM-bound key 是 control plane 必要前提、跨租戶 token 異常要立即升級、不能等供應商先公告</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/cases/failure-credential-rotation-without-scope/" data-link-title="7.C9 反例：憑證輪替未分 Scope" data-link-desc="憑證輪替若未分域分批，容易造成跨系統連鎖中斷。">Failure: Credential Rotation Without Scope</a></td>
          <td>Entra ID app secret 跟 Managed Identity 的 rotation 分域、不該把 service principal client secret 跟 user password 混在同一個 rotation policy</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/identity-access-boundary/" data-link-title="7.2 身分與授權邊界" data-link-desc="以問題驅動方式整理身分、授權、會話與供應商身分鏈">7.2 身分與授權邊界</a>、<a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">7.13 偵測覆蓋率與訊號治理</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM</a>、<a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google Cloud IAM</a>、<a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a></li>
<li>下游：<a href="/blog/backend/07-security-data-protection/secrets-and-machine-credential-governance/" data-link-title="7.6 秘密管理與機器憑證治理" data-link-desc="以問題驅動方式整理 secret、token、key 與機器身份治理">7.6 秘密管理與機器憑證治理</a>（Entra ID / Managed Identity 之後的 secret / key 層、Azure Key Vendor 個別 vendor 頁 S2 批次撰寫中）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（Entra ID / Azure 事件如何 routing 進 IR 流程）</li>
<li>官方：<a href="https://learn.microsoft.com/entra/">Microsoft Entra Documentation</a>、<a href="https://learn.microsoft.com/azure/role-based-access-control/">Azure RBAC Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>Cloud-native Data Policy (BigQuery + S3)</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/cloud-data-policy/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/cloud-data-policy/</guid><description>&lt;p>Cloud-native data policy 的核心責任是把資料層的 access 控制綁在 &lt;em>storage resource 本身&lt;/em>、用該雲既有的 IAM 體系做 enforcement、不依賴額外的 data security platform。本頁同時涵蓋 &lt;em>BigQuery policy tooling&lt;/em>（Authorized View / Column-level security / Row-level security / Dynamic Data Masking）跟 &lt;em>AWS S3 policy tooling&lt;/em>（Bucket policy / Access Points / Object Lambda / Macie / Block Public Access）— 兩條 sister stack 是各自雲端代表性的 data access control 設計、合一頁是為了讓讀者看清楚 &lt;em>GCP 走 SQL-native 細粒度&lt;/em> 跟 &lt;em>AWS 走 storage-resource-bound&lt;/em> 的取捨差異、不是把它們當同類混寫。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Cloud-native data policy 是 &lt;em>resource-bound&lt;/em> access control — 控制邏輯掛在 BigQuery dataset / column / row 或 S3 bucket / object 上、用 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google Cloud IAM&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM&lt;/a> 的 principal 體系做 evaluation。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/google-dlp/" data-link-title="Google DLP" data-link-desc="GCP 原生 Sensitive Data Protection：infoType discovery &amp;#43; transformation (mask / FPE / tokenize / k-anonymity)、整合 BigQuery / GCS / Cloud SQL">Google DLP&lt;/a> 比、DLP 是 &lt;em>content-based discovery + transformation&lt;/em>（掃 PII、做 de-id）、本頁工具是 &lt;em>access boundary&lt;/em>；典型組合是 &lt;em>DLP 發現 sensitive column → BigQuery policy tag 控制誰能讀 → S3 Object Lambda redact at read time&lt;/em>。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/microsoft-purview/" data-link-title="Microsoft Purview" data-link-desc="Microsoft 跨 M365 / Azure / endpoint 的 data governance &amp;#43; information protection &amp;#43; DLP &amp;#43; insider risk 統合平台、label-driven">Microsoft Purview&lt;/a> 比、Purview 走 &lt;em>label-driven + 跨 platform&lt;/em>（同一個 sensitivity label 跨 SharePoint / Fabric / Azure SQL）、雲端原生 policy 走 &lt;em>resource-bound + 限該雲&lt;/em>；雲端原生更貼近 storage、跨雲統一靠商業 platform。跟通用 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Cloud IAM&lt;/a> 比、IAM 是 &lt;em>resource-level read/write 二分&lt;/em>、本頁是 &lt;em>column / row / object-level 細粒度&lt;/em>、補 IAM 解不掉的「同一張表只能看自家行」場景。&lt;/p></description><content:encoded><![CDATA[<p>Cloud-native data policy 的核心責任是把資料層的 access 控制綁在 <em>storage resource 本身</em>、用該雲既有的 IAM 體系做 enforcement、不依賴額外的 data security platform。本頁同時涵蓋 <em>BigQuery policy tooling</em>（Authorized View / Column-level security / Row-level security / Dynamic Data Masking）跟 <em>AWS S3 policy tooling</em>（Bucket policy / Access Points / Object Lambda / Macie / Block Public Access）— 兩條 sister stack 是各自雲端代表性的 data access control 設計、合一頁是為了讓讀者看清楚 <em>GCP 走 SQL-native 細粒度</em> 跟 <em>AWS 走 storage-resource-bound</em> 的取捨差異、不是把它們當同類混寫。</p>
<h2 id="服務定位">服務定位</h2>
<p>Cloud-native data policy 是 <em>resource-bound</em> access control — 控制邏輯掛在 BigQuery dataset / column / row 或 S3 bucket / object 上、用 <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google Cloud IAM</a> / <a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM</a> 的 principal 體系做 evaluation。跟 <a href="/blog/backend/07-security-data-protection/vendors/google-dlp/" data-link-title="Google DLP" data-link-desc="GCP 原生 Sensitive Data Protection：infoType discovery &#43; transformation (mask / FPE / tokenize / k-anonymity)、整合 BigQuery / GCS / Cloud SQL">Google DLP</a> 比、DLP 是 <em>content-based discovery + transformation</em>（掃 PII、做 de-id）、本頁工具是 <em>access boundary</em>；典型組合是 <em>DLP 發現 sensitive column → BigQuery policy tag 控制誰能讀 → S3 Object Lambda redact at read time</em>。跟 <a href="/blog/backend/07-security-data-protection/vendors/microsoft-purview/" data-link-title="Microsoft Purview" data-link-desc="Microsoft 跨 M365 / Azure / endpoint 的 data governance &#43; information protection &#43; DLP &#43; insider risk 統合平台、label-driven">Microsoft Purview</a> 比、Purview 走 <em>label-driven + 跨 platform</em>（同一個 sensitivity label 跨 SharePoint / Fabric / Azure SQL）、雲端原生 policy 走 <em>resource-bound + 限該雲</em>；雲端原生更貼近 storage、跨雲統一靠商業 platform。跟通用 <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Cloud IAM</a> 比、IAM 是 <em>resource-level read/write 二分</em>、本頁是 <em>column / row / object-level 細粒度</em>、補 IAM 解不掉的「同一張表只能看自家行」場景。</p>
<p>關鍵張力：<em>資料細粒度</em> ↔ <em>跨雲 portability</em>。BigQuery RLS 跟 S3 Access Points 的 policy 語法都是該雲專屬、換雲要重寫；換來的是 free（無額外授權）+ 平台原生效能（不過代理）。多雲 enterprise 若要統一 policy DSL、走 Immuta / Privacera / Snowflake Horizon。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>BigQuery 跟 S3 policy 各自能做到什麼層級的細粒度（column / row / object / cross-region）、不能做到什麼</li>
<li>Cloud-native policy 跟 <a href="/blog/backend/07-security-data-protection/vendors/google-dlp/" data-link-title="Google DLP" data-link-desc="GCP 原生 Sensitive Data Protection：infoType discovery &#43; transformation (mask / FPE / tokenize / k-anonymity)、整合 BigQuery / GCS / Cloud SQL">Google DLP</a> / <a href="/blog/backend/07-security-data-protection/vendors/microsoft-purview/" data-link-title="Microsoft Purview" data-link-desc="Microsoft 跨 M365 / Azure / endpoint 的 data governance &#43; information protection &#43; DLP &#43; insider risk 統合平台、label-driven">Microsoft Purview</a> 的責任分界、何時要組合使用</li>
<li>Multi-tenant SaaS 在共用 dataset / bucket 場景的 access boundary 設計（BigQuery RLS / S3 Access Points）</li>
<li>何時用雲端原生 policy、何時改走 Immuta / Privacera / Snowflake 跨雲 data security platform</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 cloud-native data policy 是否健康、最少看四件事：</p>
<ul>
<li><strong>BigQuery 側 — RLS / column policy coverage</strong>：multi-tenant dataset 是否有 <code>CREATE ROW ACCESS POLICY</code>、sensitive column 是否綁 policy tag、policy tag 上的 IAM 是否走 group 而非 individual user、view-only access 是否走 <a href="https://cloud.google.com/bigquery/docs/authorized-views">Authorized View</a> 而非 dataset grant</li>
<li><strong>S3 側 — bucket policy 結構</strong>：Block Public Access 是否 account-level 開啟、ACL 是否 disabled（Object Ownership = BucketOwnerEnforced）、共用 bucket 是否走 Access Points 分租戶、跨帳號是否經 AP policy + bucket policy 雙重驗證</li>
<li><strong>Sensitive data discovery 接口</strong>：BigQuery 是否接 <a href="/blog/backend/07-security-data-protection/vendors/google-dlp/" data-link-title="Google DLP" data-link-desc="GCP 原生 Sensitive Data Protection：infoType discovery &#43; transformation (mask / FPE / tokenize / k-anonymity)、整合 BigQuery / GCS / Cloud SQL">Google DLP</a> inspection job、Dataplex 是否跑 data classification、S3 是否開 Macie scan、findings 是否進 EventBridge / Security Hub 而非僅 console 看</li>
<li><strong>Audit trail completeness</strong>：BigQuery audit log（dataAccess）是否進 <a href="/blog/backend/04-observability/" data-link-title="模組四：可觀測性平台" data-link-desc="整理 log、metric、trace、dashboard 與 alert 的後端操作實務">Cloud Logging</a> + 進 SIEM、S3 是否開 server access logging + CloudTrail data event（GetObject / PutObject）、跟 <a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">Detection Coverage</a> 對齊</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/07-security-data-protection/data-residency-deletion-and-evidence-chain/" data-link-title="7.11 資料駐留、刪除與證據鏈" data-link-desc="定義跨區資料駐留、刪除請求與可驗證證據鏈問題">Data Residency, Deletion and Evidence Chain</a> 邊界的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="bigquery-側">BigQuery 側</h3>
<p><strong>Authorized View / Authorized Routine</strong>：view 的 SQL definition 可以讀 source dataset、grantee 只要被 grant view 自身就能查、<em>不需要 grant source dataset access</em>。經典「給 analyst 看 aggregate 數據但不給原始 PII row」模式 — analyst 看 <code>SELECT region, count(*) FROM customer</code> 沒問題、但 underlying <code>customer</code> table 從不出現在 analyst IAM。Authorized Routine 是同邏輯延伸到 stored procedure / UDF、適合 logic 比 SELECT 複雜的轉換場景。</p>
<p><strong>Column-level security（policy tag）</strong>：在 <a href="https://cloud.google.com/data-catalog">Data Catalog</a> 建 taxonomy + policy tag、把 BigQuery column schema 綁 tag、policy tag 上設 <em>fine-grained reader</em> role。沒這個 role 的 user 即使有 dataset access、<code>SELECT *</code> 時該 column 會 <em>raise error</em> 或 <em>被 omit</em>。HIPAA / PCI-DSS 對「即使 DBA 也不能 default 看到 PHI / cardholder data」的硬要求、走 policy tag 是技術性 enforcement、不是 procedural control。</p>
<p><strong>Row-level security (RLS)</strong>：<code>CREATE ROW ACCESS POLICY tenant_filter ON dataset.table GRANT TO ('group:analysts@org.com') FILTER USING (tenant_id = SESSION_USER())</code>。每個 query 自動 append filter、user 看到的 row 由 policy expression 決定。Multi-tenant SaaS（共用 dataset、每行帶 <code>tenant_id</code>）必用 — 否則 query 必須在 application layer 帶 WHERE、漏一處就是跨 tenant data leak。對應 <a href="/blog/backend/07-security-data-protection/red-team/cases/data-exfiltration/snowflake-2024-credential-abuse/" data-link-title="7.R7.4.2 Snowflake 2024：憑證濫用與資料竊取" data-link-desc="外洩憑證與 MFA 缺口如何在資料平台形成高風險外送事件">Snowflake 2024 Credential Abuse</a> 的對照啟示。</p>
<p><strong>Dynamic Data Masking</strong>：column 上設 masking rule（hash / nullify / partial mask / regex replace）、不同 IAM 角色看不同 mask 程度 — <code>email_address</code> 在 admin 看到原值、在 analyst 看到 <code>***@example.com</code>、在 external partner 看到 NULL。補 RLS 不足之處：RLS 過濾 <em>哪些 row 看得到</em>、Masking 過濾 <em>看到的 row 內容怎麼呈現</em>；兩者組合解大多數 multi-tenant + multi-role 場景。</p>
<p><strong>Dataplex Data Classification + DLP 整合</strong>：Dataplex 走 lake-wide 治理（dataset metadata + lineage + quality）、自動觸發 <a href="/blog/backend/07-security-data-protection/vendors/google-dlp/" data-link-title="Google DLP" data-link-desc="GCP 原生 Sensitive Data Protection：infoType discovery &#43; transformation (mask / FPE / tokenize / k-anonymity)、整合 BigQuery / GCS / Cloud SQL">Google DLP</a> inspection、發現 sensitive column 自動建議 / 套用 policy tag。是 GCP 內部把 <em>discovery → access control</em> 自動化的標準路徑。</p>
<h3 id="s3-側">S3 側</h3>
<p><strong>Block Public Access account-level</strong>：2018 推出、2023 起新建 bucket 預設開啟。account-level setting 強制 override 所有 bucket policy / ACL — 即使有 bucket policy 寫 <code>&quot;Principal&quot;: &quot;*&quot;</code>、Block Public Access 開啟時也禁止對外暴露。Production AWS 帳號必須 account-level 開、bucket-level 額外加固。是 <a href="/blog/backend/07-security-data-protection/red-team/cases/data-exfiltration/lastpass-2022-backup-chain/" data-link-title="7.R7.4.1 LastPass 2022：備份路徑與鏈式入侵" data-link-desc="開發環境資訊外流如何沿著備份路徑擴大成資料風險">LastPass 2022 Backup Chain</a> 類事故的 last-line defense。</p>
<p><strong>Bucket policy / IAM policy / ACL（legacy）</strong>：三層 evaluation — bucket policy（resource-based、寫在 bucket 上）、IAM policy（identity-based、寫在 principal 上）、ACL（legacy object-level、新建 bucket 應禁用）。AWS 2023 起推 <em>Object Ownership = BucketOwnerEnforced</em>、強制 ACL disabled、所有 access 經 bucket policy + IAM 決定。舊 bucket 應走 ACL → bucket policy migration。</p>
<p><strong>S3 Access Points</strong>：每個 bucket 可開多個 Access Point、各有獨立 name + policy + VPC restriction。Multi-tenant 場景（一個 bucket 服務多個 tenant）走「每個 tenant 一個 AP + AP policy 限定 prefix + 限定 VPC」、取代過去「shared bucket + prefix-based IAM」的脆弱模式。對應 <a href="/blog/backend/07-security-data-protection/red-team/cases/data-exfiltration/mailchimp-2023-support-tool-abuse/" data-link-title="7.R7.4.4 Mailchimp 2023：支援工具路徑與客戶資料風險" data-link-desc="社交工程進入客服工具後，如何形成特定客戶資料存取風險">Mailchimp 2023 Support Tool Abuse</a> 的對照啟示 — 共用入口需 <em>per-tenant policy boundary</em>、不是 application-layer filtering。</p>
<p><strong>Multi-Region Access Points (MRAP)</strong>：跨 region replicated bucket 的單一 global endpoint、自動 route 到最近 region。資料駐留要求高的場景（GDPR / 中國資料法）反而要慎用、因為 read 來源不可預測；對 latency-sensitive 全球分發是 first-class 解法。</p>
<p><strong>Object Lambda Access Points</strong>：在 GetObject response path 插 Lambda、做 <em>read-time transformation</em>（redact PII / format conversion / image resize / decrypt + re-encrypt）。同一份 raw object、不同 caller 透過不同 Object Lambda AP 看到不同版本 — 等同 BigQuery Dynamic Data Masking 在 S3 的對應物。但 Lambda 有 cold start + 6MB response limit、不是所有場景都合適。</p>
<p><strong>Macie sensitive data discovery</strong>：S3 專屬、scan bucket 找 PII / credential / payment data、findings 進 EventBridge + AWS Security Hub。跟 <a href="/blog/backend/07-security-data-protection/vendors/google-dlp/" data-link-title="Google DLP" data-link-desc="GCP 原生 Sensitive Data Protection：infoType discovery &#43; transformation (mask / FPE / tokenize / k-anonymity)、整合 BigQuery / GCS / Cloud SQL">Google DLP</a> 同層但限 S3、不能掃 RDS / DynamoDB。findings 應自動 route 到 SIEM、不是只在 Macie console 等人看。對應 <a href="/blog/backend/07-security-data-protection/red-team/cases/data-exfiltration/progress-wsftp-2023-file-service-breach/" data-link-title="7.R7.4.6 Progress WS_FTP 2023：檔案服務入口與資料外送" data-link-desc="對外檔案服務漏洞在企業環境常直接轉為資料外送風險">Progress WS_FTP 2023 File Service Breach</a> 的對照 — 對外檔案服務必有 audit + 異常量 baseline + Macie sensitive content scan。</p>
<p><strong>S3 Object Ownership / ACL disabled</strong>：2023+ 預設 ACL disabled、所有新 bucket 應 keep this default、舊 bucket 走 audit + migration（先掃 ACL grant、確認沒人靠 ACL 拿 access、再切換）。混用 ACL + bucket policy 的 bucket 是 access control 漂移最常見的源頭。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>BigQuery policy tooling</th>
          <th>S3 policy tooling</th>
          <th>Immuta / Privacera</th>
          <th>Snowflake Horizon</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>細粒度層級</td>
          <td>Column / Row / cell-level（policy tag + RLS + DDM）</td>
          <td>Object-level（prefix-based）+ Object Lambda 內容轉換</td>
          <td>Column / Row / cell + 跨平台統一 DSL</td>
          <td>Column / Row + Snowflake 平台限定</td>
      </tr>
      <tr>
          <td>計費</td>
          <td>Free（included in BigQuery）</td>
          <td>Free（bucket policy）+ Macie / Object Lambda 用量計費</td>
          <td>商業授權、per-user 或 per-data-source</td>
          <td>Snowflake 平台費內含</td>
      </tr>
      <tr>
          <td>跨雲 portable</td>
          <td>GCP only</td>
          <td>AWS only</td>
          <td>跨 BigQuery / Snowflake / Databricks / S3</td>
          <td>Snowflake only</td>
      </tr>
      <tr>
          <td>Policy DSL</td>
          <td>SQL-native（CREATE ROW ACCESS POLICY、masking SQL）</td>
          <td>JSON policy + Lambda 程式碼</td>
          <td>統一 attribute-based DSL</td>
          <td>SQL-native</td>
      </tr>
      <tr>
          <td>Sensitive discovery</td>
          <td>DLP / Dataplex 自動整合</td>
          <td>Macie（限 S3）</td>
          <td>內建 + 跨平台 scan</td>
          <td>跨 schema metadata + classification</td>
      </tr>
      <tr>
          <td>Audit</td>
          <td>Cloud Audit Log dataAccess 細到 column</td>
          <td>CloudTrail data event + server access log</td>
          <td>跨平台統一 audit trail</td>
          <td>Snowflake QUERY_HISTORY</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>GCP-first、BigQuery 為主 data warehouse</td>
          <td>AWS-first、S3 為 data lake / 檔案分發</td>
          <td>多雲 enterprise、跨平台統一 policy</td>
          <td>Snowflake-centric data platform</td>
      </tr>
      <tr>
          <td>退場成本</td>
          <td>中 — RLS / policy tag 重寫到目標平台</td>
          <td>中 — bucket policy / AP 重寫</td>
          <td>低 — DSL 抽象可遷移</td>
          <td>中 — 限 Snowflake</td>
      </tr>
  </tbody>
</table>
<p>選雲端原生 policy 的核心訴求：<em>單一雲 + 預算敏感 + 不想引入新 vendor</em>。多雲 enterprise + 統一治理需求高、走 Immuta / Privacera 才能避免兩套 policy 漂移。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>BigQuery Authorized View vs RLS 取捨</strong>：Authorized View 適合 <em>shape-based filtering</em>（grantee 只能看 aggregate / 特定 column subset）、RLS 適合 <em>value-based filtering</em>（grantee 只能看 tenant_id = self 的行）。實務常常組合 — view 限 column、view 上再加 RLS 限 row。view 的問題是維護成本（schema 改要同步改 view）、RLS 的問題是 policy expression 寫錯整批 user 看不到資料、staging tenant 跑過再 promote。</p>
<p><strong>S3 Access Points + VPC-only restriction</strong>：AP policy 可加 <code>&quot;Condition&quot;: {&quot;StringEquals&quot;: {&quot;aws:SourceVpc&quot;: &quot;vpc-xxx&quot;}}</code>、強制只能從特定 VPC access — 跨帳號場景（partner 帳號 access 自家 bucket）必加、避免 partner credential 外洩後可從任意網路位置存取。對應 <a href="/blog/backend/07-security-data-protection/red-team/cases/data-exfiltration/lastpass-2022-backup-chain/" data-link-title="7.R7.4.1 LastPass 2022：備份路徑與鏈式入侵" data-link-desc="開發環境資訊外流如何沿著備份路徑擴大成資料風險">LastPass 2022 Backup Chain</a> 對照、backup bucket 不該跟 prod bucket 共用 IAM role + 不該允許 internet-wide access。</p>
<p><strong>Object Lambda redact PII at read time</strong>：適合 <em>raw data 已寫入、但不同 consumer 需要不同 view</em> 的場景 — 例如客服查 user record 看到 mask 過的 SSN、合規 audit 帳號看到完整 SSN。Lambda 內部呼叫 <a href="/blog/backend/07-security-data-protection/vendors/google-dlp/" data-link-title="Google DLP" data-link-desc="GCP 原生 Sensitive Data Protection：infoType discovery &#43; transformation (mask / FPE / tokenize / k-anonymity)、整合 BigQuery / GCS / Cloud SQL">Google DLP</a> deid template / Comprehend PII detection / 自家 regex；要注意 cold start 對 latency 的影響、不適合 high-throughput 場景。</p>
<p><strong>Macie automated discovery → SIEM</strong>：Macie findings 走 EventBridge rule → Security Hub → 推 <a href="/blog/backend/07-security-data-protection/vendors/" data-link-title="資安與資料保護 Vendor 清單" data-link-desc="規劃身份、秘密、金鑰、入口防護、供應鏈與偵測工具的服務頁撰寫順序與教學大綱">Splunk / Elastic Security / Datadog Security</a> — 不該只在 Macie console 看 findings。發現 unencrypted S3 bucket 有 cardholder data 必須觸發 incident response runbook、進 <a href="/blog/backend/08-incident-response/" data-link-title="模組八：事故處理與復盤" data-link-desc="用 IR 領域詞彙建問題節點、以服務級案例庫累積事故脈絡，先建概念與案例庫再進實作交接">8 事故處理</a>。</p>
<p><strong>跨 region 跟 data residency</strong>：BigQuery dataset region + S3 bucket region 是 <em>資料駐留 enforcement</em> 的硬邊界、policy tooling 不能 override。GDPR / 中國資料法場景必須 <em>region pinning</em> + 禁止 Multi-Region replication、policy tag / RLS 無法解決資料離境問題。對應 <a href="/blog/backend/07-security-data-protection/data-residency-deletion-and-evidence-chain/" data-link-title="7.11 資料駐留、刪除與證據鏈" data-link-desc="定義跨區資料駐留、刪除請求與可驗證證據鏈問題">Data Residency Deletion and Evidence Chain</a> 章節原則。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>BigQuery RLS 設了但 user 還是看到全部 row</strong>：policy <code>GRANT TO</code> 沒包該 user 的 group、或 user 有 <code>bigquery.dataOwner</code> role（owner override RLS）— check group membership + 降權到 dataViewer</li>
<li><strong>Column policy tag 沒生效</strong>：column 沒 attach tag、或 tag taxonomy 沒在該 project / region — check Data Catalog taxonomy location 跟 dataset region 對齊</li>
<li><strong>S3 bucket 意外 public</strong>：Block Public Access account-level 沒開 + bucket policy 寫 <code>&quot;Principal&quot;: &quot;*&quot;</code>、或 ACL 殘留 AllUsers grant — 立即開 BPA + audit ACL（aws s3api get-bucket-acl）</li>
<li><strong>Access Point policy 跟 bucket policy 衝突</strong>：AP 允許 但 bucket policy 拒絕、最後是拒絕（explicit deny 永遠勝）— 兩層都要明確 allow、bucket policy 加 <code>&quot;Principal&quot;: {&quot;AWS&quot;: &quot;*&quot;}</code> + condition 限定 AP ARN</li>
<li><strong>Macie scan 跑很久 / cost 暴衝</strong>：scan 整個 bucket、含 archive prefix、沒設 sampling — 用 <em>sensitive data discovery job</em> with prefix filter + sampling rate、不要 default 全 bucket scan</li>
<li><strong>Authorized View grantee 看不到資料</strong>：view definition 走的 source dataset 沒 authorize 該 view、或 view 自身改了但沒重新 authorize — <code>bq update --view_authorization</code> 重設</li>
<li><strong>Object Lambda 慢 / timeout</strong>：Lambda cold start + 6MB response limit、大檔案不該走 Object Lambda — 改在寫入時 transform、或用 pre-signed URL 繞過 Object Lambda</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>跨雲統一 data policy DSL</td>
          <td>Immuta / Privacera</td>
      </tr>
      <tr>
          <td>Content-based discovery + de-id</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/google-dlp/" data-link-title="Google DLP" data-link-desc="GCP 原生 Sensitive Data Protection：infoType discovery &#43; transformation (mask / FPE / tokenize / k-anonymity)、整合 BigQuery / GCS / Cloud SQL">Google DLP</a> / <a href="/blog/backend/07-security-data-protection/vendors/microsoft-purview/" data-link-title="Microsoft Purview" data-link-desc="Microsoft 跨 M365 / Azure / endpoint 的 data governance &#43; information protection &#43; DLP &#43; insider risk 統合平台、label-driven">Microsoft Purview</a></td>
      </tr>
      <tr>
          <td>Label-driven + Microsoft 365 跨 platform</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/microsoft-purview/" data-link-title="Microsoft Purview" data-link-desc="Microsoft 跨 M365 / Azure / endpoint 的 data governance &#43; information protection &#43; DLP &#43; insider risk 統合平台、label-driven">Microsoft Purview</a></td>
      </tr>
      <tr>
          <td>Application-layer access control</td>
          <td>應用層 RBAC / ABAC（Casbin / OPA / Cerbos）</td>
      </tr>
      <tr>
          <td>Snowflake-centric data platform</td>
          <td>Snowflake Horizon（row access policy / masking policy 平台內建）</td>
      </tr>
      <tr>
          <td>通用 cloud resource permission</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google Cloud IAM</a></td>
      </tr>
      <tr>
          <td>SIEM / detection</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/" data-link-title="資安與資料保護 Vendor 清單" data-link-desc="規劃身份、秘密、金鑰、入口防護、供應鏈與偵測工具的服務頁撰寫順序與教學大綱">Splunk / Elastic Security / Datadog Security</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>BigQuery / S3 自身的完整 admin guide（pricing / region / quota）</li>
<li>Encryption-at-rest 細節（KMS 整合走 <a href="/blog/backend/07-security-data-protection/vendors/aws-kms/" data-link-title="AWS KMS" data-link-desc="AWS 原生 key management service、envelope encryption / digital signing / Multi-Region Key、Key Policy &#43; Grant 雙軌授權">AWS KMS</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-kms/" data-link-title="Google Cloud KMS" data-link-desc="GCP 原生 key management service、KeyRing / CryptoKey Version 設計、CMEK 整合 &#43; Cloud HSM &#43; External Key Manager">Google Cloud KMS</a> 頁）</li>
<li>Azure Data Lake / Azure SQL policy（屬 Azure stack、本頁不涵蓋）</li>
<li>應用層 RBAC framework（Casbin / Cerbos / OPA Rego）</li>
<li>資料庫層 RLS（PostgreSQL RLS / SQL Server Row-Level Security）— 跟雲端原生 storage policy 是不同層</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>Cloud-native data policy 在 07 案例庫沒有直接 vendor-level 事件、所有 data exfiltration case 都是 access boundary 的對照：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 cloud-native data policy 的關係（對照啟示）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/data-exfiltration/snowflake-2024-credential-abuse/" data-link-title="7.R7.4.2 Snowflake 2024：憑證濫用與資料竊取" data-link-desc="外洩憑證與 MFA 缺口如何在資料平台形成高風險外送事件">Snowflake 2024 Credential Abuse</a></td>
          <td>Multi-tenant SaaS 共用 dataset / schema 必須有 BigQuery RLS / Snowflake row access policy 等技術邊界、即使 credential 外洩攻擊者也只能看授權 row、不能只靠 application-layer WHERE</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/data-exfiltration/lastpass-2022-backup-chain/" data-link-title="7.R7.4.1 LastPass 2022：備份路徑與鏈式入侵" data-link-desc="開發環境資訊外流如何沿著備份路徑擴大成資料風險">LastPass 2022 Backup Chain</a></td>
          <td>S3 backup bucket 跟 prod bucket 必須獨立 Access Point + 獨立 IAM role + VPC restriction、同帳號 prefix-based 區隔不夠、Block Public Access 是 last-line</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/data-exfiltration/progress-wsftp-2023-file-service-breach/" data-link-title="7.R7.4.6 Progress WS_FTP 2023：檔案服務入口與資料外送" data-link-desc="對外檔案服務漏洞在企業環境常直接轉為資料外送風險">Progress WS_FTP 2023 File Service Breach</a></td>
          <td>對外檔案服務必須有 S3 server access log + CloudTrail data event + Macie sensitive content scan、批量下載靠 GetObject 速率 baseline alert、不是事後檢視</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/data-exfiltration/mailchimp-2023-support-tool-abuse/" data-link-title="7.R7.4.4 Mailchimp 2023：支援工具路徑與客戶資料風險" data-link-desc="社交工程進入客服工具後，如何形成特定客戶資料存取風險">Mailchimp 2023 Support Tool Abuse</a></td>
          <td>共用 bucket 服務多 tenant 必走 S3 Access Points 拆 per-tenant policy、取代 prefix-based ACL 跟 application-layer filtering 的脆弱模式</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/data-residency-deletion-and-evidence-chain/" data-link-title="7.11 資料駐留、刪除與證據鏈" data-link-desc="定義跨區資料駐留、刪除請求與可驗證證據鏈問題">Data Residency Deletion and Evidence Chain (section)</a></td>
          <td>Cloud-native policy 是 deletion + residency 治理的技術 enforcement 層、region pinning + 禁止 Multi-Region replication + audit log retention 對應章節原則</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/data-residency-deletion-and-evidence-chain/" data-link-title="7.11 資料駐留、刪除與證據鏈" data-link-desc="定義跨區資料駐留、刪除請求與可驗證證據鏈問題">7.7 資料駐留刪除與證據鏈</a>、<a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">Detection Coverage and Signal Governance</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/google-dlp/" data-link-title="Google DLP" data-link-desc="GCP 原生 Sensitive Data Protection：infoType discovery &#43; transformation (mask / FPE / tokenize / k-anonymity)、整合 BigQuery / GCS / Cloud SQL">Google DLP</a>（discovery + de-id 互補）、<a href="/blog/backend/07-security-data-protection/vendors/microsoft-purview/" data-link-title="Microsoft Purview" data-link-desc="Microsoft 跨 M365 / Azure / endpoint 的 data governance &#43; information protection &#43; DLP &#43; insider risk 統合平台、label-driven">Microsoft Purview</a>（label-driven 對照）</li>
<li>下游：<a href="/blog/backend/07-security-data-protection/vendors/" data-link-title="資安與資料保護 Vendor 清單" data-link-desc="規劃身份、秘密、金鑰、入口防護、供應鏈與偵測工具的服務頁撰寫順序與教學大綱">Splunk / Elastic Security / Datadog Security</a>（audit log + Macie findings → SIEM）</li>
<li>跨類：<a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google Cloud IAM</a>（principal 體系基底）、<a href="/blog/backend/07-security-data-protection/vendors/aws-kms/" data-link-title="AWS KMS" data-link-desc="AWS 原生 key management service、envelope encryption / digital signing / Multi-Region Key、Key Policy &#43; Grant 雙軌授權">AWS KMS</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-kms/" data-link-title="Google Cloud KMS" data-link-desc="GCP 原生 key management service、KeyRing / CryptoKey Version 設計、CMEK 整合 &#43; Cloud HSM &#43; External Key Manager">Google Cloud KMS</a>（encryption-at-rest）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（data exfiltration incident routing）、<a href="/blog/backend/01-database/" data-link-title="模組一：資料庫與持久化" data-link-desc="整理 SQL、transaction、migration 與 repository adapter 的後端實務">1 資料庫模組</a>（database-layer RLS / column policy 對照）</li>
<li>官方：<a href="https://cloud.google.com/bigquery/docs/column-level-security">BigQuery column-level security</a>、<a href="https://cloud.google.com/bigquery/docs/row-level-security-intro">BigQuery row-level security</a>、<a href="https://docs.aws.amazon.com/AmazonS3/latest/userguide/access-points.html">Amazon S3 Access Points</a>、<a href="https://docs.aws.amazon.com/macie/">Amazon Macie</a></li>
</ul>
]]></content:encoded></item><item><title>Trivy</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/trivy/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/trivy/</guid><description>&lt;p>Trivy 是 Aqua Security 維護的 &lt;em>open-source all-in-one security scanner&lt;/em>、Apache 2.0、單一 CLI 涵蓋 container image / filesystem / git repo / Kubernetes / IaC 五種 scan target、額外做 secret / license / SBOM scan。設計目標跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &amp;#43; Code (SAST) &amp;#43; Container &amp;#43; IaC &amp;#43; Cloud (CSPM)、Reachability analysis">Snyk&lt;/a> 不同 — Snyk 是 SaaS-first、用 server-side dashboard 跨 SCM / 跨 repo 聚合；Trivy 是 CLI-first、零 server、CI runner 自己就能完成所有工作、air-gapped 環境也能跑。商業版 Aqua Platform 加 dashboard / RBAC / policy / runtime defense、但 Trivy 本身免費覆蓋大部分團隊需求。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Trivy 的核心定位是 &lt;em>把 supply chain scan 收斂成一個 CLI&lt;/em>。同一個 binary 處理 container image、source tree、K8s cluster live state、Terraform / Dockerfile / CloudFormation 配置、secret / license / SBOM — 不需要拼裝多個工具、不需要 SaaS account、不需要 server。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &amp;#43; Code (SAST) &amp;#43; Container &amp;#43; IaC &amp;#43; Cloud (CSPM)、Reachability analysis">Snyk&lt;/a> 商業 SaaS 的差異是 &lt;em>資料治理權&lt;/em> 在自己這邊（scan 結果不上 vendor cloud）、代價是 &lt;em>跨 repo 集中報表&lt;/em> 需要自己拼（用 Trivy Operator 或 Aqua Platform）。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/syft-grype/" data-link-title="Syft &amp;#43; Grype" data-link-desc="Anchore 開源姐妹工具：Syft 產 SBOM (CycloneDX / SPDX) &amp;#43; Grype scan 漏洞、Unix philosophy、cosign attestation 整合">Syft + Grype&lt;/a> 的差異是 &lt;em>工具邊界劃法&lt;/em>。Anchore Syft 專做 SBOM 生成、Grype 專做 vuln scan、兩個工具靠 SBOM 標準（CycloneDX / SPDX）串接；Trivy 一個 CLI 全包、SBOM 也同樣輸出標準格式。多 vendor 並存環境（例：build pipeline 用 Syft 生 SBOM、release gate 用 Grype scan、跟 SBOM repository 互通）Syft+Grype 模組化較適合；單一團隊單一 pipeline 想 &lt;em>一次裝完&lt;/em> 用 Trivy 更直接。&lt;/p></description><content:encoded><![CDATA[<p>Trivy 是 Aqua Security 維護的 <em>open-source all-in-one security scanner</em>、Apache 2.0、單一 CLI 涵蓋 container image / filesystem / git repo / Kubernetes / IaC 五種 scan target、額外做 secret / license / SBOM scan。設計目標跟 <a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk</a> 不同 — Snyk 是 SaaS-first、用 server-side dashboard 跨 SCM / 跨 repo 聚合；Trivy 是 CLI-first、零 server、CI runner 自己就能完成所有工作、air-gapped 環境也能跑。商業版 Aqua Platform 加 dashboard / RBAC / policy / runtime defense、但 Trivy 本身免費覆蓋大部分團隊需求。</p>
<h2 id="服務定位">服務定位</h2>
<p>Trivy 的核心定位是 <em>把 supply chain scan 收斂成一個 CLI</em>。同一個 binary 處理 container image、source tree、K8s cluster live state、Terraform / Dockerfile / CloudFormation 配置、secret / license / SBOM — 不需要拼裝多個工具、不需要 SaaS account、不需要 server。跟 <a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk</a> 商業 SaaS 的差異是 <em>資料治理權</em> 在自己這邊（scan 結果不上 vendor cloud）、代價是 <em>跨 repo 集中報表</em> 需要自己拼（用 Trivy Operator 或 Aqua Platform）。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/syft-grype/" data-link-title="Syft &#43; Grype" data-link-desc="Anchore 開源姐妹工具：Syft 產 SBOM (CycloneDX / SPDX) &#43; Grype scan 漏洞、Unix philosophy、cosign attestation 整合">Syft + Grype</a> 的差異是 <em>工具邊界劃法</em>。Anchore Syft 專做 SBOM 生成、Grype 專做 vuln scan、兩個工具靠 SBOM 標準（CycloneDX / SPDX）串接；Trivy 一個 CLI 全包、SBOM 也同樣輸出標準格式。多 vendor 並存環境（例：build pipeline 用 Syft 生 SBOM、release gate 用 Grype scan、跟 SBOM repository 互通）Syft+Grype 模組化較適合；單一團隊單一 pipeline 想 <em>一次裝完</em> 用 Trivy 更直接。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GitHub Advanced Security</a> 的差異是 <em>偵測類型 + 部署面</em>。GHAS 綁 GitHub、SAST（CodeQL）覆蓋深、但容器掃跟 IaC scan 較弱；Trivy 跨 SCM、容器跟 IaC 掃強、但沒 SAST 深度。跟 Clair（RedHat / Quay 內建）或 Anchore Enterprise 比、Trivy 用戶基數大（CNCF Sandbox）、社群更新快、整合面廣（GitLab CI / GitHub Actions / Jenkins / CircleCI 都有官方 step）。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>Trivy 的五種 scan target（image / fs / repo / k8s / config）各承擔哪段 supply chain 責任、什麼時候用哪個</li>
<li>Trivy DB 的更新模型（OCI artifact、6 小時 cadence、air-gapped mirror）跟 CI runner 信任邊界</li>
<li><code>.trivyignore</code> 跟 severity gate 在 CI 怎麼接、exception 治理要設哪些 tripwire</li>
<li>何時用 Trivy、何時改走 <a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk</a> / <a href="/blog/backend/07-security-data-protection/vendors/syft-grype/" data-link-title="Syft &#43; Grype" data-link-desc="Anchore 開源姐妹工具：Syft 產 SBOM (CycloneDX / SPDX) &#43; Grype scan 漏洞、Unix philosophy、cosign attestation 整合">Syft + Grype</a> / <a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GHAS</a> 的取捨</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Trivy 配置是否健康、最少看四件事：</p>
<ul>
<li><strong>scan target 覆蓋面</strong>：是否 image / fs / config / secret 四類都跑（不是只 scan image）、CI 是否把 dev container / base image / runtime image 全納入 — 漏掉 base image 等於信任 upstream registry</li>
<li><strong>Trivy DB 更新 cadence</strong>：CI runner 是否每次都 pull 最新 DB（OCI artifact、預設 6 小時 TTL）、air-gapped 環境是否有內部 mirror（<code>--db-repository</code> 指到內部 registry）、<code>trivy --skip-db-update</code> 是否被誤用</li>
<li><strong>severity gate 是否真的 fail build</strong>：Trivy 預設 scan 完 exit 0、CI 不會 fail；需要 <code>--exit-code 1 --severity HIGH,CRITICAL</code> 才會把 PR build 擋下來、否則 scan 結果只在 log、沒人看</li>
<li><strong><code>.trivyignore</code> 治理</strong>：ignore 的 CVE 有 reason + expiration 嗎、quarterly review 流程在嗎、<code>.trivyignore.yaml</code> 有用嗎 — 沒治理的 ignore list 會無限膨脹、最後等於沒 scan</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">supply chain integrity</a> 邊界的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>CLI 五種 scan target</strong>：<code>trivy image &lt;ref&gt;</code> 掃 container image 的 OS package + language dependency；<code>trivy fs &lt;dir&gt;</code> 掃 source tree（含 lockfile + Dockerfile + IaC manifest + secret）；<code>trivy repo &lt;url&gt;</code> 不 clone 直接掃 git repo；<code>trivy k8s --report summary cluster</code> 掃 K8s cluster 內所有 workload（image + manifest 配置）；<code>trivy config &lt;dir&gt;</code> 專掃 IaC 配置（Terraform / CloudFormation / K8s YAML / Dockerfile / Helm）。本地 dev 最常用 <code>trivy fs .</code>、CI 最常用 <code>trivy image $IMAGE</code>、K8s 場景用 Trivy Operator 跑 in-cluster scan。</p>
<p><strong>Trivy DB（OCI artifact）</strong>：Trivy 自己維護 vulnerability DB、以 OCI artifact 形式存在 <code>ghcr.io/aquasecurity/trivy-db</code>、每 6 小時更新一次。CI runner 第一次 scan 自動 pull、後續用 cache。air-gapped 環境（金融 / 政府 / 工控）需要把 DB mirror 到內部 OCI registry、<code>--db-repository internal.registry/trivy-db</code> 指過去。DB 內容是 aggregated source — NVD、GHSA、各 Linux distro security advisory、language ecosystem advisory（npm / PyPI / Maven / RubyGems / crates.io / Go / etc.）合在一起、所以單一查詢就能跨多生態。</p>
<p><strong><code>.trivyignore</code> 跟 <code>.trivyignore.yaml</code></strong>：scan 發現的 CVE 若已評估無風險（無 reachable code path、已有 mitigation、upstream 尚未 patch 但業務不受影響）寫進 <code>.trivyignore</code>（純 CVE-ID list）或 <code>.trivyignore.yaml</code>（含 <code>expired_at</code> + <code>comment</code> + <code>paths</code>、更適合治理）。後者強制每筆 ignore 有 expiration（建議 quarterly）跟 reason、過期自動失效、避免 ignore list 變成「忘了清的死帳」。CI 應該每季跑 <code>trivy --ignorefile .trivyignore.yaml</code> 同時 alert 即將過期的條目。</p>
<p><strong>Severity gate 是 CI 必設</strong>：Trivy 預設 scan 完 print 結果但 exit 0、CI build 不會 fail。要在 CI 真正擋下高風險 PR、必須 <code>trivy image --exit-code 1 --severity HIGH,CRITICAL $IMAGE</code>。Severity 級別（UNKNOWN / LOW / MEDIUM / HIGH / CRITICAL）對應 CVSS score、團隊需要決定 <em>什麼 severity 算 release blocker</em>。常見 baseline：CRITICAL fail PR build、HIGH fail nightly build（給 24 小時修補窗口）、MEDIUM 進 backlog ticket。</p>
<p><strong>SBOM 生成與 scan</strong>：<code>trivy image --format cyclonedx --output sbom.json $IMAGE</code> 生 CycloneDX 格式 SBOM、<code>--format spdx-json</code> 生 SPDX。也可以反向 — 拿別人生的 SBOM 餵給 Trivy：<code>trivy sbom sbom.json</code> 跑 vuln scan、不重新解析 image。這個 workflow 跟 <a href="/blog/backend/07-security-data-protection/vendors/syft-grype/" data-link-title="Syft &#43; Grype" data-link-desc="Anchore 開源姐妹工具：Syft 產 SBOM (CycloneDX / SPDX) &#43; Grype scan 漏洞、Unix philosophy、cosign attestation 整合">Syft + Grype</a> 重疊（Syft 生 SBOM + Grype scan SBOM）、差別是 Trivy 一站完成、Syft+Grype 拆兩階段更模組化。SBOM artifact 進 OCI registry（用 cosign attach）或 SBOM repository（如 Dependency-Track）做長期追蹤。</p>
<p><strong>Misconfig + Secret + License 一起 scan</strong>：<code>trivy fs .</code> 預設啟用四類 scanner — vuln（package CVE）、misconfig（IaC 配置錯誤）、secret（hardcoded credential）、license（license compliance）。Misconfig 內建 hundreds of built-in policy（Rego 寫的）涵蓋 K8s / Terraform / Docker / CloudFormation 常見錯誤（privileged container / open S3 bucket / 0.0.0.0/0 ingress）。Secret scanner 用 regex pattern 找 AWS access key / GCP service account / Stripe key 等常見格式、不是萬能、但 dev pre-commit 攔截已洩漏 secret 很實用。</p>
<p><strong>Trivy Operator（K8s in-cluster scanner）</strong>：K8s 場景的標準配置。Operator 在 cluster 跑、定期 scan 所有 namespace 的 workload、產 CRD reports：<code>VulnerabilityReport</code>（image CVE）、<code>ConfigAuditReport</code>（manifest 配置）、<code>SbomReport</code>、<code>ClusterComplianceReport</code>（CIS Kubernetes Benchmark / NSA Kubernetes Hardening Guide）。Operator 可選配 ValidatingAdmissionWebhook、admission 階段拒絕高風險 image（CVE severity 超門檻）。Reports 是 CRD、可以走 <code>kubectl get vulnerabilityreport</code> 看、也可以 prometheus exporter 出 metric 進 Grafana。</p>
<p><strong>Aqua Platform 整合</strong>：Trivy CLI / Operator 結果可以推到 Aqua Platform（商業版）做集中 dashboard、跨 cluster RBAC、policy engine、compliance report、runtime defense（runtime container 監控）。純 CLI 用戶不需要、但企業有多 cluster + 跨團隊 governance 需求時、Aqua Platform 補 server-side aggregation 那塊（對應 Snyk dashboard 的功能）。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Trivy</th>
          <th>Snyk</th>
          <th>Syft + Grype</th>
          <th>GitHub Advanced Security</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>部署模型</td>
          <td>CLI-only、零 server</td>
          <td>SaaS-first、需要 Snyk account</td>
          <td>CLI-only、兩個 binary</td>
          <td>綁 GitHub、整合在 PR / Code Scanning</td>
      </tr>
      <tr>
          <td>授權</td>
          <td>Apache 2.0、完全免費</td>
          <td>商業 SaaS（Free tier + 付費 plan）</td>
          <td>Apache 2.0、完全免費</td>
          <td>GitHub Enterprise add-on</td>
      </tr>
      <tr>
          <td>Scan target</td>
          <td>image / fs / repo / k8s / config</td>
          <td>image / SCA / IaC / Code (SAST) / Container</td>
          <td>image / fs（SBOM-first）</td>
          <td>SAST (CodeQL) + Dependabot + Secret scanning</td>
      </tr>
      <tr>
          <td>Vulnerability DB</td>
          <td>Trivy DB（OCI artifact、6h cadence、可 mirror）</td>
          <td>Snyk Intel（私有、含 reachability data）</td>
          <td>Grype DB（GitHub-hosted、可 mirror）</td>
          <td>GitHub Advisory DB</td>
      </tr>
      <tr>
          <td>Reachability</td>
          <td>無</td>
          <td>有（Snyk Code reachability）</td>
          <td>無</td>
          <td>部分（CodeQL data flow）</td>
      </tr>
      <tr>
          <td>SBOM 支援</td>
          <td>生 + scan（CycloneDX / SPDX）</td>
          <td>生（Snyk SBOM）</td>
          <td>Syft 生、Grype scan、最完整 SBOM workflow</td>
          <td>部分（Dependency Graph）</td>
      </tr>
      <tr>
          <td>K8s in-cluster</td>
          <td>Trivy Operator（CRD reports + admission）</td>
          <td>Snyk Kubernetes（agent-based）</td>
          <td>無原生、靠外部 wrapper</td>
          <td>無</td>
      </tr>
      <tr>
          <td>跨 repo 報表</td>
          <td>Trivy 本身無、Aqua Platform 補</td>
          <td>Snyk dashboard（強項）</td>
          <td>無原生、靠外部</td>
          <td>GitHub Security tab（綁 GitHub）</td>
      </tr>
      <tr>
          <td>Air-gapped 支援</td>
          <td>強 — DB 可 mirror 到內部 registry</td>
          <td>弱 — 需要 Snyk SaaS（Snyk On-Prem 商業版另算）</td>
          <td>強 — DB 可 mirror</td>
          <td>弱 — 綁 GitHub.com</td>
      </tr>
      <tr>
          <td>學習曲線</td>
          <td>低 — 一個 CLI + 通用 flag</td>
          <td>低 — UI 友善、CLI 也順</td>
          <td>中 — 兩個工具拼、SBOM 概念要懂</td>
          <td>中 — CodeQL query 寫 / 調有門檻</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>CI image scan、K8s scan、air-gapped、OSS-only 預算</td>
          <td>跨 SCM 跨 repo 集中治理、SaaS 預算 OK、需 reachability</td>
          <td>SBOM 為主軸的 supply chain、多 vendor 互通</td>
          <td>GitHub-only + 需要 SAST 深度</td>
      </tr>
  </tbody>
</table>
<p>選 Trivy 的核心訴求：<em>零 server / OSS-only 預算 / air-gapped 友善 / 一個 CLI 涵蓋 container + IaC + secret</em>。需要跨 SCM 集中 dashboard 跟 reachability 走 Snyk；純 SBOM workflow + 多工具互通走 Syft+Grype；GitHub-only + 重 SAST 走 GHAS。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Trivy Operator + admission control</strong>：Operator 跑 ValidatingAdmissionWebhook、admission 階段對 Pod spec 的 image 跑 vuln check、超門檻就拒絕創建。對應 <a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">supply chain integrity</a> 的 <em>artifact gate at deploy time</em>。組態要小心 — webhook timeout / Trivy DB 不可用 / Operator 自己 down 都會擋住 deploy、production 通常 fail-open（DB 不可用時放行 + alert）而非 fail-close。</p>
<p><strong>Custom check（Rego policy）</strong>：Trivy misconfig scanner 用 Rego 寫 policy、可以自己加 custom check（例：禁止特定 namespace 用 hostPath volume、禁止特定 IAM action）。policy 走 <code>--policy ./custom-policies/</code> 載入、跟內建 policy 一起跑。比 OPA Gatekeeper 簡單（不需要部署 admission webhook、scan-time 就執行）、但 runtime enforcement 還是要靠 Gatekeeper / Kyverno。</p>
<p><strong>Air-gapped DB sync</strong>：金融 / 政府 / 工控環境 CI runner 不能連外網。流程是：有對外網的 staging machine 跑 <code>trivy --download-db-only</code> 把 OCI artifact 拉下來、用 <code>skopeo copy</code> 推到內部 OCI registry、CI runner 用 <code>--db-repository internal.registry/trivy-db --skip-db-update</code>（或排程從內部 mirror pull）。DB 更新節奏要排程化（每天 / 每 6 小時）、否則 air-gapped DB 落後幾天會 miss 掉新公布 CVE。</p>
<p><strong>Cosign + SLSA + Trivy 三件事</strong>：Trivy 看的是 <em>known CVE</em>、看不到 <em>build-time backdoor</em>。配套需要 Sigstore cosign 做 image signature verify（確認 image 真的是自家 CI 出的）+ SLSA provenance（build pipeline 不可篡改紀錄）+ Trivy scan（known CVE）三件事一起、才是完整 supply chain trust chain。對應 <a href="/blog/backend/07-security-data-protection/vendors/cert-manager/" data-link-title="cert-manager" data-link-desc="K8s 原生 certificate lifecycle automation、支援 Let&#39;s Encrypt / Vault PKI / Venafi 等多 issuer、auto-renewal &#43; Challenge solver">Cert-manager</a> 在 TLS 的角色、Trivy 在 supply chain 的角色是 <em>已知漏洞檢測</em>、不是 <em>trust establishment</em>。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>CI 顯示 scan 完但 build 沒 fail</strong>：忘了 <code>--exit-code 1 --severity HIGH,CRITICAL</code>、scan 結果只在 log、PR 一直 merge 進高風險 image — 補 severity gate flag、設 baseline</li>
<li><strong>Trivy DB 拉不下來 / 過期</strong>：CI runner 沒對外網 / GitHub Container Registry 被擋 / DB cache 太舊 — 設內部 OCI mirror、CI runner <code>--db-repository</code> 指過去、排程 update</li>
<li><strong><code>.trivyignore</code> 無限膨脹</strong>：用純 list 沒 expiration、團隊找不到誰加的 / 為什麼加 — 改 <code>.trivyignore.yaml</code> 強制 reason + expiration、quarterly review 排進 sprint</li>
<li><strong>false positive 多到 alert fatigue</strong>：base image 自帶大量未修補 OS package、scan 出 50+ HIGH — 換 distroless / Chainguard / Wolfi 等 <em>minimal base image</em>、或 multi-stage build 只保留必要 binary、不是調高門檻當沒看到</li>
<li><strong>secret scanner 漏報</strong>：hardcoded credential 是非標準格式（內部 token、特殊 vendor key）— 加 custom secret pattern、或配合 dedicated tool（Gitleaks / GitGuardian）做第二道</li>
<li><strong>Trivy Operator 報表沒人看</strong>：reports 是 CRD、<code>kubectl get</code> 才看到、PR / Slack 沒通知 — 接 prometheus exporter + Grafana alert、或 webhook 推 Slack</li>
<li><strong>K8s admission webhook fail 擋住 deploy</strong>：Operator down / DB 不可用、所有 Pod 創建被拒 — webhook 配 <code>failurePolicy: Ignore</code>、production 通常 fail-open + alert、不是 fail-close</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>需 reachability / 跨 SCM dashboard</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk</a></td>
      </tr>
      <tr>
          <td>SBOM-first / 多工具互通</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/syft-grype/" data-link-title="Syft &#43; Grype" data-link-desc="Anchore 開源姐妹工具：Syft 產 SBOM (CycloneDX / SPDX) &#43; Grype scan 漏洞、Unix philosophy、cosign attestation 整合">Syft + Grype</a></td>
      </tr>
      <tr>
          <td>SAST 深度 / GitHub-only</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GitHub Advanced Security</a>（CodeQL）</td>
      </tr>
      <tr>
          <td>純依賴升級自動化</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/dependabot/" data-link-title="Dependabot" data-link-desc="GitHub 原生依賴更新自動化、Version Update &#43; Security Update &#43; Alerts、Grouped Updates 減 PR noise、Auto-merge 配 branch protection">Dependabot</a></td>
      </tr>
      <tr>
          <td>Runtime container monitoring</td>
          <td>Falco / Cilium Tetragon / Aqua Runtime（商業版）</td>
      </tr>
      <tr>
          <td>TLS / mTLS cert lifecycle</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/cert-manager/" data-link-title="cert-manager" data-link-desc="K8s 原生 certificate lifecycle automation、支援 Let&#39;s Encrypt / Vault PKI / Venafi 等多 issuer、auto-renewal &#43; Challenge solver">cert-manager</a></td>
      </tr>
      <tr>
          <td>Image signing / provenance</td>
          <td>Sigstore cosign + SLSA framework</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Trivy CLI 所有 flag 跟 output format 完整 reference</li>
<li>Rego policy language 完整語法（OPA / Rego 自有體系）</li>
<li>Aqua Platform 商業版完整功能矩陣（dashboard / RBAC / runtime defense）</li>
<li>各 PCI DSS / SOC 2 / FedRAMP 合規 mapping</li>
<li>跟其他 scanner（Clair / Anchore Enterprise / Twistlock）的逐項比較</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>Trivy 在 07 案例庫沒有 <em>直接 vendor-level 事件</em>（Trivy 本身 OSS、無 vendor-side 控制面風險）、但 supply chain 案例都對應 Trivy 的能力與邊界：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 Trivy 的關係</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/log4shell-cve-2021-44228-component-chain/" data-link-title="7.R7.2.7 Log4Shell 2021：共用元件風險與修補鏈" data-link-desc="共用元件漏洞如何同步影響多服務，並迫使團隊建立依賴治理 workflow">Log4Shell CVE-2021-44228</a></td>
          <td>對照啟示 — CVE 公開後 Trivy DB 幾小時內更新、scan container image 找受影響 service 是緊急 response 主軸；air-gapped 環境 DB mirror 更新節奏直接決定窗口期長度</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/solarwinds-2020-sunburst/" data-link-title="7.R7.2.1 SolarWinds 2020：更新鏈被濫用" data-link-desc="合法更新流程遭植入後，攻擊者如何長期潛伏與橫向擴散">SolarWinds 2020 Sunburst</a></td>
          <td>對照啟示 — Trivy scan known CVE、看不到 build-time backdoor 植入；必須配合 image signing（cosign）+ SLSA provenance 才完整</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/3cx-2023-desktopapp-supply-chain/" data-link-title="7.R7.2.8 3CX 2023：桌面軟體更新鏈攻擊" data-link-desc="合法更新流程被植入後，桌面端供應鏈事件如何傳到企業端點">3CX 2023 Desktop App Supply Chain</a></td>
          <td>對照啟示 — container scan 看 image layer 內 known CVE、看不到 runtime callback / dynamic load；需配合 runtime monitoring（Falco / Tetragon）</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/xz-backdoor-2024-open-source-supply-chain/" data-link-title="7.R7.2.4 XZ Backdoor 2024：開源供應鏈長期滲透" data-link-desc="開源維護鏈遭滲透後，為何會直接影響廣泛 Linux 發行流程">XZ Backdoor 2024</a></td>
          <td>對照啟示 — Trivy 比對 package name + version 對應 CVE、看不到 maintainer takeover；mitigation 走 SBOM provenance + maintainer trust baseline</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">7.12 供應鏈完整性與 Artifact 信任</a></td>
          <td>章節原則 — Trivy 是 <em>known CVE 檢測</em>、SBOM + signing + provenance 三件事一起才形成完整 trust chain</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">7.12 供應鏈完整性與 Artifact 信任</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk</a>、<a href="/blog/backend/07-security-data-protection/vendors/syft-grype/" data-link-title="Syft &#43; Grype" data-link-desc="Anchore 開源姐妹工具：Syft 產 SBOM (CycloneDX / SPDX) &#43; Grype scan 漏洞、Unix philosophy、cosign attestation 整合">Syft + Grype</a>、<a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GitHub Advanced Security</a>、<a href="/blog/backend/07-security-data-protection/vendors/dependabot/" data-link-title="Dependabot" data-link-desc="GitHub 原生依賴更新自動化、Version Update &#43; Security Update &#43; Alerts、Grouped Updates 減 PR noise、Auto-merge 配 branch protection">Dependabot</a></li>
<li>下游：<a href="/blog/backend/07-security-data-protection/entrypoint-and-server-protection/" data-link-title="7.3 入口治理與伺服器防護" data-link-desc="以問題驅動方式整理對外入口、管理平面與伺服器邊界">7.3 入口治理與伺服器防護</a>（image 漏洞最終影響的是 origin server 風險面）</li>
<li>跨類：<a href="/blog/backend/07-security-data-protection/vendors/cert-manager/" data-link-title="cert-manager" data-link-desc="K8s 原生 certificate lifecycle automation、支援 Let&#39;s Encrypt / Vault PKI / Venafi 等多 issuer、auto-renewal &#43; Challenge solver">cert-manager</a>（TLS lifecycle）、<a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a>（secret rotation 對應 Trivy secret scan 找到的 hardcoded credential）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（CVE 緊急 response 流程 / 高風險 image rollback）</li>
<li>官方：<a href="https://aquasecurity.github.io/trivy/">Trivy Documentation</a>、<a href="https://aquasecurity.github.io/trivy-operator/">Trivy Operator</a></li>
</ul>
]]></content:encoded></item><item><title>AWS Aurora</title><link>https://tarrragon.github.io/blog/backend/01-database/vendors/aurora/</link><pubDate>Wed, 13 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/01-database/vendors/aurora/</guid><description>&lt;p>Aurora 是 AWS managed PostgreSQL / MySQL、把 storage layer 重寫成跨 AZ 分散式 log service、保留 wire protocol 相容。Netflix 把多套 RDBMS 統一到 Aurora（+75% 效能、-28% 成本）、DraftKings 撐每分鐘 100 萬 ops 體育博彩、Standard Chartered 跨 7 個受監管市場、FanDuel 處理 Super Bowl 5-10 倍峰值 — 是 SQL OLTP managed 服務的代表。&lt;/p>
&lt;h2 id="教學路線managed-sql-與平台責任轉移">教學路線：Managed SQL 與平台責任轉移&lt;/h2>
&lt;p>Aurora 服務頁的教學目標是把 PostgreSQL / MySQL 語意延伸到 AWS managed storage / compute 分離模型。讀者讀完後要能判斷哪些責任交給 Aurora，哪些責任仍留在 schema、query、maintenance window、region 與成本治理。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>學習段&lt;/th>
 &lt;th>核心問題&lt;/th>
 &lt;th>對應段落&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Managed SQL&lt;/td>
 &lt;td>Aurora 如何保留 PostgreSQL / MySQL 語意並改變操作責任&lt;/td>
 &lt;td>定位、適用場景&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Storage / compute&lt;/td>
 &lt;td>分離 storage layer 如何影響 replica、failover、backup&lt;/td>
 &lt;td>容量規劃要點、案例對照&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>AWS operation model&lt;/td>
 &lt;td>parameter group、maintenance、region、cost 如何成為平台責任&lt;/td>
 &lt;td>跟其他 vendor 的取捨、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rto/" data-link-title="RTO" data-link-desc="說明恢復時間目標如何約束事故回復策略">RTO&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rpo/" data-link-title="RPO" data-link-desc="說明恢復點目標如何定義可接受資料損失範圍">RPO&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Peak workload&lt;/td>
 &lt;td>金融、串流、Super Bowl、banking case 如何提供容量判準&lt;/td>
 &lt;td>適用場景、案例對照&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>替代路由&lt;/td>
 &lt;td>何時留 RDS、自管 PostgreSQL / MySQL、轉 Spanner 或 DynamoDB&lt;/td>
 &lt;td>不適用場景、下一步路由&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="定位storage--compute-分離的-sql">定位：storage / compute 分離的 SQL&lt;/h2>
&lt;p>Aurora 跟傳統 PostgreSQL / MySQL primary 最大差異是 &lt;em>storage layer 重寫&lt;/em>。傳統 SQL primary 把 storage 跟 CPU / RAM 綁定、storage 擴容要換 instance、replication lag 受 compute 影響。Aurora 把 storage 拉到分散式 log service、跨 6 個 storage node（3 AZ × 2 node）、storage 跟 compute 獨立擴。&lt;/p>
&lt;p>&lt;strong>容量特性&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>單一 cluster 最高 storage：128 TB&lt;/li>
&lt;li>最多 15 個 read replica（單 region 內）&lt;/li>
&lt;li>read replica replication lag：10-30ms（vs 傳統 PostgreSQL 跨 AZ 可能秒級）&lt;/li>
&lt;li>跨 AZ failover：&amp;lt; 30 秒（promote read replica）&lt;/li>
&lt;li>Aurora Global Database 跨 region replication：&amp;lt; 1 秒典型 lag&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>為什麼這個分離很重要&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>傳統 PostgreSQL primary 上的 read replica 都靠 logical replication、會跟著 primary write load 走慢&lt;/li>
&lt;li>Aurora storage 直接複製到 6 個 storage node、read replica 從 storage 讀、不靠 primary&lt;/li>
&lt;li>→ read replica 大幅減少 lag、可以撐更多 OLTP read traffic&lt;/li>
&lt;li>對應 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/netflix-aurora-consolidation/" data-link-title="9.C23 Netflix：把關聯式 DB 統一到 Aurora、效能 &amp;#43;75%、成本 -28%" data-link-desc="Netflix 把多套關聯式 DB 統一到 Aurora、效能提升 75%、成本下降 28%、串流數十億小時">9.C23 Netflix&lt;/a> +75% 效能改善的關鍵原因&lt;/li>
&lt;/ul>
&lt;h2 id="適用場景">適用場景&lt;/h2>
&lt;p>按公開 case 提煉的典型適用場景：&lt;/p></description><content:encoded><![CDATA[<p>Aurora 是 AWS managed PostgreSQL / MySQL、把 storage layer 重寫成跨 AZ 分散式 log service、保留 wire protocol 相容。Netflix 把多套 RDBMS 統一到 Aurora（+75% 效能、-28% 成本）、DraftKings 撐每分鐘 100 萬 ops 體育博彩、Standard Chartered 跨 7 個受監管市場、FanDuel 處理 Super Bowl 5-10 倍峰值 — 是 SQL OLTP managed 服務的代表。</p>
<h2 id="教學路線managed-sql-與平台責任轉移">教學路線：Managed SQL 與平台責任轉移</h2>
<p>Aurora 服務頁的教學目標是把 PostgreSQL / MySQL 語意延伸到 AWS managed storage / compute 分離模型。讀者讀完後要能判斷哪些責任交給 Aurora，哪些責任仍留在 schema、query、maintenance window、region 與成本治理。</p>
<table>
  <thead>
      <tr>
          <th>學習段</th>
          <th>核心問題</th>
          <th>對應段落</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Managed SQL</td>
          <td>Aurora 如何保留 PostgreSQL / MySQL 語意並改變操作責任</td>
          <td>定位、適用場景</td>
      </tr>
      <tr>
          <td>Storage / compute</td>
          <td>分離 storage layer 如何影響 replica、failover、backup</td>
          <td>容量規劃要點、案例對照</td>
      </tr>
      <tr>
          <td>AWS operation model</td>
          <td>parameter group、maintenance、region、cost 如何成為平台責任</td>
          <td>跟其他 vendor 的取捨、<a href="/blog/backend/knowledge-cards/rto/" data-link-title="RTO" data-link-desc="說明恢復時間目標如何約束事故回復策略">RTO</a> / <a href="/blog/backend/knowledge-cards/rpo/" data-link-title="RPO" data-link-desc="說明恢復點目標如何定義可接受資料損失範圍">RPO</a></td>
      </tr>
      <tr>
          <td>Peak workload</td>
          <td>金融、串流、Super Bowl、banking case 如何提供容量判準</td>
          <td>適用場景、案例對照</td>
      </tr>
      <tr>
          <td>替代路由</td>
          <td>何時留 RDS、自管 PostgreSQL / MySQL、轉 Spanner 或 DynamoDB</td>
          <td>不適用場景、下一步路由</td>
      </tr>
  </tbody>
</table>
<h2 id="定位storage--compute-分離的-sql">定位：storage / compute 分離的 SQL</h2>
<p>Aurora 跟傳統 PostgreSQL / MySQL primary 最大差異是 <em>storage layer 重寫</em>。傳統 SQL primary 把 storage 跟 CPU / RAM 綁定、storage 擴容要換 instance、replication lag 受 compute 影響。Aurora 把 storage 拉到分散式 log service、跨 6 個 storage node（3 AZ × 2 node）、storage 跟 compute 獨立擴。</p>
<p><strong>容量特性</strong>：</p>
<ul>
<li>單一 cluster 最高 storage：128 TB</li>
<li>最多 15 個 read replica（單 region 內）</li>
<li>read replica replication lag：10-30ms（vs 傳統 PostgreSQL 跨 AZ 可能秒級）</li>
<li>跨 AZ failover：&lt; 30 秒（promote read replica）</li>
<li>Aurora Global Database 跨 region replication：&lt; 1 秒典型 lag</li>
</ul>
<p><strong>為什麼這個分離很重要</strong>：</p>
<ul>
<li>傳統 PostgreSQL primary 上的 read replica 都靠 logical replication、會跟著 primary write load 走慢</li>
<li>Aurora storage 直接複製到 6 個 storage node、read replica 從 storage 讀、不靠 primary</li>
<li>→ read replica 大幅減少 lag、可以撐更多 OLTP read traffic</li>
<li>對應 <a href="/blog/backend/09-performance-capacity/cases/netflix-aurora-consolidation/" data-link-title="9.C23 Netflix：把關聯式 DB 統一到 Aurora、效能 &#43;75%、成本 -28%" data-link-desc="Netflix 把多套關聯式 DB 統一到 Aurora、效能提升 75%、成本下降 28%、串流數十億小時">9.C23 Netflix</a> +75% 效能改善的關鍵原因</li>
</ul>
<h2 id="適用場景">適用場景</h2>
<p>按公開 case 提煉的典型適用場景：</p>
<p><strong>1. 既有 PostgreSQL / MySQL 應用想要 managed</strong>：</p>
<ul>
<li>wire protocol 相容，應用層改動通常集中在連線、參數與操作流程</li>
<li>ORM / driver / SQL 多數可保留，但 migration plan 仍要驗證 dialect 與 extension</li>
<li>對應案例：<a href="/blog/backend/09-performance-capacity/cases/netflix-aurora-consolidation/" data-link-title="9.C23 Netflix：把關聯式 DB 統一到 Aurora、效能 &#43;75%、成本 -28%" data-link-desc="Netflix 把多套關聯式 DB 統一到 Aurora、效能提升 75%、成本下降 28%、串流數十億小時">9.C23 Netflix</a> — 多套 RDBMS（PostgreSQL、MySQL、Oracle）統一到 Aurora、+75% 效能、-28% 成本</li>
</ul>
<p><strong>2. 金融交易 / 體育博彩 OLTP</strong>：</p>
<ul>
<li>強 ACID transaction</li>
<li>多 read replica 處理 query traffic、不影響寫</li>
<li>對應案例：<a href="/blog/backend/09-performance-capacity/cases/draftkings-aurora-financial-ledger/" data-link-title="9.C4 DraftKings：Aurora 撐 100 萬 ops/min 的體育博彩金融帳本" data-link-desc="DraftKings 用 Aurora MySQL 跑體育博彩金融帳本、Super Bowl 流量 &#43;50% 不影響延遲">9.C4 DraftKings</a> — 每分鐘 100 萬 ops、200 個獨立資料庫、Super Bowl 流量 +50% 無影響</li>
</ul>
<p><strong>3. 受監管產業跨市場部署</strong>：</p>
<ul>
<li>每個市場一個獨立 cluster、合規分割</li>
<li>對應案例：<a href="/blog/backend/09-performance-capacity/cases/standard-chartered-aurora-banking/" data-link-title="9.C14 Standard Chartered：受監管銀行的 Aurora 4000 TPS 容量提升" data-link-desc="Standard Chartered 銀行遷移到 Aurora 後吞吐量提升 10 倍至 4000 TPS、跨 7 個受監管市場">9.C14 Standard Chartered</a> — 7 個受監管市場、各自獨立 Aurora、總吞吐 4000 TPS、10x 提升</li>
</ul>
<p><strong>4. 高峰流量 + 多 read replica 擴容</strong>：</p>
<ul>
<li>read 高峰用 read replica 接、write 走 primary</li>
<li>對應案例：<a href="/blog/backend/09-performance-capacity/cases/fanduel-dual-peak-betting-streaming/" data-link-title="9.C28 FanDuel：體育直播 &#43; 投注的雙重峰值" data-link-desc="FanDuel 3.5M MAU、Super Bowl 期間擴容 5-10 倍、用 AWS Local Zones &#43; Wavelength &#43; Outposts 處理 20&#43; 州的雙重峰值">9.C28 FanDuel</a> — 5-10x Super Bowl 峰值、直播 + 投注雙工作負載</li>
</ul>
<p><strong>5. Aurora Serverless v2 適用場景</strong>：</p>
<ul>
<li>流量 unpredictable + sustained workload</li>
<li>自動 scale CPU / RAM，降低 instance class 管理負擔</li>
<li>適合：dev / test 環境、流量稀疏的多 tenant SaaS</li>
</ul>
<p><strong>6. Aurora Global Database</strong>：</p>
<ul>
<li>跨 region async replication（&lt; 1 秒 typical）</li>
<li>DR + 跨地理 read（write 在 primary region、read 可從 secondary region）</li>
<li>Global Database 是跨 region DR / read route，multi-region active-active write 要改看 Aurora DSQL</li>
</ul>
<h2 id="不適用場景">不適用場景</h2>
<p><strong>1. 跨雲需求</strong>：</p>
<ul>
<li>Aurora 是 AWS-only、wire protocol 相容但 storage 是 AWS 專屬</li>
<li>替代：自管 PostgreSQL / MySQL on Kubernetes</li>
</ul>
<p><strong>2. 需要最新 upstream PostgreSQL / MySQL 特性</strong>：</p>
<ul>
<li>Aurora 通常落後 upstream 1-2 個 major version</li>
<li>替代：RDS PostgreSQL（更接近 upstream）</li>
</ul>
<p><strong>3. 極端寫入吞吐</strong>：</p>
<ul>
<li>單一 primary 寫入受 storage 設計限制（雖然比 PostgreSQL 快）</li>
<li>
<blockquote>
<p>100K WPS 級別、考慮 sharding、CockroachDB、或 DynamoDB</p></blockquote>
</li>
<li>對應 <a href="/blog/backend/09-performance-capacity/cases/ntt-docomo-lemino-japanese-streaming/" data-link-title="9.C29 NTT DOCOMO Lemino：3 個月達 500 萬 MAU 的串流後端" data-link-desc="Lemino 用 DynamoDB &#43; AWS Media Services 撐 30 channels live &#43; 5M MAU、工程工時下降 90%">9.C29 Lemino</a> — RDB connection limit 是 bottleneck、改 DynamoDB</li>
</ul>
<p><strong>4. 全球 multi-region active-active write</strong>：</p>
<ul>
<li>Aurora Global Database 是 async、有 lag，write 仍集中在 primary region</li>
<li>替代：Aurora DSQL（2024 推出）、Spanner、Cosmos DB</li>
</ul>
<p><strong>5. 預算敏感的小 workload</strong>：</p>
<ul>
<li>Aurora 比 self-managed PostgreSQL 貴 20-30%</li>
<li>小流量場景、自管 PostgreSQL on EC2 或 RDS 更便宜</li>
</ul>
<h2 id="跟其他-vendor-的取捨">跟其他 vendor 的取捨</h2>
<p><strong>vs RDS PostgreSQL / MySQL（同 AWS）</strong>：</p>
<ul>
<li>Aurora：storage / compute 分離、更多 read replica、更快 failover、跨 AZ 自動 replication</li>
<li>RDS：純 managed PostgreSQL / MySQL、不重寫 storage、更接近 upstream</li>
<li>選 Aurora：需要 scale read replica 或 cross-AZ failover &lt; 30 秒</li>
<li>選 RDS：需要最新 upstream 特性、預算更敏感</li>
</ul>
<p><strong>vs 自管 PostgreSQL / MySQL</strong>：</p>
<ul>
<li>Aurora：託管、自動 backup / failover，降低日常 database operation</li>
<li>自管：彈性高、可自己 tuning、跨雲可用、預算可控</li>
<li>選 Aurora：團隊想把 DBA / SRE 操作責任轉交 AWS、AWS 生態深</li>
<li>選自管：跨雲需求、需要客製化、預算極敏感</li>
</ul>
<p><strong>vs CockroachDB</strong>：</p>
<ul>
<li>Aurora：single-region scaling（一個 region 內擴）、AWS-only</li>
<li>CockroachDB：multi-region 強一致、跨雲可用、PostgreSQL wire protocol</li>
<li>選 Aurora：AWS-only + single-region OLTP</li>
<li>選 CockroachDB：需要 multi-region 強一致 + 跨雲 / on-prem 彈性</li>
</ul>
<p><strong>vs Aurora DSQL（2024-12 preview / 2025-05 GA）</strong>：</p>
<ul>
<li>Aurora：single-region scaling、傳統 OLTP</li>
<li>Aurora DSQL：multi-region active-active write、serverless、強一致</li>
<li>選 Aurora：流量集中在一個 region</li>
<li>選 Aurora DSQL：需要全球 active-active</li>
<li>從 PG / Aurora PG 遷 DSQL 的完整 playbook 見 <a href="/blog/backend/01-database/vendors/postgresql/migrate-to-aurora-dsql/" data-link-title="PostgreSQL → Aurora DSQL Migration：PG wire-compatible Distributed SQL 的 Paradigm Shift" data-link-desc="Aurora DSQL（2024-12 re:Invent preview / 2025-05 GA）是 AWS 推的 PG wire-compatible *active-active distributed SQL*、跟 self-managed PG / Aurora PG 不同 paradigm（OCC &#43; snapshot isolation &#43; multi-region strong consistency）。Migration 結構是 *protocol drop-in &#43; paradigm shift*：app SQL 不太改、但 transaction retry / extension 缺位 / 多 region 一致性需重設計。本文走 DSQL vs Aurora PG vs self-managed PG 三軸對比、為什麼遷的三條 driver（global write / operational zero-touch / region resiliency）、Type E phased plan、5 production 踩雷（transaction retry 沒處理 / extension 缺位 / sequence throughput 限制 / Aurora PG 直升 DSQL 不可行 / region failover semantic）、跟 PG → Aurora 跟 PG → CockroachDB 對比">PG → Aurora DSQL Migration</a></li>
</ul>
<p><strong>vs DynamoDB</strong>：</p>
<ul>
<li>詳見 <a href="/blog/backend/01-database/vendors/dynamodb/" data-link-title="DynamoDB" data-link-desc="AWS managed key-value、partition-based scaling、9000 萬 RPS sustained 實戰證據">DynamoDB vendor page</a> 對比段。Aurora 是 SQL、DynamoDB 是 KV、適用場景不同。</li>
</ul>
<p><strong>vs Azure SQL Hyperscale</strong>：</p>
<ul>
<li>設計理念類似（storage / compute 分離）</li>
<li>Aurora 在 AWS、Hyperscale 在 Azure</li>
<li>對應案例：<a href="/blog/backend/09-performance-capacity/cases/clearent-azure-sql-hyperscale-payments/" data-link-title="9.C32 Clearent：Azure SQL Hyperscale 撐每年 5 億筆支付交易" data-link-desc="Clearent 在 Azure SQL Hyperscale 上處理每年 5 億筆支付交易、autoscale &#43; 微服務架構">9.C32 Clearent</a> — Azure 生態的同類設計、5 億 payment txn / 年</li>
</ul>
<h2 id="容量規劃要點">容量規劃要點</h2>
<p>從 09 案例庫提煉的 Aurora 容量規劃實踐：</p>
<p><strong>1. read replica 是擴 read traffic 的主要工具</strong>：</p>
<ul>
<li>最多 15 個 read replica、replication lag 10-30ms</li>
<li>read replica autoscaler 按 CPU / connection 自動加減</li>
<li>對應 <a href="/blog/backend/09-performance-capacity/cases/draftkings-aurora-financial-ledger/" data-link-title="9.C4 DraftKings：Aurora 撐 100 萬 ops/min 的體育博彩金融帳本" data-link-desc="DraftKings 用 Aurora MySQL 跑體育博彩金融帳本、Super Bowl 流量 &#43;50% 不影響延遲">9.C4 DraftKings</a> 用多個 read replica 處理「比賽期間用戶查 balance」流量</li>
</ul>
<p><strong>2. 200 個獨立 cluster 模式</strong>：</p>
<ul>
<li>Aurora 的實務設計通常用多個 bounded cluster 控制 blast radius</li>
<li>按業務切多個小 cluster（<a href="/blog/backend/09-performance-capacity/cases/draftkings-aurora-financial-ledger/" data-link-title="9.C4 DraftKings：Aurora 撐 100 萬 ops/min 的體育博彩金融帳本" data-link-desc="DraftKings 用 Aurora MySQL 跑體育博彩金融帳本、Super Bowl 流量 &#43;50% 不影響延遲">9.C4 DraftKings</a> 200 個）、降低 <a href="/blog/backend/knowledge-cards/blast-radius/" data-link-title="Blast Radius" data-link-desc="說明事故影響面如何估算與隔離">blast radius</a></li>
<li>對應 microservice 私有 store（<a href="/blog/backend/09-performance-capacity/cases/netflix-aurora-consolidation/" data-link-title="9.C23 Netflix：把關聯式 DB 統一到 Aurora、效能 &#43;75%、成本 -28%" data-link-desc="Netflix 把多套關聯式 DB 統一到 Aurora、效能提升 75%、成本下降 28%、串流數十億小時">9.C23 Netflix</a> 同樣思維）</li>
</ul>
<p><strong>3. Aurora I/O-Optimized</strong>：</p>
<ul>
<li>2023-05 推出的 storage 配置</li>
<li>適合 I/O-heavy workload（write 多、scan 多）</li>
<li>比 standard storage 貴、但少 I/O 收費</li>
<li>對應 <a href="/blog/backend/09-performance-capacity/cases/draftkings-aurora-financial-ledger/" data-link-title="9.C4 DraftKings：Aurora 撐 100 萬 ops/min 的體育博彩金融帳本" data-link-desc="DraftKings 用 Aurora MySQL 跑體育博彩金融帳本、Super Bowl 流量 &#43;50% 不影響延遲">9.C4 DraftKings</a> 用 I/O-Optimized 加速</li>
</ul>
<p><strong>4. Aurora Serverless v2</strong>：</p>
<ul>
<li>ACU（Aurora Capacity Unit）為單位、自動 scale 0.5-128 ACU</li>
<li>適合 dev / test、稀疏 workload、unpredictable burst</li>
<li>不適合：sustained predictable high workload（provisioned 便宜）</li>
</ul>
<p><strong>5. Cross-region Global Database</strong>：</p>
<ul>
<li>&lt; 1 秒 typical replication lag、但是 async</li>
<li>secondary region 可 read，write 仍回 primary region</li>
<li>DR 切換通常 1-2 分鐘</li>
<li>對應 <a href="/blog/backend/09-performance-capacity/cases/standard-chartered-aurora-banking/" data-link-title="9.C14 Standard Chartered：受監管銀行的 Aurora 4000 TPS 容量提升" data-link-desc="Standard Chartered 銀行遷移到 Aurora 後吞吐量提升 10 倍至 4000 TPS、跨 7 個受監管市場">9.C14 Standard Chartered</a> — 跨市場各自獨立 Aurora，合規邊界優先於 Global Database</li>
</ul>
<p><strong>6. Connection pool 仍是隱性限制</strong>：</p>
<ul>
<li>Aurora 跟傳統 PostgreSQL 一樣有 connection pool 上限</li>
<li>應用層 + Aurora 之間建議用 RDS Proxy 做 pool 共享</li>
<li>對應 <a href="/blog/backend/09-performance-capacity/cases/ntt-docomo-lemino-japanese-streaming/" data-link-title="9.C29 NTT DOCOMO Lemino：3 個月達 500 萬 MAU 的串流後端" data-link-desc="Lemino 用 DynamoDB &#43; AWS Media Services 撐 30 channels live &#43; 5M MAU、工程工時下降 90%">9.C29 Lemino</a> — RDB connection limit 是 surge 場景的 bottleneck；Lemino 案例發生在 RDS，但 connection-bound 機制同樣適用 Aurora</li>
</ul>
<h2 id="deep-article已完成">Deep article（已完成）</h2>
<p>本 vendor 現有 deep article 覆蓋 Aurora 從 storage architecture、fleet 治理到容量彈性、連線管理與 distributed 升級門檻的核心 production 議題：</p>
<table>
  <thead>
      <tr>
          <th>主題</th>
          <th>文章</th>
          <th>對應 production 議題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>quorum-based 分散式 log、韌性即性能、6-way replication</td>
          <td><a href="storage-architecture/">storage-architecture</a></td>
          <td>4-of-6 write / 3-of-6 read、DraftKings 6ms 寫 / &lt;1ms 讀 production reference</td>
      </tr>
      <tr>
          <td>Cross-AZ failover lifecycle、&lt; 30 秒 RTO、endpoint routing</td>
          <td><a href="cross-az-failover-rto/">cross-az-failover-rto</a></td>
          <td>application DNS cache + connection pool 對齊、Standard Chartered 受監管獨立 cluster 而非 Global Database failover</td>
      </tr>
      <tr>
          <td>15 replica 上限、lag profile、headroom 預留、fleet 治理 3 條 driver</td>
          <td><a href="read-replica-scaling/">read-replica-scaling</a></td>
          <td>Aurora fleet 治理 SSoT、DraftKings headroom 預留、FanDuel 雙 SLO 並行</td>
      </tr>
      <tr>
          <td>跨 region async replication、&lt; 1 秒 lag、合規 anti-recommendation</td>
          <td><a href="global-database-multi-region/">global-database-multi-region</a></td>
          <td>planned vs unplanned failover RTO、Standard Chartered 合規禁止跨境複製反指標</td>
      </tr>
      <tr>
          <td>從自管 PostgreSQL / MySQL 遷到 Aurora（Type C operational redesign）</td>
          <td><a href="migrate-from-self-managed-pg-mysql/">migrate-from-self-managed-pg-mysql</a></td>
          <td>Standard Chartered 合規 lead time、Netflix 非 all-purpose store 邊界</td>
      </tr>
      <tr>
          <td>ACU 自動擴縮、min/max 設定、混合 cluster、成本 crossover</td>
          <td><a href="serverless-v2-scaling/">serverless-v2-scaling</a></td>
          <td>離峰浪費 vs 尖峰不足、穩定高負載 serverless 反而更貴</td>
      </tr>
      <tr>
          <td>多 cluster 業務切分、blast radius 隔離、fleet 治理</td>
          <td><a href="multi-cluster-business-split/">multi-cluster-business-split</a></td>
          <td>Netflix 微服務私有 store + DB 種類 consolidation 雙重成立</td>
      </tr>
      <tr>
          <td>RDS Proxy connection multiplexing、pinning 陷阱、failover 加速</td>
          <td><a href="rds-proxy-connection-pooling/">rds-proxy-connection-pooling</a></td>
          <td>Lambda 連線風暴、pinning 讓 multiplexing 失效</td>
      </tr>
      <tr>
          <td>standard Aurora vs Aurora DSQL 升級門檻取捨</td>
          <td><a href="aurora-vs-dsql-tradeoff/">aurora-vs-dsql-tradeoff</a></td>
          <td>single-writer 上限 vs active-active distributed、何時跨 paradigm</td>
      </tr>
  </tbody>
</table>
<p>I/O-Optimized vs Standard 成本對比由 <a href="/blog/backend/01-database/vendors/postgresql/aurora-io-optimized-cost/" data-link-title="Aurora PostgreSQL I/O-Optimized Cost" data-link-desc="Aurora PostgreSQL Standard 與 I/O-Optimized 的成本模型、I/O 壓力、workload 判斷、遷移與回退條件">Aurora PostgreSQL I/O-Optimized Cost</a> 主寫（storage I/O 成本模型 SSoT），本 vendor 各篇提到 storage 成本時 cross-link 它、不重複展開。</p>
<p>跨 vendor entry：先看 <a href="../cockroachdb/aurora-dsql-spanner-decision-tree/">CockroachDB vs Aurora DSQL vs Spanner 決策樹</a>（distributed SQL 三選一 + 撞牆訊號分型），再決定是否進 Aurora overview。</p>
<h2 id="後續擴充仍待補">後續擴充（仍待補）</h2>
<ul>
<li>Aurora Global Database write forwarding 深入</li>
<li>Babelfish（SQL Server 相容層）適用判斷</li>
<li>Blue/Green deployment 做 major version 升級</li>
<li>Backup / PITR restore drill（hands-on lab）</li>
</ul>
<h2 id="anti-recommendation-與升級路由">Anti-recommendation 與升級路由</h2>
<p>Aurora 的 managed SQL 能把大量操作責任交給 AWS，但它仍保留 single-primary SQL 的資料模型與交易邊界。這一段先說何時維持 RDS / Aurora，再說何時升級 Global Database、Serverless v2、RDS Proxy、Aurora DSQL 或 DynamoDB。</p>
<table>
  <thead>
      <tr>
          <th>機制 / 路線</th>
          <th>維持簡單設計的條件</th>
          <th>升級訊號</th>
          <th>主要引用路徑</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>RDS PostgreSQL / MySQL</td>
          <td>upstream 相容、成本、版本節奏比 storage 分離更重要</td>
          <td>read replica lag、backup / failover、storage growth 成主題</td>
          <td><a href="/blog/backend/01-database/vendors/postgresql/" data-link-title="PostgreSQL" data-link-desc="多用途 OLTP 主流關聯式資料庫、MVCC、豐富 SQL 特性、是 Aurora / Cosmos DB / Spanner / CockroachDB / Aurora DSQL 的相容目標">PostgreSQL vendor</a>、<a href="/blog/backend/01-database/vendors/mysql/" data-link-title="MySQL" data-link-desc="高併發網路服務常用關聯式資料庫、Vitess / PlanetScale 分片生態、GitHub / Shopify / Facebook 規模驗證">MySQL vendor</a></td>
      </tr>
      <tr>
          <td>Aurora provisioned</td>
          <td>workload sustained、容量可預測、團隊能管理 instance class</td>
          <td>read replica、fast failover、storage autoscale 是主要需求</td>
          <td><a href="/blog/backend/knowledge-cards/replication-lag/" data-link-title="Replication Lag" data-link-desc="說明資料副本落後正式來源多久，以及它如何影響讀取正確性">Replication Lag</a>、<a href="/blog/backend/knowledge-cards/failover/" data-link-title="Failover" data-link-desc="說明主要服務或節點失效時如何切換到備援能力">Failover</a></td>
      </tr>
      <tr>
          <td>Aurora Serverless v2</td>
          <td>sustained workload 已穩定且 provisioned 成本較低</td>
          <td>稀疏 tenant、dev/test、不可預測 burst</td>
          <td><a href="/blog/backend/knowledge-cards/cost-per-request/" data-link-title="Cost Per Request" data-link-desc="把雲端成本拆到單一 API 請求的 unit economics 模型">Cost Per Request</a>、<a href="/blog/backend/knowledge-cards/scheduled-scaling/" data-link-title="Scheduled Scaling" data-link-desc="說明按已知時間表預先擴容的 autoscaler 模式">Scheduled Scaling</a></td>
      </tr>
      <tr>
          <td>RDS Proxy</td>
          <td>application pool 已能控制 backend connection</td>
          <td>Lambda / surge / connection storm 造成 pool 壓力</td>
          <td><a href="/blog/backend/knowledge-cards/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">Connection Pool</a></td>
      </tr>
      <tr>
          <td>Global Database</td>
          <td>single-region DR 已符合 RTO/RPO</td>
          <td>跨 region read、regional DR、低 RPO 是產品需求</td>
          <td><a href="/blog/backend/knowledge-cards/rto/" data-link-title="RTO" data-link-desc="說明恢復時間目標如何約束事故回復策略">RTO</a>、<a href="/blog/backend/knowledge-cards/rpo/" data-link-title="RPO" data-link-desc="說明恢復點目標如何定義可接受資料損失範圍">RPO</a>、<a href="/blog/backend/knowledge-cards/stale-read/" data-link-title="Stale Read" data-link-desc="讀取到落後於最新寫入版本的舊資料">Stale Read</a></td>
      </tr>
      <tr>
          <td>Aurora DSQL / Spanner / CockroachDB</td>
          <td>single-primary write 仍足夠</td>
          <td>multi-region active-active write、global strong consistency</td>
          <td><a href="/blog/backend/01-database/global-distributed-oltp/" data-link-title="1.11 全球分散式 OLTP" data-link-desc="Spanner / Aurora DSQL / Cosmos DB multi-region write / CockroachDB / TiDB 的全球一致性取捨">1.11 全球分散式 OLTP</a></td>
      </tr>
      <tr>
          <td>DynamoDB</td>
          <td>SQL query 與 transaction 仍是主要價值</td>
          <td>access pattern 固定、connection-free surge、KV latency 成主題</td>
          <td><a href="/blog/backend/01-database/vendors/dynamodb/" data-link-title="DynamoDB" data-link-desc="AWS managed key-value、partition-based scaling、9000 萬 RPS sustained 實戰證據">DynamoDB vendor</a></td>
      </tr>
  </tbody>
</table>
<p>Aurora 的簡單路徑是先把 operation transfer 寫清楚。Backup、minor upgrade、storage growth、failover 與 read replica lag 交給平台後，schema design、query shape、transaction boundary、connection pool 與 cost guardrail 仍由 application / SRE 共同承擔。</p>
<p>Global Database 的升級路徑要先定義讀寫方向。它適合 DR 與跨地理 read，若業務需要多 region 同時寫入並保持強一致，應直接進入 Aurora DSQL、Spanner 或 CockroachDB 的 distributed SQL 比較。</p>
<h2 id="已知-limitation-與後續路由">已知 limitation 與後續路由</h2>
<p>Aurora overview 目前完成 managed SQL 判斷。下一輪 deep article / playbook 應補 storage architecture、RDS Proxy、Global Database、Serverless v2、I/O-Optimized cost、PostgreSQL / MySQL → Aurora migration 與 Aurora → Aurora DSQL 的分歧路徑。</p>
<h2 id="案例對照">案例對照</h2>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>規模</th>
          <th>教學重點</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/cases/draftkings-aurora-financial-ledger/" data-link-title="9.C4 DraftKings：Aurora 撐 100 萬 ops/min 的體育博彩金融帳本" data-link-desc="DraftKings 用 Aurora MySQL 跑體育博彩金融帳本、Super Bowl 流量 &#43;50% 不影響延遲">9.C4 DraftKings</a></td>
          <td>1M ops/min、&lt;1ms reads、6ms writes、200 個 DB</td>
          <td>體育博彩金融帳本、按業務切 cluster</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/cases/standard-chartered-aurora-banking/" data-link-title="9.C14 Standard Chartered：受監管銀行的 Aurora 4000 TPS 容量提升" data-link-desc="Standard Chartered 銀行遷移到 Aurora 後吞吐量提升 10 倍至 4000 TPS、跨 7 個受監管市場">9.C14 Standard Chartered</a></td>
          <td>4000 TPS、7 個受監管市場、10x 提升</td>
          <td>受監管金融跨市場部署</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/cases/netflix-aurora-consolidation/" data-link-title="9.C23 Netflix：把關聯式 DB 統一到 Aurora、效能 &#43;75%、成本 -28%" data-link-desc="Netflix 把多套關聯式 DB 統一到 Aurora、效能提升 75%、成本下降 28%、串流數十億小時">9.C23 Netflix</a></td>
          <td>+75% 效能、-28% 成本</td>
          <td>多套 RDBMS 統一到 Aurora</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/cases/fanduel-dual-peak-betting-streaming/" data-link-title="9.C28 FanDuel：體育直播 &#43; 投注的雙重峰值" data-link-desc="FanDuel 3.5M MAU、Super Bowl 期間擴容 5-10 倍、用 AWS Local Zones &#43; Wavelength &#43; Outposts 處理 20&#43; 州的雙重峰值">9.C28 FanDuel</a></td>
          <td>Super Bowl 5-10x peak</td>
          <td>直播 + 投注雙工作負載</td>
      </tr>
  </tbody>
</table>
<p>Aurora case 的讀法是看 operation transfer 如何變成容量與成本結果。DraftKings 與 FanDuel 提供 peak OLTP 訊號，Standard Chartered 提供合規分區訊號，Netflix 則提供多套 RDBMS 整併到 managed SQL 的組織與成本訊號。</p>
<h2 id="反向-sibling-路由">反向 sibling 路由</h2>
<p>Aurora 的反向 sibling 路由用來避免把 managed SQL 誤讀成唯一升級方向。若讀者從 PostgreSQL / MySQL 章節過來，先對照 <a href="/blog/backend/01-database/vendors/postgresql/migrate-to-aurora/" data-link-title="PostgreSQL → Aurora Migration：protocol 相容、operational 重設計" data-link-desc="Aurora 號稱 PostgreSQL-compatible 但 operational model 不同（storage decouple / cluster endpoint / instance class / 自家備份）；遷移流程是混合（protocol drop-in &#43; operational phased）、5 個 production 踩雷（extension 不支援 / replication slot 不直通 / autovacuum 行為差 / IAM 認證強制 / cost model 換算）、跟 Patroni / read replica / DR 對位">PostgreSQL → Aurora</a> 與 <a href="/blog/backend/01-database/vendors/mysql/migrate-to-aurora/" data-link-title="MySQL → Aurora MySQL：storage layer 轉手到 AWS、replication / HA / backup 全部 outsource" data-link-desc="自管 MySQL → Aurora MySQL 是 Type C operational hybrid migration — wire protocol 一致、ops 責任轉到 AWS。本文走 6 維 audit（Operational High）、Aurora storage architecture 衝擊、4-phase migration、5 production 踩雷、何時維持原路線。">MySQL → Aurora</a>；若核心需求是 connection surge，補讀 <a href="/blog/backend/01-database/vendors/dynamodb/" data-link-title="DynamoDB" data-link-desc="AWS managed key-value、partition-based scaling、9000 萬 RPS sustained 實戰證據">DynamoDB vendor</a> 與 <a href="/blog/backend/09-performance-capacity/cases/ntt-docomo-lemino-japanese-streaming/" data-link-title="9.C29 NTT DOCOMO Lemino：3 個月達 500 萬 MAU 的串流後端" data-link-desc="Lemino 用 DynamoDB &#43; AWS Media Services 撐 30 channels live &#43; 5M MAU、工程工時下降 90%">Lemino case</a>；若核心需求是 multi-region active-active write，轉到 <a href="/blog/backend/01-database/vendors/spanner/" data-link-title="Google Cloud Spanner" data-link-desc="全球分散式 strong-consistency OLTP、TrueTime API、線性擴展到 10 億 req/sec">Spanner vendor</a> 或 <a href="/blog/backend/01-database/vendors/cockroachdb/" data-link-title="CockroachDB" data-link-desc="分散式 SQL、PostgreSQL 相容、跨區強一致、Spanner 的開源 / 跨雲替代">CockroachDB vendor</a>。</p>
<p>這條路由的判準是先問「保留 SQL + 轉移 operation」是否足夠。答案成立時，Aurora 是 RDS / 自管 MySQL / 自管 PostgreSQL 的 managed endpoint；答案需要改成 global quorum、partition-key access pattern 或 document API 時，Aurora 應退到對照組，而非成為最後選項。</p>
<h2 id="常見陷阱">常見陷阱</h2>
<ul>
<li><strong>誤以為 Aurora 等於無限擴</strong>：寫吞吐仍受 primary 限制，容量曲線和 distributed SQL 不同</li>
<li><strong>忽略 read replica</strong>：把所有 query 打 primary，會浪費 read replica scaling 能力</li>
<li><strong>跨 region 強一致誤解</strong>：Global Database 是 <em>async</em> 複製，multi-region active-active 要看 Aurora DSQL / Spanner / CockroachDB</li>
<li><strong>connection pool 忽略</strong>：Aurora 仍是 PostgreSQL / MySQL、connection 上限有效</li>
<li><strong>單一巨大 cluster</strong>：把所有業務塞進一個 cluster 會放大 blast radius，通常要按業務切</li>
</ul>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>完整 T1 對照：<a href="/blog/backend/01-database/vendors/" data-link-title="資料庫 Vendor 清單" data-link-desc="規劃 SQL、managed SQL、document、KV 與 distributed SQL 的服務頁撰寫順序與教學大綱">01-database vendors index</a></li>
<li>平行：<a href="/blog/backend/01-database/vendors/dynamodb/" data-link-title="DynamoDB" data-link-desc="AWS managed key-value、partition-based scaling、9000 萬 RPS sustained 實戰證據">DynamoDB vendor page</a>（NoSQL 對比）</li>
<li>上游：<a href="/blog/backend/01-database/transaction-boundary/" data-link-title="1.3 Transaction 與一致性邊界" data-link-desc="交易邊界、isolation level、retry 策略、distributed transaction（2PC、Saga）與跨 region 強一致取捨">1.3 Transaction Boundary</a> / <a href="/blog/backend/01-database/global-distributed-oltp/" data-link-title="1.11 全球分散式 OLTP" data-link-desc="Spanner / Aurora DSQL / Cosmos DB multi-region write / CockroachDB / TiDB 的全球一致性取捨">1.11 全球分散式 OLTP</a></li>
<li>下游：<a href="/blog/backend/01-database/large-scale-db-migration/" data-link-title="1.12 大規模 DB 遷移實戰" data-link-desc="跨 DB 遷移的 dual-write、[shadow read](/backend/knowledge-cards/shadow-read/)、cutover、rollback 流程 — 從實戰案例提煉的工程做法">1.12 大規模 DB 遷移實戰</a>（從 RDS / 自管遷到 Aurora）</li>
<li>跨模組：<a href="/blog/backend/09-performance-capacity/bottleneck-localization/" data-link-title="9.5 瓶頸定位流程" data-link-desc="從 app 到 DB / cache / broker / 第三方 quota 的逐層瓶頸定位">9.5 瓶頸定位流程</a>、<a href="/blog/backend/09-performance-capacity/capacity-planning/" data-link-title="9.6 容量規劃模型" data-link-desc="peak forecast、headroom budget、growth curve、autoscaling sizing">9.6 容量規劃模型</a></li>
<li>Last reviewed：2026-05-22（Aurora storage / Serverless / Global Database / I/O-Optimized 屬時間敏感 claim）</li>
<li>官方：<a href="https://aws.amazon.com/rds/aurora/">Amazon Aurora</a>、<a href="https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/Aurora.Overview.StorageReliability.html">Aurora storage architecture</a></li>
</ul>
]]></content:encoded></item><item><title>Atlassian Statuspage</title><link>https://tarrragon.github.io/blog/backend/08-incident-response/vendors/atlassian-statuspage/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/08-incident-response/vendors/atlassian-statuspage/</guid><description>&lt;p>Statuspage 是 Atlassian 收購整合的公開狀態頁 SaaS、承擔三個責任：對外公開服務狀態揭露（component / incident / maintenance）、subscriber notification（email / SMS / Slack / Microsoft Teams / webhook / RSS）、自有 domain + branding。是公開狀態頁的事實標準、跟 &lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/vendors/opsgenie/" data-link-title="Opsgenie" data-link-desc="Atlassian on-call、跟 Jira / Statuspage 套件整合、JSM Premium migration 議題">Opsgenie&lt;/a> 同屬 Atlassian 事故處理生態（搭配 Jira Service Management、Confluence post-mortem template）、也跟 &lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/vendors/pagerduty/" data-link-title="PagerDuty" data-link-desc="On-call / alerting 主流 SaaS、IR 平台演化">PagerDuty&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/vendors/incident-io/" data-link-title="incident.io" data-link-desc="Slack-native IR 平台、整合 paging / response / retro">incident.io&lt;/a> 等第三方 IR 平台廣泛整合。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Statuspage 的定位是 &lt;em>對外狀態頁領導品牌&lt;/em>、責任邊界是 &lt;em>把內部 incident state 翻譯成對外可讀的公告&lt;/em>、不是 IR workflow 本身。功能涵蓋 component status（operational / degraded / partial outage / major outage / under maintenance）、incident update（lifecycle + template）、scheduled maintenance（pre-announce + auto-publish + auto-resolve）、metrics chart（uptime / latency 公開圖表、來源 Datadog / Pingdom / New Relic / Library）、audience targeting（public / private / partner / per-customer 分軌）。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/vendors/opsgenie/" data-link-title="Opsgenie" data-link-desc="Atlassian on-call、跟 Jira / Statuspage 套件整合、JSM Premium migration 議題">Opsgenie&lt;/a> / Confluence / Jira Service Management 是同生態 — Statuspage 接 Opsgenie alert 自動 create incident draft、incident resolve 自動 publish post-mortem 到 Confluence、JSM ticket 連結 Statuspage incident URL。enterprise polish（custom CSS / 自有 domain / multi-language / SSO admin）是賣點、defaults 也夠用、是大型 SaaS public-facing 的主流選擇。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;ol>
&lt;li>建 Statuspage + 設 component / group&lt;/li>
&lt;li>寫第一個 incident update（template-driven）&lt;/li>
&lt;li>配置 subscriber notification channels&lt;/li>
&lt;li>API 自動化（從 IR 平台 push update）&lt;/li>
&lt;li>設定 custom domain + 品牌一致 UI&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑">最短路徑&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 1. 註冊 Statuspage、選 plan&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="c1"># 2. 建 component（按服務拆）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">&lt;span class="c1"># 3. 寫 test incident&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="c1"># 4. 訂閱者 self-service subscribe&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="最短判讀路徑">最短判讀路徑&lt;/h2>
&lt;p>判斷 Statuspage deployment 是否健康、最少看四件事：&lt;/p></description><content:encoded><![CDATA[<p>Statuspage 是 Atlassian 收購整合的公開狀態頁 SaaS、承擔三個責任：對外公開服務狀態揭露（component / incident / maintenance）、subscriber notification（email / SMS / Slack / Microsoft Teams / webhook / RSS）、自有 domain + branding。是公開狀態頁的事實標準、跟 <a href="/blog/backend/08-incident-response/vendors/opsgenie/" data-link-title="Opsgenie" data-link-desc="Atlassian on-call、跟 Jira / Statuspage 套件整合、JSM Premium migration 議題">Opsgenie</a> 同屬 Atlassian 事故處理生態（搭配 Jira Service Management、Confluence post-mortem template）、也跟 <a href="/blog/backend/08-incident-response/vendors/pagerduty/" data-link-title="PagerDuty" data-link-desc="On-call / alerting 主流 SaaS、IR 平台演化">PagerDuty</a> / <a href="/blog/backend/08-incident-response/vendors/incident-io/" data-link-title="incident.io" data-link-desc="Slack-native IR 平台、整合 paging / response / retro">incident.io</a> 等第三方 IR 平台廣泛整合。</p>
<h2 id="服務定位">服務定位</h2>
<p>Statuspage 的定位是 <em>對外狀態頁領導品牌</em>、責任邊界是 <em>把內部 incident state 翻譯成對外可讀的公告</em>、不是 IR workflow 本身。功能涵蓋 component status（operational / degraded / partial outage / major outage / under maintenance）、incident update（lifecycle + template）、scheduled maintenance（pre-announce + auto-publish + auto-resolve）、metrics chart（uptime / latency 公開圖表、來源 Datadog / Pingdom / New Relic / Library）、audience targeting（public / private / partner / per-customer 分軌）。</p>
<p>跟 <a href="/blog/backend/08-incident-response/vendors/opsgenie/" data-link-title="Opsgenie" data-link-desc="Atlassian on-call、跟 Jira / Statuspage 套件整合、JSM Premium migration 議題">Opsgenie</a> / Confluence / Jira Service Management 是同生態 — Statuspage 接 Opsgenie alert 自動 create incident draft、incident resolve 自動 publish post-mortem 到 Confluence、JSM ticket 連結 Statuspage incident URL。enterprise polish（custom CSS / 自有 domain / multi-language / SSO admin）是賣點、defaults 也夠用、是大型 SaaS public-facing 的主流選擇。</p>
<h2 id="本章目標">本章目標</h2>
<ol>
<li>建 Statuspage + 設 component / group</li>
<li>寫第一個 incident update（template-driven）</li>
<li>配置 subscriber notification channels</li>
<li>API 自動化（從 IR 平台 push update）</li>
<li>設定 custom domain + 品牌一致 UI</li>
</ol>
<h2 id="最短路徑">最短路徑</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 1. 註冊 Statuspage、選 plan</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># 2. 建 component（按服務拆）</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="c1"># 3. 寫 test incident</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 4. 訂閱者 self-service subscribe</span></span></span></code></pre></div><h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Statuspage deployment 是否健康、最少看四件事：</p>
<ul>
<li><strong>誰能 publish update</strong>：admin / page admin / incident manager 的權限分層、incident publish 是否走 template + reviewer、API token 是否分 <em>human ops</em> 跟 <em>machine push</em> 兩條</li>
<li><strong>Component dependency 設計</strong>：component 是否對應 <em>使用者可感知的服務面</em>（不是內部 microservice）、group 是否拆得太細導致 status update 散落、dependency map 是否誇大內部架構讓對外公告失焦</li>
<li><strong>Metrics integration</strong>：uptime / latency chart 來源是否跟內部 SLO 對齊（Datadog / Pingdom / 自家 API push）、metrics 是否跟 incident state 同步（incident 開了 metrics 還綠燈 = 對外公信力下降）</li>
<li><strong>Audience targeting</strong>：public / private / partner page 是否清楚分軌、subscriber list 是否定期清理（離職者 / 失效 email / SMS bounce）、per-customer audience 是否走 SSO 控管</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/08-incident-response/incident-communication/" data-link-title="8.4 事故通訊與狀態更新" data-link-desc="建立內外部通報節奏與狀態更新格式">Incident Communication</a> 邊界的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="component--group-設計">Component / group 設計</h3>
<p>子議題：</p>
<ul>
<li>Component 對應服務 / API endpoint（粒度跟使用者可感知一致、不是內部服務拓樸）</li>
<li>Group 組織多 component（按產品線 / 區域 / 客戶層）</li>
<li>Status：operational / degraded / partial outage / major outage / under maintenance</li>
<li>Component dependency：parent component 自動匯總 child status（過細會造成內部架構洩漏）</li>
</ul>
<h3 id="incident-lifecycle--subscriber">Incident lifecycle + Subscriber</h3>
<p>子議題：</p>
<ul>
<li>Investigating → Identified → Monitoring → Resolved 四段、每段都該推 update</li>
<li>Template（標準措辭、降低 incident commander 寫稿壓力、避免揭露過多內部細節）</li>
<li>Email / SMS / Slack / Microsoft Teams / webhook / RSS subscriber</li>
<li>Subscribe by component（部分訂閱、避免 noise）</li>
</ul>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<h3 id="audience-specific-page">Audience-specific page</h3>
<p>子議題：public（所有人）/ private（authenticated、內部員工 / 特定客戶）/ partner（B2B 獨立 view）、per-customer / per-region status（大型 SaaS 用、避免單一 region 事故影響全球公信力）</p>
<h3 id="scheduled-maintenance">Scheduled maintenance</h3>
<p>子議題：提前公告 maintenance window、auto-publish + auto-resolve、跟 change management 流程串接、recurring maintenance 用 template</p>
<h3 id="subscription-management">Subscription management</h3>
<p>子議題：email / SMS / Slack / Microsoft Teams / webhook 多通道、bounce 清理、SMS provider 限額（高峰 incident 可能塞車）、subscriber list growth 變廣告管理目標時需 GDPR / CAN-SPAM 治理</p>
<h3 id="templates">Templates</h3>
<p>子議題：incident template（standard outage / degraded performance / scheduled maintenance）、避免每次 incident commander 重新寫稿、降低措辭風險</p>
<h3 id="ir-平台整合">IR 平台整合</h3>
<p>子議題：<a href="/blog/backend/08-incident-response/vendors/pagerduty/" data-link-title="PagerDuty" data-link-desc="On-call / alerting 主流 SaaS、IR 平台演化">PagerDuty</a> Status Pages integration、<a href="/blog/backend/08-incident-response/vendors/incident-io/" data-link-title="incident.io" data-link-desc="Slack-native IR 平台、整合 paging / response / retro">incident.io</a> Statuspage sync、<a href="/blog/backend/08-incident-response/vendors/opsgenie/" data-link-title="Opsgenie" data-link-desc="Atlassian on-call、跟 Jira / Statuspage 套件整合、JSM Premium migration 議題">Opsgenie</a> incident-to-Statuspage workflow、<a href="/blog/backend/08-incident-response/vendors/firehydrant/" data-link-title="FireHydrant" data-link-desc="IR &#43; retrospective 平台、Slack / Teams 整合、service catalog &#43; runbook automation 為核心">FireHydrant</a> auto-publish</p>
<h3 id="api-automation">API automation</h3>
<p>子議題：從 IR 平台 push update、跟 Opsgenie alert sync、custom field、API token 分軌（human ops vs machine push）、retry / idempotency</p>
<h3 id="custom-domain--branding">Custom domain + branding</h3>
<p>子議題：status.example.com vs example.statuspage.io、custom CSS / logo、多語言、SSO trap（admin SSO 設錯導致 lock-out）</p>
<h3 id="metrics-公開">Metrics 公開</h3>
<p>子議題：uptime / response time 圖表、來源（Datadog / Pingdom / New Relic / 自家 API push）、metrics 跟 incident state 同步、避免 metrics 綠燈但 incident open</p>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<ul>
<li><strong>Incident update 沒發</strong>：API token 失效 / IR 沒 trigger / template variable 漏帶</li>
<li><strong>Stale status（incident 過了還掛 active）</strong>：auto-resolve 規則沒設 / IR 平台 close 沒 sync / oncall 手動忘記 resolve</li>
<li><strong>Subscriber 沒收到</strong>：email bounce / SMS provider 限額 / Slack workspace token expired</li>
<li><strong>Component dependency map 過細</strong>：把內部 microservice 都拉成 component、對外公告失焦、攻擊面間接洩漏架構</li>
<li><strong>Subscriber list growth 變廣告管理</strong>：上萬 subscriber 後接近 marketing list、需 GDPR / CAN-SPAM 治理、定期清離職 + bounce</li>
<li><strong>Component status 跟實際不符</strong>：自動 sync 規則錯 / 手動沒更新 / metrics 來源延遲</li>
<li><strong>Custom domain 失效</strong>：DNS / SSL cert 過期、Statuspage cert auto-renew 沒 enable</li>
<li><strong>SSO trap</strong>：admin SSO 切過去後 IdP 出事、Statuspage admin 進不去、break-glass token 沒留</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>預算敏感 / 小型團隊</td>
          <td><a href="/blog/backend/08-incident-response/vendors/instatus/" data-link-title="Instatus" data-link-desc="輕量 status page SaaS、現代 UI、價格敏感替代">Instatus</a> / Better Stack</td>
      </tr>
      <tr>
          <td>OSS / 自管 / 完全 control</td>
          <td>Cachet</td>
      </tr>
      <tr>
          <td>IR 平台內建 status</td>
          <td><a href="/blog/backend/08-incident-response/vendors/firehydrant/" data-link-title="FireHydrant" data-link-desc="IR &#43; retrospective 平台、Slack / Teams 整合、service catalog &#43; runbook automation 為核心">FireHydrant</a></td>
      </tr>
      <tr>
          <td>IR workflow + Status 一體</td>
          <td><a href="/blog/backend/08-incident-response/vendors/incident-io/" data-link-title="incident.io" data-link-desc="Slack-native IR 平台、整合 paging / response / retro">incident.io</a></td>
      </tr>
      <tr>
          <td>內部 only</td>
          <td>內部 dashboard（Grafana / Datadog）</td>
      </tr>
  </tbody>
</table>
<p>選 Statuspage 的核心訴求：<em>enterprise polish + Atlassian 生態整合（Opsgenie / JSM / Confluence）+ subscriber scale（百萬級 email/SMS）+ audience targeting 需求（partner / per-customer page）</em>。中小團隊 / 預算敏感走 Instatus / Better Stack 更划算；IR workflow + status 想一體化走 incident.io。</p>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>完整 API reference / Custom CSS / Statuspage Connect</li>
<li>Atlassian SSO 設定細節（屬 IdP 範疇）</li>
<li>SLA 計算 / SLO dashboard（屬 observability、不屬對外狀態頁）</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p><strong>Statuspage 廣泛使用</strong>：GitHub / Cloudflare / Atlassian / Slack / Discord / Datadog / Fastly / Heroku / Reddit / Roblox 等大型 SaaS 的 public-facing status communication 多為 Statuspage 託管、是 <em>對外揭露節奏跟措辭</em> 的事實標準。</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>對應主題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/08-incident-response/cases/github/" data-link-title="GitHub" data-link-desc="GitHub 重大事故時間線與架構脈絡">GitHub cases</a></td>
          <td>Statuspage update 與長尾事故時序</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/08-incident-response/cases/cloudflare/" data-link-title="Cloudflare" data-link-desc="Cloudflare 全球 edge 事故時間線與架構脈絡">Cloudflare cases</a></td>
          <td>控制面事故的公開揭露節奏</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/08-incident-response/cases/atlassian/" data-link-title="Atlassian" data-link-desc="Atlassian 多租戶事故時間線與架構脈絡">Atlassian cases</a></td>
          <td>自家 Statuspage、14 天長尾事故對外通訊</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/08-incident-response/cases/slack/" data-link-title="Slack" data-link-desc="Slack 通訊服務事故與外部狀態頁設計">Slack cases</a></td>
          <td>通訊平台失效時的 status 訊息分軌</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/08-incident-response/cases/discord/" data-link-title="Discord" data-link-desc="Discord Gateway scale-out 事故與容量驚奇">Discord cases</a></td>
          <td>Gateway 事故的 component 拆分</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/08-incident-response/cases/datadog/" data-link-title="Datadog" data-link-desc="Datadog 監控服務事故、客戶觀測落差">Datadog cases</a></td>
          <td>觀測平台失效時的 status 自我宣告</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/08-incident-response/cases/fastly/" data-link-title="Fastly" data-link-desc="Fastly 全球配置 push 事故時間線">Fastly cases</a></td>
          <td>全球邊緣事故的單頁公開時程</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/08-incident-response/cases/heroku/" data-link-title="Heroku" data-link-desc="Heroku PaaS 事故與 router 層架構脈絡">Heroku cases</a></td>
          <td>平台型 Routing 事故的 incident 分層</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/08-incident-response/cases/reddit/" data-link-title="Reddit" data-link-desc="Reddit Pi Day 2023 k8s 升級事故">Reddit cases</a></td>
          <td>Kubernetes 升級事故的對外揭露策略</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/08-incident-response/cases/roblox/" data-link-title="Roblox" data-link-desc="Roblox 73 小時事故時間線與架構脈絡">Roblox cases</a></td>
          <td>長時間核心基礎設施事故的 incident lifecycle</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/08-incident-response/incident-decision-log/" data-link-title="8.19 Incident Decision Log" data-link-desc="把事中假設、決策、證據、回退條件與責任人留下可復盤紀錄">8.19 Incident Decision Log</a></li>
<li>平行：<a href="/blog/backend/08-incident-response/vendors/instatus/" data-link-title="Instatus" data-link-desc="輕量 status page SaaS、現代 UI、價格敏感替代">Instatus</a>、<a href="/blog/backend/08-incident-response/vendors/opsgenie/" data-link-title="Opsgenie" data-link-desc="Atlassian on-call、跟 Jira / Statuspage 套件整合、JSM Premium migration 議題">Opsgenie</a>、<a href="/blog/backend/08-incident-response/vendors/incident-io/" data-link-title="incident.io" data-link-desc="Slack-native IR 平台、整合 paging / response / retro">incident.io</a></li>
<li>下游：<a href="/blog/backend/08-incident-response/incident-evidence-write-back/" data-link-title="8.22 Incident Evidence Write-back" data-link-desc="把事故證據、決策與復盤結論回寫到 observability、reliability 與 runbook">8.22 Incident Evidence Write-back</a></li>
</ul>
]]></content:encoded></item><item><title>AWS CloudWatch</title><link>https://tarrragon.github.io/blog/backend/04-observability/vendors/aws-cloudwatch/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/04-observability/vendors/aws-cloudwatch/</guid><description>&lt;p>CloudWatch 是 AWS 原生 observability 服務、承擔三個責任：AWS 服務內建 metrics / logs / alarms（無需配置）、跨 AWS 服務統一觀測平面、X-Ray + Container Insights + Lambda Insights 等專用擴展。設計取捨偏向「AWS 生態深度整合 + 不用第三方 vendor + 預設 turnkey」、跨雲跟成本是主要限制。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>用 AWS CLI / Console 查 CloudWatch metrics / logs / alarms&lt;/li>
&lt;li>用 CloudWatch Logs Insights 查詢結構化 logs&lt;/li>
&lt;li>配置 alarm + composite alarm + EventBridge integration&lt;/li>
&lt;li>用 X-Ray 追蹤 distributed tracing&lt;/li>
&lt;li>控制 CloudWatch cost（log ingestion / metric / API call）&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑5-分鐘把-cloudwatch-跑起來">最短路徑：5 分鐘把 CloudWatch 跑起來&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 1. 用 CloudWatch Agent 採集 EC2 metrics + logs&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: aws-cli + cloudwatch-agent.json config&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="c1"># 2. 查詢 metric&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: aws cloudwatch get-metric-statistics --namespace AWS/EC2 --metric-name CPUUtilization&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">&lt;span class="c1"># 3. 用 Logs Insights 查詢&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: fields @timestamp, @message | filter @message like /ERROR/ | sort @timestamp desc&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="日常操作與決策形狀">日常操作與決策形狀&lt;/h2>
&lt;h3 id="metrics--logs--alarms-整合">Metrics / Logs / Alarms 整合&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>Namespace + Dimension + Metric 三層&lt;/li>
&lt;li>Custom metric（CLI / SDK / Agent）&lt;/li>
&lt;li>Logs group + Log stream + Log event&lt;/li>
&lt;li>Alarm + Composite alarm + EventBridge rule&lt;/li>
&lt;/ul>
&lt;h3 id="logs-insights-query">Logs Insights query&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>Query syntax：fields / filter / parse / stats / sort&lt;/li>
&lt;li>跟 KQL / LogQL 對照（CloudWatch 自家 syntax）&lt;/li>
&lt;li>對應指令：&lt;code>aws logs start-query&lt;/code>、&lt;code>aws logs get-query-results&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="metrics-math">Metrics Math&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>跨 metric 算術運算（rate / sum / avg）&lt;/li>
&lt;li>適合 dashboard / alarm 不直接 metric 表達的計算&lt;/li>
&lt;li>對比 PromQL：CloudWatch Math 較弱、無 label join 能力&lt;/li>
&lt;/ul>
&lt;h3 id="x-ray-tracing">X-Ray tracing&lt;/h3>
&lt;p>子議題：&lt;/p></description><content:encoded><![CDATA[<p>CloudWatch 是 AWS 原生 observability 服務、承擔三個責任：AWS 服務內建 metrics / logs / alarms（無需配置）、跨 AWS 服務統一觀測平面、X-Ray + Container Insights + Lambda Insights 等專用擴展。設計取捨偏向「AWS 生態深度整合 + 不用第三方 vendor + 預設 turnkey」、跨雲跟成本是主要限制。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>用 AWS CLI / Console 查 CloudWatch metrics / logs / alarms</li>
<li>用 CloudWatch Logs Insights 查詢結構化 logs</li>
<li>配置 alarm + composite alarm + EventBridge integration</li>
<li>用 X-Ray 追蹤 distributed tracing</li>
<li>控制 CloudWatch cost（log ingestion / metric / API call）</li>
</ol>
<h2 id="最短路徑5-分鐘把-cloudwatch-跑起來">最短路徑：5 分鐘把 CloudWatch 跑起來</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 1. 用 CloudWatch Agent 採集 EC2 metrics + logs</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># TODO: aws-cli + cloudwatch-agent.json config</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 2. 查詢 metric</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="c1"># TODO: aws cloudwatch get-metric-statistics --namespace AWS/EC2 --metric-name CPUUtilization</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="c1"># 3. 用 Logs Insights 查詢</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="c1"># TODO: fields @timestamp, @message | filter @message like /ERROR/ | sort @timestamp desc</span></span></span></code></pre></div><h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="metrics--logs--alarms-整合">Metrics / Logs / Alarms 整合</h3>
<p>子議題：</p>
<ul>
<li>Namespace + Dimension + Metric 三層</li>
<li>Custom metric（CLI / SDK / Agent）</li>
<li>Logs group + Log stream + Log event</li>
<li>Alarm + Composite alarm + EventBridge rule</li>
</ul>
<h3 id="logs-insights-query">Logs Insights query</h3>
<p>子議題：</p>
<ul>
<li>Query syntax：fields / filter / parse / stats / sort</li>
<li>跟 KQL / LogQL 對照（CloudWatch 自家 syntax）</li>
<li>對應指令：<code>aws logs start-query</code>、<code>aws logs get-query-results</code></li>
</ul>
<h3 id="metrics-math">Metrics Math</h3>
<p>子議題：</p>
<ul>
<li>跨 metric 算術運算（rate / sum / avg）</li>
<li>適合 dashboard / alarm 不直接 metric 表達的計算</li>
<li>對比 PromQL：CloudWatch Math 較弱、無 label join 能力</li>
</ul>
<h3 id="x-ray-tracing">X-Ray tracing</h3>
<p>子議題：</p>
<ul>
<li>各語言 X-Ray SDK</li>
<li>Sampling rule（rate-based / reservoir）</li>
<li>Service map 自動 build</li>
<li>對應 <a href="/blog/backend/04-observability/cases/xray-to-opentelemetry-migration/" data-link-title="4.C4 AWS：X-Ray 到 OpenTelemetry 轉換" data-link-desc="觀測儀表從 vendor-specific SDK 轉向 OpenTelemetry 的治理重點。">4.C4 X-Ray to OpenTelemetry</a> 遷移案例</li>
</ul>
<h2 id="deep-article">Deep Article</h2>
<ul>
<li><a href="logs-insights-governance/">Logs Insights 查詢與日誌治理</a>：log group 設計、query syntax、retention policy、cross-account aggregation、subscription filter 與 cost governance</li>
<li><a href="alarms-composite-operations/">Alarms 與 Composite Alarms 操作實務</a>：Metric Alarm、Anomaly Detection、Composite Alarm 設計、alarm actions、missing data 處理與 cost</li>
</ul>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<h3 id="container-insights--lambda-insights">Container Insights / Lambda Insights</h3>
<p>子議題：</p>
<ul>
<li>Container Insights：EKS / ECS metrics + logs 自動採集</li>
<li>Lambda Insights：Lambda runtime metrics + cold start visibility</li>
<li>跟 Prometheus + Grafana 的 K8s 模式對照</li>
</ul>
<h3 id="cloudwatch-synthetics--rum">CloudWatch Synthetics / RUM</h3>
<p>子議題：</p>
<ul>
<li>Synthetics：canary script 定期 probe</li>
<li>RUM：前端用戶體驗</li>
<li>跟 Datadog Synthetics / RUM 對照</li>
</ul>
<h3 id="logs-lifecycle">Logs lifecycle</h3>
<p>子議題：</p>
<ul>
<li>Retention（1 day to never expire）</li>
<li>Subscription filter：把 logs 送到 Lambda / Kinesis / S3</li>
<li>Logs to S3 archive</li>
<li>對應 cost 控制</li>
</ul>
<h3 id="cost-控制">Cost 控制</h3>
<p>子議題：</p>
<ul>
<li>Logs ingestion charge（per GB）</li>
<li>Metrics storage charge（custom metrics + high-resolution）</li>
<li>API call charge（GetMetricData / Logs Insights query）</li>
<li>對應 <a href="/blog/backend/04-observability/cases/fintech-audit-evidence-observability/" data-link-title="FinTech：審計證據鏈的可觀測性設計" data-link-desc="把交易與存取事件轉成可回查證據，降低合規審核與事故判讀落差。">4.C1 Fintech audit</a></li>
</ul>
<h3 id="cloudwatch-managed-prometheusamp">CloudWatch Managed Prometheus（AMP）</h3>
<p>子議題：</p>
<ul>
<li>AMP：AWS managed Prometheus、scrape EKS / ECS</li>
<li>跟 CloudWatch 互補（CloudWatch 是 AWS-native、AMP 是 OSS standard）</li>
<li>對應 <a href="/blog/backend/04-observability/cases/adot-eks-observability-pipeline-migration/" data-link-title="4.C6 AWS：ADOT on EKS 管線遷移" data-link-desc="從分散式 agent 組合轉成 OpenTelemetry collector 管線治理。">4.C6 ADOT EKS</a></li>
</ul>
<h3 id="aws-distro-for-opentelemetryadot">AWS Distro for OpenTelemetry（ADOT）</h3>
<p>子議題：</p>
<ul>
<li>AWS-supported OTel distribution</li>
<li>跟 X-Ray / AMP / CloudWatch 都整合</li>
<li>推薦的 OTel adoption 路徑</li>
<li>對應 <a href="/blog/backend/04-observability/cases/adot-eks-observability-pipeline-migration/" data-link-title="4.C6 AWS：ADOT on EKS 管線遷移" data-link-desc="從分散式 agent 組合轉成 OpenTelemetry collector 管線治理。">4.C6 ADOT EKS</a></li>
</ul>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<h3 id="logs-insights-query-過慢">Logs Insights query 過慢</h3>
<p>操作原則：query 範圍 + 結果集大時、用 sample 縮範圍。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># TODO: fields @timestamp, @message | limit 100（先測 logic）</span></span></span></code></pre></div><h3 id="metric-not-found">Metric not found</h3>
<p>操作原則：metric namespace / dimension 對應錯。判讀：用 <code>aws cloudwatch list-metrics --namespace ...</code> 確認。</p>
<h3 id="alarm-沒觸發">Alarm 沒觸發</h3>
<p>操作原則：alarm period / evaluation period / datapoints 配置造成延遲或忽略。</p>
<h3 id="x-ray-trace-incomplete">X-Ray trace incomplete</h3>
<p>操作原則：sampling rule 過頭、subseg context propagation 失敗。判讀：X-Ray console 看 trace timeline。</p>
<h3 id="cost-爆">Cost 爆</h3>
<p>操作原則：log ingestion 多、custom metric 多、Logs Insights query 量大都會貢獻。判讀：Cost Explorer 看 CloudWatch service breakdown。</p>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>多雲 / 跨雲統一</td>
          <td><a href="/blog/backend/04-observability/vendors/datadog/" data-link-title="Datadog" data-link-desc="All-in-one SaaS 觀測平台、APM / Logs / Metrics / RUM / Security">Datadog</a> / <a href="/blog/backend/04-observability/vendors/grafana-stack/" data-link-title="Grafana Stack" data-link-desc="Grafana / Loki / Tempo / Mimir / Pyroscope 全棧">Grafana Stack</a> / <a href="/blog/backend/04-observability/vendors/opentelemetry/" data-link-title="OpenTelemetry" data-link-desc="可觀測性開放標準、SDK 與 Collector">OTel</a></td>
      </tr>
      <tr>
          <td>進階 APM 體驗</td>
          <td><a href="/blog/backend/04-observability/vendors/datadog/" data-link-title="Datadog" data-link-desc="All-in-one SaaS 觀測平台、APM / Logs / Metrics / RUM / Security">Datadog</a> / <a href="/blog/backend/04-observability/vendors/honeycomb/" data-link-title="Honeycomb" data-link-desc="High-cardinality observability 平台、events-based 模型">Honeycomb</a></td>
      </tr>
      <tr>
          <td>高頻 query / 大量 log</td>
          <td><a href="/blog/backend/04-observability/vendors/grafana-stack/" data-link-title="Grafana Stack" data-link-desc="Grafana / Loki / Tempo / Mimir / Pyroscope 全棧">Grafana Stack</a>（Loki）/ <a href="/blog/backend/04-observability/vendors/elastic-stack/" data-link-title="Elastic Stack" data-link-desc="ELK：Elasticsearch / Logstash / Kibana &#43; Beats / APM">Elastic</a></td>
      </tr>
      <tr>
          <td>OTel standard</td>
          <td><a href="/blog/backend/04-observability/vendors/opentelemetry/" data-link-title="OpenTelemetry" data-link-desc="可觀測性開放標準、SDK 與 Collector">OTel</a> + ADOT / AMP</td>
      </tr>
      <tr>
          <td>GCP / Azure 生態</td>
          <td><a href="/blog/backend/04-observability/vendors/gcp-cloud-operations/" data-link-title="GCP Cloud Operations" data-link-desc="GCP 原生觀測性套件（前 Stackdriver）：Logging / Monitoring / Trace / Profiler">Cloud Operations</a> / Azure Monitor</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>各 AWS 服務的 CloudWatch metric 名稱列表</li>
<li>CloudWatch Synthetics canary script 語法</li>
<li>Logs Insights 完整 query syntax reference</li>
<li>AWS IAM 跟 CloudWatch 的細部權限</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<h3 id="直接相關案例">直接相關案例</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>主討論議題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/xray-to-opentelemetry-migration/" data-link-title="4.C4 AWS：X-Ray 到 OpenTelemetry 轉換" data-link-desc="觀測儀表從 vendor-specific SDK 轉向 OpenTelemetry 的治理重點。">4.C4 X-Ray to OTel</a></td>
          <td>X-Ray 遷出到 OTel</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/adot-eks-observability-pipeline-migration/" data-link-title="4.C6 AWS：ADOT on EKS 管線遷移" data-link-desc="從分散式 agent 組合轉成 OpenTelemetry collector 管線治理。">4.C6 ADOT EKS pipeline</a></td>
          <td>AWS Distro + EKS 觀測</td>
      </tr>
  </tbody>
</table>
<h3 id="跨-vendor-對照">跨 vendor 對照</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>對 CloudWatch 的對應</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/fintech-audit-evidence-observability/" data-link-title="FinTech：審計證據鏈的可觀測性設計" data-link-desc="把交易與存取事件轉成可回查證據，降低合規審核與事故判讀落差。">4.C1 Fintech audit</a></td>
          <td>CloudWatch Logs / S3 archive 作為 audit evidence</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/healthcare-access-traceability-and-retention/" data-link-title="Healthcare：存取可追溯性與保留邊界" data-link-desc="在資料主權限制下，建立可追溯存取證據與分層保留策略。">4.C3 Healthcare retention</a></td>
          <td>Logs lifecycle / retention 對應資料主權限制</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/contrast-observability-rollout-by-scale/" data-link-title="4.C10 對照：規模差異下的觀測遷移" data-link-desc="觀測遷移在不同規模團隊下的流程與風險差異。">4.C10 規模對照</a></td>
          <td>AWS-only 場景優先 CloudWatch</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游概念：<a href="/blog/backend/04-observability/telemetry-data-quality/" data-link-title="4.17 Telemetry Data Quality" data-link-desc="把 missing signal、schema drift、sampling bias 與 timestamp skew 變成資料品質問題">4.17 Telemetry Data Quality</a></li>
<li>平行 vendor：<a href="/blog/backend/04-observability/vendors/opentelemetry/" data-link-title="OpenTelemetry" data-link-desc="可觀測性開放標準、SDK 與 Collector">OpenTelemetry</a>、<a href="/blog/backend/04-observability/vendors/gcp-cloud-operations/" data-link-title="GCP Cloud Operations" data-link-desc="GCP 原生觀測性套件（前 Stackdriver）：Logging / Monitoring / Trace / Profiler">Cloud Operations</a></li>
<li>下游能力：<a href="/blog/backend/04-observability/observability-evidence-package/" data-link-title="4.20 Observability Evidence Package" data-link-desc="把 log、metric、trace、audit 與資料品質限制包成可交接證據">4.20 Observability Evidence Package</a></li>
</ul>
]]></content:encoded></item><item><title>Chaos Mesh</title><link>https://tarrragon.github.io/blog/backend/06-reliability/vendors/chaos-mesh/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/06-reliability/vendors/chaos-mesh/</guid><description>&lt;p>Chaos Mesh 是 PingCAP 開源、CNCF incubating 的 Kubernetes-native chaos engineering 平台、承擔三個責任：CRD-driven fault injection（PodChaos / NetworkChaos / IOChaos / StressChaos）、Chaos Workflow（多步驟編排）、Chaos Dashboard 視覺化 + experiment scope 控制。設計取捨偏向「K8s-native + GitOps-friendly + multi-fault types」、適合 K8s 為主的 chaos engineering。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>部署 Chaos Mesh 到 K8s cluster&lt;/li>
&lt;li>設計 PodChaos / NetworkChaos / IOChaos experiment&lt;/li>
&lt;li>用 Chaos Workflow 編排多步驟實驗 + steady state probe&lt;/li>
&lt;li>控制 blast radius（namespace / labelSelector / mode）&lt;/li>
&lt;li>跟 &lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/experiment-safety-boundary/" data-link-title="6.20 Experiment Safety Boundary" data-link-desc="定義 chaos、load test、DR drill 的 [blast radius](/backend/knowledge-cards/blast-radius/)、停止條件與權限約束">6.20 Experiment Safety Boundary&lt;/a> 對齊 chaos 實驗審批&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑5-分鐘把-chaos-mesh-跑起來">最短路徑：5 分鐘把 Chaos Mesh 跑起來&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 1. 安裝&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: curl -sSL https://mirrors.chaos-mesh.org/v2.7.0/install.sh | bash&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="c1"># 2. 跑第一個 PodChaos&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: 寫 podchaos.yaml、kubectl apply&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: action: pod-kill / selector / mode&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl">&lt;span class="c1"># 3. Dashboard&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">9&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: kubectl port-forward svc/chaos-dashboard 2333:2333&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="日常操作與決策形狀">日常操作與決策形狀&lt;/h2>
&lt;h3 id="crd-設計">CRD 設計&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>PodChaos：pod-kill / pod-failure / container-kill&lt;/li>
&lt;li>NetworkChaos：delay / loss / duplicate / corrupt / partition&lt;/li>
&lt;li>IOChaos：delay / errno / mistake / attrOverride&lt;/li>
&lt;li>StressChaos：CPU / memory pressure&lt;/li>
&lt;li>對應 GitOps：Helm / Kustomize 管 experiment&lt;/li>
&lt;/ul>
&lt;h3 id="chaos-workflow">Chaos Workflow&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>多步驟 chaos 編排（serial / parallel）&lt;/li>
&lt;li>Suspend / resume 控制&lt;/li>
&lt;li>Probe（steady state validation）&lt;/li>
&lt;li>對應 &lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/experiment-safety-boundary/" data-link-title="6.20 Experiment Safety Boundary" data-link-desc="定義 chaos、load test、DR drill 的 [blast radius](/backend/knowledge-cards/blast-radius/)、停止條件與權限約束">6.20 Experiment Safety Boundary&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="chaos-dashboard">Chaos Dashboard&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>視覺化 experiment timeline&lt;/li>
&lt;li>Experiment archive&lt;/li>
&lt;li>Event log&lt;/li>
&lt;li>RBAC&lt;/li>
&lt;/ul>
&lt;h2 id="進階主題按需閱讀">進階主題（按需閱讀）&lt;/h2>
&lt;h3 id="blast-radius-控制">Blast radius 控制&lt;/h3>
&lt;p>子議題：&lt;/p></description><content:encoded><![CDATA[<p>Chaos Mesh 是 PingCAP 開源、CNCF incubating 的 Kubernetes-native chaos engineering 平台、承擔三個責任：CRD-driven fault injection（PodChaos / NetworkChaos / IOChaos / StressChaos）、Chaos Workflow（多步驟編排）、Chaos Dashboard 視覺化 + experiment scope 控制。設計取捨偏向「K8s-native + GitOps-friendly + multi-fault types」、適合 K8s 為主的 chaos engineering。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>部署 Chaos Mesh 到 K8s cluster</li>
<li>設計 PodChaos / NetworkChaos / IOChaos experiment</li>
<li>用 Chaos Workflow 編排多步驟實驗 + steady state probe</li>
<li>控制 blast radius（namespace / labelSelector / mode）</li>
<li>跟 <a href="/blog/backend/06-reliability/experiment-safety-boundary/" data-link-title="6.20 Experiment Safety Boundary" data-link-desc="定義 chaos、load test、DR drill 的 [blast radius](/backend/knowledge-cards/blast-radius/)、停止條件與權限約束">6.20 Experiment Safety Boundary</a> 對齊 chaos 實驗審批</li>
</ol>
<h2 id="最短路徑5-分鐘把-chaos-mesh-跑起來">最短路徑：5 分鐘把 Chaos Mesh 跑起來</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 1. 安裝</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># TODO: curl -sSL https://mirrors.chaos-mesh.org/v2.7.0/install.sh | bash</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 2. 跑第一個 PodChaos</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="c1"># TODO: 寫 podchaos.yaml、kubectl apply</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="c1"># TODO: action: pod-kill / selector / mode</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl">
</span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="c1"># 3. Dashboard</span>
</span></span><span class="line"><span class="ln">9</span><span class="cl"><span class="c1"># TODO: kubectl port-forward svc/chaos-dashboard 2333:2333</span></span></span></code></pre></div><h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="crd-設計">CRD 設計</h3>
<p>子議題：</p>
<ul>
<li>PodChaos：pod-kill / pod-failure / container-kill</li>
<li>NetworkChaos：delay / loss / duplicate / corrupt / partition</li>
<li>IOChaos：delay / errno / mistake / attrOverride</li>
<li>StressChaos：CPU / memory pressure</li>
<li>對應 GitOps：Helm / Kustomize 管 experiment</li>
</ul>
<h3 id="chaos-workflow">Chaos Workflow</h3>
<p>子議題：</p>
<ul>
<li>多步驟 chaos 編排（serial / parallel）</li>
<li>Suspend / resume 控制</li>
<li>Probe（steady state validation）</li>
<li>對應 <a href="/blog/backend/06-reliability/experiment-safety-boundary/" data-link-title="6.20 Experiment Safety Boundary" data-link-desc="定義 chaos、load test、DR drill 的 [blast radius](/backend/knowledge-cards/blast-radius/)、停止條件與權限約束">6.20 Experiment Safety Boundary</a></li>
</ul>
<h3 id="chaos-dashboard">Chaos Dashboard</h3>
<p>子議題：</p>
<ul>
<li>視覺化 experiment timeline</li>
<li>Experiment archive</li>
<li>Event log</li>
<li>RBAC</li>
</ul>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<h3 id="blast-radius-控制">Blast radius 控制</h3>
<p>子議題：</p>
<ul>
<li>namespace 限制</li>
<li>labelSelector / value mode（one / all / fixed / fixed-percent / random-max-percent）</li>
<li>annotationSelector</li>
<li>Pause / resume 緊急中止</li>
</ul>
<h3 id="schedule-與-gitops">Schedule 與 GitOps</h3>
<p>子議題：</p>
<ul>
<li>Schedule CRD 定期 chaos</li>
<li>ArgoCD / Flux 整合</li>
<li>Experiment as code review</li>
</ul>
<h3 id="跟-litmuschaos--gremlin-對比">跟 LitmusChaos / Gremlin 對比</h3>
<p>子議題：</p>
<ul>
<li>Chaos Mesh：CRD-driven、PingCAP 主導</li>
<li>LitmusChaos：ChaosHub experiment / CNCF graduated</li>
<li>Gremlin：商業 SaaS、跨平台</li>
<li>選擇判讀：K8s OSS first → Chaos Mesh / Litmus；商業跨平台 → Gremlin</li>
</ul>
<h3 id="steady-state-驗證">Steady state 驗證</h3>
<p>子議題：</p>
<ul>
<li>HTTP / TCP / Pod / podHTTPChaos</li>
<li>Probe success threshold</li>
<li>跟 <a href="/blog/backend/09-performance-capacity/" data-link-title="模組九：效能工程與容量規劃" data-link-desc="把『目前配置能撐多少、要加多少機器』變成可量化、可驗證、可改進的工程流程">9.13 SLO</a> 對應 burn rate</li>
</ul>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<h3 id="experiment-沒生效">Experiment 沒生效</h3>
<p>操作原則：先 <code>kubectl describe podchaos</code> 看 status、再看 webhook + RBAC。</p>
<h3 id="blast-radius-過大">Blast radius 過大</h3>
<p>操作原則：mode 設 all 或 percent 設太高、影響超出預期。預防：先 dry-run / staging 測試。</p>
<h3 id="pause-不及時">Pause 不及時</h3>
<p>操作原則：experiment running 中要 pause、不是 delete（delete 不會 cleanup state）。</p>
<h3 id="dashboard-連不上">Dashboard 連不上</h3>
<p>操作原則：service 沒暴露、RBAC 不對。</p>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>非 K8s 環境</td>
          <td><a href="/blog/backend/06-reliability/vendors/gremlin/" data-link-title="Gremlin" data-link-desc="商業 chaos engineering 平台、跨平台與 GameDay">Gremlin</a> / <a href="/blog/backend/06-reliability/vendors/toxiproxy/" data-link-title="Toxiproxy" data-link-desc="TCP-level fault injection proxy（Shopify 開源）">Toxiproxy</a></td>
      </tr>
      <tr>
          <td>AWS-native chaos</td>
          <td>AWS Fault Injection Service</td>
      </tr>
      <tr>
          <td>K8s + ChaosHub experiment</td>
          <td><a href="/blog/backend/06-reliability/vendors/litmuschaos/" data-link-title="LitmusChaos" data-link-desc="Kubernetes chaos engineering 平台（CNCF graduated）">LitmusChaos</a></td>
      </tr>
      <tr>
          <td>Integration test 模擬故障</td>
          <td><a href="/blog/backend/06-reliability/vendors/toxiproxy/" data-link-title="Toxiproxy" data-link-desc="TCP-level fault injection proxy（Shopify 開源）">Toxiproxy</a></td>
      </tr>
      <tr>
          <td>商業 + GameDay 設計</td>
          <td><a href="/blog/backend/06-reliability/vendors/gremlin/" data-link-title="Gremlin" data-link-desc="商業 chaos engineering 平台、跨平台與 GameDay">Gremlin</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>完整 CRD spec</li>
<li>Chaos Mesh internal architecture</li>
<li>各 fault type 詳細 parameter</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<table>
  <thead>
      <tr>
          <th>案例方向</th>
          <th>對應主題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/06-reliability/cases/netflix/steady-state-chaos-and-fit/" data-link-title="Netflix：Steady State、Chaos 與 FIT 的驗證路徑" data-link-desc="把故障注入從工具操作升級成可驗證流程：先定義穩態，再設計注入與回復條件。">Netflix：Steady State、Chaos 與 FIT</a></td>
          <td>steady state hypothesis 對應 Chaos Workflow Probe</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/06-reliability/cases/netflix/chaos-monkey-business-hours-guardrails/" data-link-title="Netflix：Business-Hours Chaos 與 Guardrails" data-link-desc="Chaos Monkey 為何刻意在 business hours 執行：把即時應變能力納入驗證，並用 guardrails 限制實驗風險。">Netflix：Business-Hours Guardrails</a></td>
          <td>blast radius / pause / mode 控制對應時段策略</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/06-reliability/cases/pinterest/cache-reliability-and-capacity-surprises/" data-link-title="Pinterest：快取可靠性與容量驚奇治理" data-link-desc="針對快取層失效與流量突增，建立容量緩衝、退化路徑與重建節奏。">Pinterest：快取可靠性與容量驚奇</a></td>
          <td>NetworkChaos / StressChaos 模擬熱點與 cache failure mode</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/06-reliability/cases/google/error-budget-policy-and-release-gating/" data-link-title="Google：Error Budget 政策如何決定發布節奏" data-link-desc="把 SLO 消耗量轉成 release gate，讓可靠性與交付速度共用同一套決策語言。">Google：Error Budget 與 Release Gating</a></td>
          <td>chaos finding 對應 SLO burn rate 的回寫</td>
      </tr>
  </tbody>
</table>
<p><strong>待補 Chaos Mesh customer case</strong>：PingCAP / TiDB 客戶 Chaos Mesh 案例、CNCF Chaos Mesh adopters。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游概念：<a href="/blog/backend/06-reliability/experiment-safety-boundary/" data-link-title="6.20 Experiment Safety Boundary" data-link-desc="定義 chaos、load test、DR drill 的 [blast radius](/backend/knowledge-cards/blast-radius/)、停止條件與權限約束">6.20 Experiment Safety Boundary</a></li>
<li>平行 vendor：<a href="/blog/backend/06-reliability/vendors/litmuschaos/" data-link-title="LitmusChaos" data-link-desc="Kubernetes chaos engineering 平台（CNCF graduated）">LitmusChaos</a>、<a href="/blog/backend/06-reliability/vendors/gremlin/" data-link-title="Gremlin" data-link-desc="商業 chaos engineering 平台、跨平台與 GameDay">Gremlin</a></li>
<li>下游能力：<a href="/blog/backend/08-incident-response/" data-link-title="模組八：事故處理與復盤" data-link-desc="用 IR 領域詞彙建問題節點、以服務級案例庫累積事故脈絡，先建概念與案例庫再進實作交接">8 incident response</a>（chaos finding 進 IR 流程）</li>
</ul>
]]></content:encoded></item><item><title>Terraform / OpenTofu</title><link>https://tarrragon.github.io/blog/backend/05-deployment-platform/vendors/terraform/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/05-deployment-platform/vendors/terraform/</guid><description>&lt;p>Terraform 是 HashiCorp 出品的 IaC 工具、承擔三個責任：declarative infrastructure 配置（HCL）、state-based reconciliation（plan → apply）、跨 provider 抽象（AWS / GCP / Azure / K8s / SaaS）。設計取捨偏向「state-driven + declarative + multi-cloud」、provider 生態最廣。2023 改 BSL 授權、社群 fork OpenTofu（Linux Foundation 託管、MPL 2.0）。&lt;/p>
&lt;p>對「跨雲基礎設施管理、團隊協作 IaC、需要 state + plan workflow」這條路徑、Terraform / OpenTofu 是首選。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>寫 HCL config（resource / variable / output / module）&lt;/li>
&lt;li>設定 remote state（S3 + DynamoDB lock / Terraform Cloud）&lt;/li>
&lt;li>設計 module + workspace 結構&lt;/li>
&lt;li>跑 plan / apply / destroy 工作流 + GitOps&lt;/li>
&lt;li>評估 Terraform vs OpenTofu vs Pulumi vs Crossplane&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑5-分鐘把-terraform-跑起來">最短路徑：5 分鐘把 Terraform 跑起來&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 1. 安裝&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">brew install hashicorp/tap/terraform &lt;span class="c1"># 或 brew install opentofu&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>




&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-hcl" data-lang="hcl">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 2. 寫 main.tf
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="k">terraform&lt;/span> {
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl"> &lt;span class="k">required_providers&lt;/span> {
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="n"> aws&lt;/span> &lt;span class="o">=&lt;/span>&lt;span class="n"> { source&lt;/span> &lt;span class="o">=&lt;/span>&lt;span class="n"> &amp;#34;hashicorp/aws&amp;#34;, version&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;~&amp;gt; 5.0&amp;#34;&lt;/span> }
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl"> }
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">&lt;span class="n">provider &amp;#34;aws&amp;#34; { region&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;us-east-1&amp;#34;&lt;/span> }
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl">&lt;span class="n">resource &amp;#34;aws_s3_bucket&amp;#34; &amp;#34;demo&amp;#34; { bucket&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;my-tf-demo-bucket&amp;#34;&lt;/span> }&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>




&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 3. init + plan + apply&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">terraform init
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">terraform plan -out&lt;span class="o">=&lt;/span>plan.tfplan
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">terraform apply plan.tfplan&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="日常操作與決策形狀">日常操作與決策形狀&lt;/h2>
&lt;h3 id="hcl-config-結構">HCL config 結構&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>provider / resource / data source / variable / output / locals&lt;/li>
&lt;li>terraform block（required_version / required_providers / backend）&lt;/li>
&lt;li>Module（reusable group of resources）&lt;/li>
&lt;li>對應指令：&lt;code>terraform fmt&lt;/code>、&lt;code>terraform validate&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="state-管理">State 管理&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>Local state（terraform.tfstate）：dev / 學習用&lt;/li>
&lt;li>Remote state（S3 + DynamoDB lock / GCS / Terraform Cloud / Spacelift）&lt;/li>
&lt;li>State migration（terraform state mv / rm / import）&lt;/li>
&lt;li>State sensitive data 不入 git&lt;/li>
&lt;/ul>
&lt;h3 id="plan--apply-workflow">Plan / apply workflow&lt;/h3>
&lt;p>子議題：&lt;/p></description><content:encoded><![CDATA[<p>Terraform 是 HashiCorp 出品的 IaC 工具、承擔三個責任：declarative infrastructure 配置（HCL）、state-based reconciliation（plan → apply）、跨 provider 抽象（AWS / GCP / Azure / K8s / SaaS）。設計取捨偏向「state-driven + declarative + multi-cloud」、provider 生態最廣。2023 改 BSL 授權、社群 fork OpenTofu（Linux Foundation 託管、MPL 2.0）。</p>
<p>對「跨雲基礎設施管理、團隊協作 IaC、需要 state + plan workflow」這條路徑、Terraform / OpenTofu 是首選。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>寫 HCL config（resource / variable / output / module）</li>
<li>設定 remote state（S3 + DynamoDB lock / Terraform Cloud）</li>
<li>設計 module + workspace 結構</li>
<li>跑 plan / apply / destroy 工作流 + GitOps</li>
<li>評估 Terraform vs OpenTofu vs Pulumi vs Crossplane</li>
</ol>
<h2 id="最短路徑5-分鐘把-terraform-跑起來">最短路徑：5 分鐘把 Terraform 跑起來</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 1. 安裝</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">brew install hashicorp/tap/terraform   <span class="c1"># 或 brew install opentofu</span></span></span></code></pre></div>




<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-hcl" data-lang="hcl"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 2. 寫 main.tf
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"></span><span class="k">terraform</span> {
</span></span><span class="line"><span class="ln">3</span><span class="cl">  <span class="k">required_providers</span> {
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="n">    aws</span> <span class="o">=</span><span class="n"> { source</span> <span class="o">=</span><span class="n"> &#34;hashicorp/aws&#34;, version</span> <span class="o">=</span> <span class="s2">&#34;~&gt; 5.0&#34;</span> }
</span></span><span class="line"><span class="ln">5</span><span class="cl">  }
</span></span><span class="line"><span class="ln">6</span><span class="cl">}
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="n">provider &#34;aws&#34; { region</span> <span class="o">=</span> <span class="s2">&#34;us-east-1&#34;</span> }
</span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="n">resource &#34;aws_s3_bucket&#34; &#34;demo&#34; { bucket</span> <span class="o">=</span> <span class="s2">&#34;my-tf-demo-bucket&#34;</span> }</span></span></code></pre></div>




<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 3. init + plan + apply</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">terraform init
</span></span><span class="line"><span class="ln">3</span><span class="cl">terraform plan -out<span class="o">=</span>plan.tfplan
</span></span><span class="line"><span class="ln">4</span><span class="cl">terraform apply plan.tfplan</span></span></code></pre></div><h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="hcl-config-結構">HCL config 結構</h3>
<p>子議題：</p>
<ul>
<li>provider / resource / data source / variable / output / locals</li>
<li>terraform block（required_version / required_providers / backend）</li>
<li>Module（reusable group of resources）</li>
<li>對應指令：<code>terraform fmt</code>、<code>terraform validate</code></li>
</ul>
<h3 id="state-管理">State 管理</h3>
<p>子議題：</p>
<ul>
<li>Local state（terraform.tfstate）：dev / 學習用</li>
<li>Remote state（S3 + DynamoDB lock / GCS / Terraform Cloud / Spacelift）</li>
<li>State migration（terraform state mv / rm / import）</li>
<li>State sensitive data 不入 git</li>
</ul>
<h3 id="plan--apply-workflow">Plan / apply workflow</h3>
<p>子議題：</p>
<ul>
<li>terraform plan -out=plan.tfplan（凍結結果）</li>
<li>terraform apply plan.tfplan</li>
<li>Auto-approve（CI / CD）vs manual approve（critical）</li>
<li>對應 GitOps：Atlantis / Terraform Cloud / Spacelift</li>
</ul>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<h3 id="module-設計">Module 設計</h3>
<p>子議題：</p>
<ul>
<li>Module input / output</li>
<li>Module composition（root module → child module）</li>
<li>Public module registry（Terraform Registry / OpenTofu Registry）</li>
<li>Version pinning</li>
<li>對應 Terraform best practice</li>
</ul>
<h3 id="workspaces-vs-directory-layout">Workspaces vs directory layout</h3>
<p>子議題：</p>
<ul>
<li>Workspaces：同 module 多 instance（dev / staging / prod）</li>
<li>Directory：每 env 一個 directory</li>
<li>Workspaces 的局限（state 同 backend、env 共享 config）</li>
<li>選擇判讀：強隔離 → directory；快切換 → workspace</li>
</ul>
<h3 id="drift-detection">Drift detection</h3>
<p>子議題：</p>
<ul>
<li>Drift = 實際 infra ≠ Terraform state</li>
<li>偵測：<code>terraform plan</code> 跑出來有 diff</li>
<li>修法：Manual import / state pull / 修改 cloud directly + plan refresh</li>
<li>對應 自動化 drift detection（Atlantis / Driftctl）</li>
</ul>
<h3 id="terraform-vs-opentofu">Terraform vs OpenTofu</h3>
<p>子議題：</p>
<ul>
<li>2023 Terraform 改 BSL：Linux Foundation fork OpenTofu</li>
<li>OpenTofu 跟 Terraform 1.5 API 相容</li>
<li>之後分歧：OpenTofu 加 state encryption、provider iteration</li>
<li>遷移路徑：替換 binary、import 既有 state</li>
</ul>
<h3 id="provider-生態">Provider 生態</h3>
<p>子議題：</p>
<ul>
<li>AWS / Azure / GCP（cloud provider）</li>
<li>Kubernetes / Helm（K8s provider）</li>
<li>SaaS：Datadog / Pagerduty / Cloudflare / GitHub</li>
<li>Community provider vs official provider 品質差距</li>
</ul>
<h3 id="跟-crossplane--pulumi-對比">跟 Crossplane / Pulumi 對比</h3>
<p>子議題：</p>
<ul>
<li>Crossplane：K8s-native IaC（用 K8s CRD 管 cloud resource）</li>
<li>Pulumi：用通用語言（TS / Python / Go / C#）寫 IaC</li>
<li>選擇判讀：純 cloud infra → Terraform / OpenTofu；K8s-heavy → Crossplane；developer-first → Pulumi</li>
</ul>
<h3 id="terraform-cloud--spacelift--atlantis">Terraform Cloud / Spacelift / Atlantis</h3>
<p>子議題：</p>
<ul>
<li>Terraform Cloud（HashiCorp managed）：remote state + run + policy</li>
<li>Spacelift / env0：商業替代</li>
<li>Atlantis：OSS Pull Request automation</li>
<li>對應 GitOps for IaC</li>
</ul>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<h3 id="state-lock-stuck">State lock stuck</h3>
<p>操作原則：DynamoDB lock 沒釋放（process killed）。判讀 + 修法：<code>terraform force-unlock &lt;lock-id&gt;</code>（小心）。</p>
<h3 id="plan-diff-過大">Plan diff 過大</h3>
<p>操作原則：drift 累積 / provider 升級 / config 改太多。判讀：先看 plan output、再決定要不要 apply。</p>
<h3 id="provider-auth-fail">Provider auth fail</h3>
<p>操作原則：AWS / GCP credentials 沒設、過期、權限不夠。判讀：<code>AWS_PROFILE</code> / IAM role / GCP ADC 配置。</p>
<h3 id="module-version-衝突">Module version 衝突</h3>
<p>操作原則：root module 跟 child module 用不同 provider version。判讀：<code>terraform providers</code> 看 version constraint。</p>
<h3 id="apply-partial-failure">Apply partial failure</h3>
<p>操作原則：apply 中某 resource 失敗、state 一致性問題。判讀：state pull 看當前、可能要 import / state rm 修。</p>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>OSI-licensed Terraform</td>
          <td>OpenTofu（同模組）</td>
      </tr>
      <tr>
          <td>Imperative API</td>
          <td>Pulumi</td>
      </tr>
      <tr>
          <td>Cloud-specific（單一 cloud）</td>
          <td>CloudFormation / Azure Bicep / GCP Deployment Manager</td>
      </tr>
      <tr>
          <td>K8s-native IaC</td>
          <td>Crossplane</td>
      </tr>
      <tr>
          <td>Application config（不是 infra）</td>
          <td>Helm / Kustomize / cdk8s</td>
      </tr>
      <tr>
          <td>極小場景</td>
          <td>CLI / Cloud Shell（不用 IaC）</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>完整 HCL syntax reference</li>
<li>各 provider 完整 resource list</li>
<li>Terraform Cloud / Spacelift 商業 feature</li>
<li>Drift detection 工具細節</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<h3 id="跨-vendor-對照">跨 vendor 對照</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>對 Terraform 的對應</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/05-deployment-platform/cases/tradeshift-self-managed-k8s-to-eks/" data-link-title="5.C1 Tradeshift：self-managed Kubernetes 遷移到 EKS" data-link-desc="零停機平台遷移的分段策略案例。">5.C1 Tradeshift self-managed → EKS</a></td>
          <td>平台遷移期間舊 / 新叢集共通配置基線靠 IaC 表達、批次切流時 module 版本要凍結</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/05-deployment-platform/cases/conde-nast-platform-modernization-eks/" data-link-title="5.C2 Condé Nast：EKS 平台整併與標準化" data-link-desc="多地區異質 Kubernetes 平台整併為統一控制面的案例。">5.C2 Condé Nast EKS</a></td>
          <td>多團隊異質集群盤點後、用 module + workspace 把平台基線變成統一可審計的 IaC</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/05-deployment-platform/cases/miro-managed-eks-migration/" data-link-title="5.C5 Miro：Managed EKS 遷移" data-link-desc="從自維運平台轉向 managed EKS 的組織與技術協同案例。">5.C5 Miro EKS</a></td>
          <td>Managed EKS 後平台團隊把手動操作改成 IaC + GitOps、自動化取代手動操作</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/05-deployment-platform/cases/contrast-platform-migration-by-scale/" data-link-title="5.C10 對照：規模差異下的平台遷移" data-link-desc="平台遷移策略在小中大型組織下的差異。">5.C10 規模對照</a></td>
          <td>小型 CLI / 中型單 workspace / 大型 multi-workspace + Atlantis / Spacelift 治理</td>
      </tr>
  </tbody>
</table>
<p><strong>待補 Terraform 案例</strong>：HashiCorp Cloud 大客戶案例、OpenTofu fork 後企業遷移案例、Drift detection 治理案例。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游概念：<a href="/blog/backend/05-deployment-platform/" data-link-title="模組五：部署平台與網路入口" data-link-desc="整理 Kubernetes、systemd、load balancer、container 與服務生命週期合約">5 deployment platform</a></li>
<li>平行 vendor：<a href="/blog/backend/05-deployment-platform/vendors/kubernetes/" data-link-title="Kubernetes" data-link-desc="Container orchestration 主流、GKE / EKS / AKS / 自管">Kubernetes</a>（K8s provider）</li>
<li>下游能力：<a href="/blog/backend/06-reliability/" data-link-title="模組六：可靠性驗證流程" data-link-desc="用 SRE 領域詞彙建問題節點、以服務級案例庫累積驗證脈絡，先建概念與案例庫再進實作交接">06 reliability</a>（IaC GitOps + release gate）</li>
</ul>
]]></content:encoded></item><item><title>Caffeine</title><link>https://tarrragon.github.io/blog/backend/02-cache-redis/vendors/caffeine/</link><pubDate>Tue, 16 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/02-cache-redis/vendors/caffeine/</guid><description>&lt;p>Caffeine 是 JVM 上的 high-performance process-local cache library、承擔三個責任：在 application 進程內（on-heap）提供奈秒到微秒級的 cache（沒有網路往返）、用 Window TinyLFU 淘汰演算法逼近最佳命中率（優於傳統 LRU）、提供 expire / refresh / size-based eviction 等完整 cache 語意。設計取捨偏向「最低延遲 + 最高命中率 + 嵌進 application」、是 Redis 之外的另一層 cache，不是 Redis 的替代。&lt;/p>
&lt;p>對「每個請求重複讀同一份小資料、Redis 的網路往返都嫌慢、資料可在每個實例各存一份」這條路徑、Caffeine 是 process-local 層的標準選擇。它常跟 Redis 組成兩層 cache（Caffeine L1 + Redis L2）、不是二選一。Caffeine 是 &lt;a href="https://github.com/google/guava">Guava Cache&lt;/a> 的後繼、由同作者重寫、Spring Boot 等框架的預設 local cache。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>用 Maven / Gradle 引入 Caffeine、寫出基本 cache&lt;/li>
&lt;li>理解 Window TinyLFU 為何命中率優於 LRU&lt;/li>
&lt;li>設計 expire-after-write / refresh-after-write / 容量上限&lt;/li>
&lt;li>判斷 process-local cache 跟 Redis 的兩層 cache 分工&lt;/li>
&lt;li>評估跨實例 invalidation 的限制與 GC 壓力&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑引入-caffeine-寫一個-cache">最短路徑：引入 Caffeine 寫一個 cache&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-xml" data-lang="xml">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c">&amp;lt;!-- Maven 依賴（version 為範例、實際以 Maven Central 最新為準、最後檢查日 2026-06-16）--&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="nt">&amp;lt;dependency&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl"> &lt;span class="nt">&amp;lt;groupId&amp;gt;&lt;/span>com.github.ben-manes.caffeine&lt;span class="nt">&amp;lt;/groupId&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"> &lt;span class="nt">&amp;lt;artifactId&amp;gt;&lt;/span>caffeine&lt;span class="nt">&amp;lt;/artifactId&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl"> &lt;span class="nt">&amp;lt;version&amp;gt;&lt;/span>3.2.4&lt;span class="nt">&amp;lt;/version&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">&lt;span class="nt">&amp;lt;/dependency&amp;gt;&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>




&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-java" data-lang="java">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c1">// 基本 cache：容量上限 10000、寫入後 5 分鐘過期&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="n">Cache&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">String&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">User&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">cache&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Caffeine&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">newBuilder&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">maximumSize&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">10_000&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">expireAfterWrite&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Duration&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">ofMinutes&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">5&lt;/span>&lt;span class="p">))&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">build&lt;/span>&lt;span class="p">();&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="n">cache&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">put&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;user:123&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">user&lt;/span>&lt;span class="p">);&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="n">User&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">u&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">cache&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">getIfPresent&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;user:123&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c1">// loading cache：miss 時自動回源（取代手寫 cache-aside）&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="n">LoadingCache&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">String&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">User&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">loading&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Caffeine&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">newBuilder&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">maximumSize&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">10_000&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">refreshAfterWrite&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Duration&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">ofMinutes&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">1&lt;/span>&lt;span class="p">))&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c1">// 背景非同步 refresh、不阻塞讀&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">build&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">key&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">userRepository&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">findById&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">key&lt;/span>&lt;span class="p">));&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c1">// miss / refresh 時呼叫&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="n">User&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">u2&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">loading&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;user:123&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Caffeine 是 library 不是 server、跑在 application JVM 內、無法 docker 獨立驗證；上面是依官方 API 的範例（API 以 &lt;a href="https://github.com/ben-manes/caffeine/wiki">Caffeine wiki&lt;/a> 為準）。&lt;/p>
&lt;h2 id="日常操作與決策形狀">日常操作與決策形狀&lt;/h2>
&lt;h3 id="淘汰與過期策略">淘汰與過期策略&lt;/h3>
&lt;p>Caffeine 把 cache 行為拆成幾個正交的旋鈕。子議題：&lt;/p>
&lt;ul>
&lt;li>&lt;code>maximumSize&lt;/code> / &lt;code>maximumWeight&lt;/code>：容量上限（筆數或加權大小）、超過用 W-TinyLFU 淘汰&lt;/li>
&lt;li>&lt;code>expireAfterWrite&lt;/code>：寫入後固定時間過期（資料新鮮度上限）&lt;/li>
&lt;li>&lt;code>expireAfterAccess&lt;/code>：最後存取後過期（淘汰冷資料）&lt;/li>
&lt;li>&lt;code>refreshAfterWrite&lt;/code>：到期後背景 refresh、舊值先服務、不阻塞（跟 expire 不同）&lt;/li>
&lt;/ul>
&lt;h3 id="window-tinylfu-淘汰">Window TinyLFU 淘汰&lt;/h3>
&lt;p>子議題：&lt;/p></description><content:encoded><![CDATA[<p>Caffeine 是 JVM 上的 high-performance process-local cache library、承擔三個責任：在 application 進程內（on-heap）提供奈秒到微秒級的 cache（沒有網路往返）、用 Window TinyLFU 淘汰演算法逼近最佳命中率（優於傳統 LRU）、提供 expire / refresh / size-based eviction 等完整 cache 語意。設計取捨偏向「最低延遲 + 最高命中率 + 嵌進 application」、是 Redis 之外的另一層 cache，不是 Redis 的替代。</p>
<p>對「每個請求重複讀同一份小資料、Redis 的網路往返都嫌慢、資料可在每個實例各存一份」這條路徑、Caffeine 是 process-local 層的標準選擇。它常跟 Redis 組成兩層 cache（Caffeine L1 + Redis L2）、不是二選一。Caffeine 是 <a href="https://github.com/google/guava">Guava Cache</a> 的後繼、由同作者重寫、Spring Boot 等框架的預設 local cache。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>用 Maven / Gradle 引入 Caffeine、寫出基本 cache</li>
<li>理解 Window TinyLFU 為何命中率優於 LRU</li>
<li>設計 expire-after-write / refresh-after-write / 容量上限</li>
<li>判斷 process-local cache 跟 Redis 的兩層 cache 分工</li>
<li>評估跨實例 invalidation 的限制與 GC 壓力</li>
</ol>
<h2 id="最短路徑引入-caffeine-寫一個-cache">最短路徑：引入 Caffeine 寫一個 cache</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-xml" data-lang="xml"><span class="line"><span class="ln">1</span><span class="cl"><span class="c">&lt;!-- Maven 依賴（version 為範例、實際以 Maven Central 最新為準、最後檢查日 2026-06-16）--&gt;</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="nt">&lt;dependency&gt;</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">  <span class="nt">&lt;groupId&gt;</span>com.github.ben-manes.caffeine<span class="nt">&lt;/groupId&gt;</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">  <span class="nt">&lt;artifactId&gt;</span>caffeine<span class="nt">&lt;/artifactId&gt;</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">  <span class="nt">&lt;version&gt;</span>3.2.4<span class="nt">&lt;/version&gt;</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="nt">&lt;/dependency&gt;</span></span></span></code></pre></div>




<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1">// 基本 cache：容量上限 10000、寫入後 5 分鐘過期</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="w"></span><span class="n">Cache</span><span class="o">&lt;</span><span class="n">String</span><span class="p">,</span><span class="w"> </span><span class="n">User</span><span class="o">&gt;</span><span class="w"> </span><span class="n">cache</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Caffeine</span><span class="p">.</span><span class="na">newBuilder</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="w">    </span><span class="p">.</span><span class="na">maximumSize</span><span class="p">(</span><span class="n">10_000</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="w">    </span><span class="p">.</span><span class="na">expireAfterWrite</span><span class="p">(</span><span class="n">Duration</span><span class="p">.</span><span class="na">ofMinutes</span><span class="p">(</span><span class="n">5</span><span class="p">))</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="w">    </span><span class="p">.</span><span class="na">build</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="w"></span><span class="n">cache</span><span class="p">.</span><span class="na">put</span><span class="p">(</span><span class="s">&#34;user:123&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">user</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="w"></span><span class="n">User</span><span class="w"> </span><span class="n">u</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cache</span><span class="p">.</span><span class="na">getIfPresent</span><span class="p">(</span><span class="s">&#34;user:123&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="w"></span><span class="c1">// loading cache：miss 時自動回源（取代手寫 cache-aside）</span><span class="w">
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="w"></span><span class="n">LoadingCache</span><span class="o">&lt;</span><span class="n">String</span><span class="p">,</span><span class="w"> </span><span class="n">User</span><span class="o">&gt;</span><span class="w"> </span><span class="n">loading</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Caffeine</span><span class="p">.</span><span class="na">newBuilder</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="w">    </span><span class="p">.</span><span class="na">maximumSize</span><span class="p">(</span><span class="n">10_000</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="w">    </span><span class="p">.</span><span class="na">refreshAfterWrite</span><span class="p">(</span><span class="n">Duration</span><span class="p">.</span><span class="na">ofMinutes</span><span class="p">(</span><span class="n">1</span><span class="p">))</span><span class="w">   </span><span class="c1">// 背景非同步 refresh、不阻塞讀</span><span class="w">
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="w">    </span><span class="p">.</span><span class="na">build</span><span class="p">(</span><span class="n">key</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="n">userRepository</span><span class="p">.</span><span class="na">findById</span><span class="p">(</span><span class="n">key</span><span class="p">));</span><span class="w"> </span><span class="c1">// miss / refresh 時呼叫</span><span class="w">
</span></span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="w"></span><span class="n">User</span><span class="w"> </span><span class="n">u2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">loading</span><span class="p">.</span><span class="na">get</span><span class="p">(</span><span class="s">&#34;user:123&#34;</span><span class="p">);</span></span></span></code></pre></div><p>Caffeine 是 library 不是 server、跑在 application JVM 內、無法 docker 獨立驗證；上面是依官方 API 的範例（API 以 <a href="https://github.com/ben-manes/caffeine/wiki">Caffeine wiki</a> 為準）。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="淘汰與過期策略">淘汰與過期策略</h3>
<p>Caffeine 把 cache 行為拆成幾個正交的旋鈕。子議題：</p>
<ul>
<li><code>maximumSize</code> / <code>maximumWeight</code>：容量上限（筆數或加權大小）、超過用 W-TinyLFU 淘汰</li>
<li><code>expireAfterWrite</code>：寫入後固定時間過期（資料新鮮度上限）</li>
<li><code>expireAfterAccess</code>：最後存取後過期（淘汰冷資料）</li>
<li><code>refreshAfterWrite</code>：到期後背景 refresh、舊值先服務、不阻塞（跟 expire 不同）</li>
</ul>
<h3 id="window-tinylfu-淘汰">Window TinyLFU 淘汰</h3>
<p>子議題：</p>
<ul>
<li>W-TinyLFU 結合 recency（window）+ frequency（TinyLFU sketch）、命中率逼近最佳</li>
<li>比 LRU 更抗一次性掃描污染（scan resistance）、跟 <a href="/blog/backend/02-cache-redis/vendors/redis/memory-eviction-tuning/" data-link-title="Redis 記憶體與淘汰調校：maxmemory-policy、LFU 與碎片化的實戰判讀" data-link-desc="Redis 的記憶體是一條會在半夜爆掉的曲線：maxmemory 設多少、policy 選 LRU 還 LFU、碎片化什麼時候開始吃掉 30% RAM、OOM 時 noeviction 怎麼讓寫入全部失敗。本文展開 Redis 記憶體會計模型、eviction policy 的選型判讀、5 個把記憶體配置寫成 production 事故的踩坑，以及單機記憶體撞牆後該往 cluster 還是 DragonflyDB 走的邊界">Redis LFU</a> 的動機類似但演算法更先進</li>
<li>frequency 用 count-min sketch 近似、記憶體開銷小</li>
</ul>
<h3 id="兩層-cachel1-caffeine--l2-redis">兩層 cache（L1 Caffeine + L2 Redis）</h3>
<p>子議題：</p>
<ul>
<li>L1 Caffeine（process-local、奈秒級、每實例一份）擋掉大部分讀</li>
<li>L2 Redis（共享、毫秒級、跨實例一致）擋掉 L1 miss</li>
<li>對應 <a href="/blog/backend/02-cache-redis/high-concurrency-access/" data-link-title="2.1 高併發下的 Redis 讀寫邊界" data-link-desc="說明高併發服務如何共用 Redis client、控制 pipeline 與避免 cache stampede">2.6 high concurrency 的 hot key 兩層解法</a></li>
</ul>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<h3 id="跨實例-invalidation-的根本限制">跨實例 invalidation 的根本限制</h3>
<p>子議題：</p>
<ul>
<li>每個 JVM 實例有自己的 Caffeine 副本、一個實例更新不會通知其他實例</li>
<li>解法：短 TTL 容忍 stale、或用 Redis pub/sub 廣播 invalidation 訊息給各實例</li>
<li>這是 process-local cache 的固有取捨：最低延遲換來最弱的跨實例一致性</li>
</ul>
<h3 id="gc-壓力與-on-heap-vs-off-heap">GC 壓力與 on-heap vs off-heap</h3>
<p>子議題：</p>
<ul>
<li>Caffeine 預設 on-heap、大 cache 會增加 JVM heap 與 GC 壓力</li>
<li>容量上限要對齊 heap 預算、避免 cache 把 heap 撐爆觸發 full GC</li>
<li>極大 local cache 考慮 off-heap 方案（如 Ehcache 的 off-heap tier），但 Caffeine 本身專注 on-heap</li>
</ul>
<h3 id="async-與-refresh-語意">async 與 refresh 語意</h3>
<p>子議題：</p>
<ul>
<li><code>AsyncCache</code> / <code>AsyncLoadingCache</code>：回傳 CompletableFuture、不阻塞 caller</li>
<li><code>refreshAfterWrite</code>：到期後第一個讀觸發背景 refresh、舊值立即回、避免 <a href="/blog/backend/02-cache-redis/cases/failure-cache-stampede-rollout-regression/" data-link-title="2.C9 反例：快取切換引發 Stampede 回歸" data-link-desc="快取策略切換若缺乏保護，會導致回源壓力與錯誤率連鎖上升。">stampede</a></li>
<li>refresh vs expire 的差異是「舊值能不能先服務」</li>
</ul>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<h3 id="跨實例讀到舊值">跨實例讀到舊值</h3>
<p>操作原則：process-local cache 各實例獨立、更新不傳播。判讀：縮短 TTL 容忍 stale、或加 Redis pub/sub 廣播 invalidation；強一致需求不該用 process-local cache。</p>
<h3 id="命中率低--cache-沒效果">命中率低 / cache 沒效果</h3>
<p>操作原則：先看 <code>maximumSize</code> 是否太小（working set 放不下）、再看 TTL 是否太短。判讀：用 <code>recordStats()</code> 看 hit rate / eviction count、對齊 working set。</p>
<h3 id="full-gc-頻繁">Full GC 頻繁</h3>
<p>操作原則：on-heap cache 太大撐爆 heap。判讀：降 <code>maximumSize</code> 或用 <code>maximumWeight</code> 控制實際記憶體、對齊 JVM heap 預算。</p>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>需要跨實例共享 / 一致</td>
          <td><a href="/blog/backend/02-cache-redis/vendors/redis/" data-link-title="Redis" data-link-desc="OSS in-memory data structure store、cache 主流">Redis / Valkey</a>（共享 cache 層）</td>
      </tr>
      <tr>
          <td>非 JVM 語言</td>
          <td>該語言的 process-local cache（Go ristretto、Python cachetools 等）</td>
      </tr>
      <tr>
          <td>需要持久化 / durable</td>
          <td>Redis with AOF / AWS MemoryDB</td>
      </tr>
      <tr>
          <td>極大 cache 超過 heap</td>
          <td>off-heap cache（Ehcache off-heap）或外部 cache（Redis）</td>
      </tr>
      <tr>
          <td>不想管容量 / serverless</td>
          <td><a href="/blog/backend/02-cache-redis/vendors/momento/" data-link-title="Momento" data-link-desc="Serverless cache、按用量計費、無容量規劃">Momento</a>（serverless、但有網路延遲）</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Caffeine 完整 API（以官方 wiki 為準）</li>
<li>各 JVM 框架（Spring Cache abstraction）的整合細節</li>
<li>Guava Cache 到 Caffeine 的完整 API 對照</li>
<li>off-heap cache 方案比較</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<h3 id="跨-vendor-對照本模組-case-庫暫無-caffeine-specific-case">跨 vendor 對照（本模組 case 庫暫無 Caffeine-specific case）</h3>
<p>Caffeine 是 library 層元件、本 blog cache case 庫（Meta / Shopify / Netflix / Cloudflare / Tinder / Tubi / Snap）暫無 Caffeine-specific case。以下用 process-local 的角度對照。</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>對 Caffeine 的對應</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/meta-cachelib-kangaroo-tiered-cache/" data-link-title="2.C4 Meta：CacheLib / Kangaroo 分層快取" data-link-desc="快取從 DRAM-only 轉向分層快取架構的實務案例。">2.C4 Meta CacheLib + Kangaroo</a></td>
          <td>CacheLib 是 C++ 的 process-local + flash 分層 library、Caffeine 是 JVM 的 on-heap 對應</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/cases/meta-tao-social-graph-cache-evolution/" data-link-title="2.C8 Meta：TAO 社交圖快取演進" data-link-desc="社交圖查詢在規模化下如何把快取做成資料層能力。">2.C8 Meta TAO</a></td>
          <td>TAO 有 application-tier local cache、process-local 擋掉大部分讀的思路一致</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/cases/tinder-elasticache-valkey-matching/" data-link-title="9.C6 Tinder：ElastiCache for Valkey 撐 4700 萬月活的配對引擎" data-link-desc="Tinder 用 Amazon ElastiCache for Valkey 提供配對引擎所需的次毫秒延遲快取層">9.C6 Tinder</a></td>
          <td>每次互動查多個 cache、process-local L1 可擋掉重複讀、降低 L2（Redis）的 RTT 壓力</td>
      </tr>
  </tbody>
</table>
<p><strong>待補 Caffeine-specific 案例</strong>：L1 Caffeine + L2 Redis 兩層 cache 的 production 命中率分層數據、跨實例 invalidation 的 Redis pub/sub 廣播實作、W-TinyLFU vs LRU 的實測命中率對照。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>deep article：<a href="/blog/backend/02-cache-redis/vendors/caffeine/two-tier-cache-invalidation/" data-link-title="Caffeine &#43; Redis 兩層 cache：搭起來很容易，跨實例失效才是全部的問題" data-link-desc="L1 Caffeine（process-local）&#43; L2 Redis（共享）的兩層 cache 程式碼三十行就寫完，但每個 JVM 實例有自己的 L1 副本、一個實例更新不會通知其他實例——跨實例 invalidation 才是這個架構的全部難度。本文展開兩層讀寫路徑、用 Redis pub/sub 廣播失效、5 個把 L1 stale 與 GC 寫成事故的 production 踩坑，以及哪些資料適合放 L1">Caffeine + Redis 兩層 cache 與跨實例失效</a>（L1+L2 + pub/sub 廣播失效）</li>
<li>上游概念：<a href="/blog/backend/02-cache-redis/high-concurrency-access/" data-link-title="2.1 高併發下的 Redis 讀寫邊界" data-link-desc="說明高併發服務如何共用 Redis client、控制 pipeline 與避免 cache stampede">2.6 high concurrency</a>（hot key 兩層解法）、<a href="/blog/backend/02-cache-redis/ttl-eviction/" data-link-title="2.3 TTL 與 eviction" data-link-desc="整理過期策略、容量控制與熱點資料">2.3 TTL eviction</a></li>
<li>平行 vendor：<a href="/blog/backend/02-cache-redis/vendors/redis/" data-link-title="Redis" data-link-desc="OSS in-memory data structure store、cache 主流">Redis</a>（兩層 cache 的 L2）、<a href="/blog/backend/02-cache-redis/vendors/momento/" data-link-title="Momento" data-link-desc="Serverless cache、按用量計費、無容量規劃">Momento</a>（另一端：serverless）</li>
<li>下游能力：<a href="/blog/backend/02-cache-redis/cache-copy-freshness-boundary/" data-link-title="2.7 Cache Copy Boundary 與 Freshness" data-link-desc="說明快取何時只是可重建副本，何時會影響交易、權限或配額正確性。">2.7 cache copy boundary</a>（跨實例一致性窗口）</li>
</ul>
]]></content:encoded></item><item><title>cert-manager</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/cert-manager/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/cert-manager/</guid><description>&lt;p>cert-manager 是 K8s 原生的 &lt;em>certificate lifecycle automation&lt;/em> — 把「拿 cert、放 cert、定期 renew」這條從以前需要 cron + certbot + 手動 reload 的鏈、轉成 &lt;em>declarative + controller pattern&lt;/em>。使用者在 cluster 內 apply 一個 &lt;code>Certificate&lt;/code> resource、cert-manager controller 自動跟 issuer 對話、把 cert 存進 Secret、在 lifetime 2/3 點觸發 renew。它把 cert 這件事接進 K8s 控制循環、跟 Pod / Service / Ingress 同等地位的 first-class resource、層級高於 certbot 的 K8s 移植。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>cert-manager 的核心責任是 &lt;em>K8s cluster 內所有 cert 的生命週期治理&lt;/em>。從 Ingress / Gateway 對外 TLS、internal service mTLS、到 workload-level 短期 cert、都用同一套 declarative model 表達。Issuer 抽象讓底層 cert 來源可換 — 公開 cert 走 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/letsencrypt/" data-link-title="Let&amp;#39;s Encrypt" data-link-desc="免費 &amp;#43; 自動化的公共 ACME CA、90 天 TTL 強制自動化、跨雲跨平台 public TLS cert 的事實基礎">Let&amp;rsquo;s Encrypt&lt;/a> ACME、內部 cert 走 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault PKI engine&lt;/a> 或 self-signed CA、企業環境走 Venafi 或 AWS PCA — 上層 &lt;code>Certificate&lt;/code> spec 不變。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-acm/" data-link-title="AWS ACM" data-link-desc="AWS-managed certificate provisioning、DNS validation &amp;#43; auto-renewal、整合 ELB / CloudFront / API Gateway、Private CA 後端">AWS ACM&lt;/a> 的差異是 &lt;em>cert 的部署面&lt;/em>：ACM 是 AWS-managed cert、只能掛在 AWS service（ELB / CloudFront / API Gateway）、私鑰永不離 AWS；cert-manager 是 K8s-native client、cert 放在 cluster 內的 Secret、可以掛任何 ingress controller 或 workload mTLS。跟 Let&amp;rsquo;s Encrypt 的關係是 &lt;em>client vs issuer&lt;/em> — cert-manager 是 ACME client、Let&amp;rsquo;s Encrypt 是 ACME server、不是替代關係。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/spire/" data-link-title="SPIRE" data-link-desc="SPIFFE Runtime Environment、attested workload identity、short-lived SVID &amp;#43; Trust Bundle、跨組織 federation">SPIRE&lt;/a> 的差異是 &lt;em>身份模型&lt;/em> — cert-manager 給 &lt;em>DNS-named cert&lt;/em>（CN / SAN 是 hostname）、SPIRE 給 &lt;em>SPIFFE ID-based workload identity&lt;/em>（&lt;code>spiffe://trust-domain/workload&lt;/code>）、兩者互補不衝突。&lt;/p></description><content:encoded><![CDATA[<p>cert-manager 是 K8s 原生的 <em>certificate lifecycle automation</em> — 把「拿 cert、放 cert、定期 renew」這條從以前需要 cron + certbot + 手動 reload 的鏈、轉成 <em>declarative + controller pattern</em>。使用者在 cluster 內 apply 一個 <code>Certificate</code> resource、cert-manager controller 自動跟 issuer 對話、把 cert 存進 Secret、在 lifetime 2/3 點觸發 renew。它把 cert 這件事接進 K8s 控制循環、跟 Pod / Service / Ingress 同等地位的 first-class resource、層級高於 certbot 的 K8s 移植。</p>
<h2 id="服務定位">服務定位</h2>
<p>cert-manager 的核心責任是 <em>K8s cluster 內所有 cert 的生命週期治理</em>。從 Ingress / Gateway 對外 TLS、internal service mTLS、到 workload-level 短期 cert、都用同一套 declarative model 表達。Issuer 抽象讓底層 cert 來源可換 — 公開 cert 走 <a href="/blog/backend/07-security-data-protection/vendors/letsencrypt/" data-link-title="Let&#39;s Encrypt" data-link-desc="免費 &#43; 自動化的公共 ACME CA、90 天 TTL 強制自動化、跨雲跨平台 public TLS cert 的事實基礎">Let&rsquo;s Encrypt</a> ACME、內部 cert 走 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault PKI engine</a> 或 self-signed CA、企業環境走 Venafi 或 AWS PCA — 上層 <code>Certificate</code> spec 不變。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/aws-acm/" data-link-title="AWS ACM" data-link-desc="AWS-managed certificate provisioning、DNS validation &#43; auto-renewal、整合 ELB / CloudFront / API Gateway、Private CA 後端">AWS ACM</a> 的差異是 <em>cert 的部署面</em>：ACM 是 AWS-managed cert、只能掛在 AWS service（ELB / CloudFront / API Gateway）、私鑰永不離 AWS；cert-manager 是 K8s-native client、cert 放在 cluster 內的 Secret、可以掛任何 ingress controller 或 workload mTLS。跟 Let&rsquo;s Encrypt 的關係是 <em>client vs issuer</em> — cert-manager 是 ACME client、Let&rsquo;s Encrypt 是 ACME server、不是替代關係。跟 <a href="/blog/backend/07-security-data-protection/vendors/spire/" data-link-title="SPIRE" data-link-desc="SPIFFE Runtime Environment、attested workload identity、short-lived SVID &#43; Trust Bundle、跨組織 federation">SPIRE</a> 的差異是 <em>身份模型</em> — cert-manager 給 <em>DNS-named cert</em>（CN / SAN 是 hostname）、SPIRE 給 <em>SPIFFE ID-based workload identity</em>（<code>spiffe://trust-domain/workload</code>）、兩者互補不衝突。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>cert-manager 用 Issuer / ClusterIssuer 哪個、配什麼 issuer backend（Let&rsquo;s Encrypt / Vault PKI / self-signed / 公司 CA）</li>
<li>Challenge solver 選 HTTP01 還是 DNS01、為什麼 wildcard cert 必須用 DNF01</li>
<li>Auto-renewal 觸發點、renew 失敗的 alert 時機、跟 Ingress / Gateway API 整合的 annotation</li>
<li>何時用 cert-manager、何時改走 <a href="/blog/backend/07-security-data-protection/vendors/aws-acm/" data-link-title="AWS ACM" data-link-desc="AWS-managed certificate provisioning、DNS validation &#43; auto-renewal、整合 ELB / CloudFront / API Gateway、Private CA 後端">ACM</a>（雲端原生 service）或 <a href="/blog/backend/07-security-data-protection/vendors/spire/" data-link-title="SPIRE" data-link-desc="SPIFFE Runtime Environment、attested workload identity、short-lived SVID &#43; Trust Bundle、跨組織 federation">SPIRE</a>（workload identity）</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 cert-manager 部署是否健康、最少看四件事：</p>
<ul>
<li><strong>Issuer 配置</strong>：是 <code>ClusterIssuer</code>（cluster-wide）還是 <code>Issuer</code>（namespace-scoped）、backend 是哪一種（acme / vault / ca / venafi）、credential（ACME private key、Vault token、CA cert）放哪、RBAC 限制誰能參考這個 issuer</li>
<li><strong>Certificate spec</strong>：<code>dnsNames</code> / <code>ipAddresses</code> 跟實際 service 一致、<code>duration</code> 跟 <code>renewBefore</code> 比例合理（renewBefore &gt;= duration / 3）、<code>secretName</code> 指向的 Secret 是不是 ingress 真的會讀的那個</li>
<li><strong>Renewal 觸發</strong>：controller log 有沒有按時觸發 renew、<code>kubectl describe certificate</code> 的 <code>Renewal Time</code> 接近沒、Challenge resource 沒有卡在 pending</li>
<li><strong>Challenge solver</strong>：HTTP01 的 ingress / Gateway 80 port 真的能被 Let&rsquo;s Encrypt 從 Internet 打到、DNS01 用的 cloud provider credential 還有效、wildcard cert 沒誤用 HTTP01</li>
</ul>
<p>四件事任一缺失、cert 就會在不知不覺中過期、production 看到 <code>x509: certificate has expired</code> 才驚覺、是 <a href="/blog/backend/07-security-data-protection/transport-trust-and-certificate-lifecycle/" data-link-title="7.5 傳輸信任與憑證生命週期" data-link-desc="以問題驅動方式整理傳輸信任鏈、會話完整性與憑證節奏">Transport Trust and Certificate Lifecycle</a> 的典型缺口。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>Issuer vs ClusterIssuer 的選擇</strong>：<code>Issuer</code> 是 namespace-scoped、只能 issue 該 namespace 的 cert、適合 <em>單 team 自管 issuer credential</em> 的場景；<code>ClusterIssuer</code> 是 cluster-wide、所有 namespace 都可以參考、適合 <em>平台 team 統一管理 issuer</em>。production 通常用 ClusterIssuer 配特定 issuer backend + RBAC 收 <code>Certificate</code> 建立權（讓 application team 只能在自己 namespace 建 Certificate、不能改 ClusterIssuer）。</p>
<p><strong>Certificate spec 設計</strong>：<code>dnsNames</code> 列出該 cert 涵蓋的 hostname（支援 wildcard <code>*.example.com</code>）、<code>ipAddresses</code> 加 IP SAN（mTLS 跨 service 常用）、<code>duration</code> 是 cert 有效期、<code>renewBefore</code> 是提前多久 renew（預設 duration 的 1/3）。短期 cert（hours-level、Vault PKI 常用）配 <code>renewBefore</code> 短、長期 cert（90 天、Let&rsquo;s Encrypt）配 <code>renewBefore</code> 30 天。<code>secretName</code> 指向 cert-manager 會寫入的 Secret、Ingress 跟 workload 從這個 Secret 讀。</p>
<p><strong>Challenge solver 的選擇</strong>：ACME issuer（Let&rsquo;s Encrypt）需要證明 <em>你控制這個 domain</em>、有兩個方法：HTTP01（在 <code>http://yourdomain/.well-known/acme-challenge/&lt;token&gt;</code> 放檔案、Let&rsquo;s Encrypt 從 Internet 來抓）跟 DNS01（在 DNS zone 加 <code>_acme-challenge.yourdomain TXT &lt;token&gt;</code> record、Let&rsquo;s Encrypt 查 DNS）。<strong>wildcard cert（<code>*.example.com</code>）必須用 DNS01</strong>、HTTP01 不支援 wildcard 因為 Let&rsquo;s Encrypt 不知道要打哪個 subdomain。HTTP01 要求 ingress controller 80 port 對 Internet 開放、DNS01 要求 cluster 有 cloud DNS API credential。</p>
<p><strong>Auto-renewal 機制</strong>：cert-manager 在 cert lifetime 達到 <code>(duration - renewBefore)</code> 時間時觸發 renew、預設約 lifetime 2/3 點。Let&rsquo;s Encrypt cert 90 天 = 60 天時開始嘗試 renew、留 30 天緩衝給 renew 失敗的重試。renew 失敗會持續重試（exponential backoff、最長 8 小時間隔）、剩下 ~7 天時 controller log 開始 ERROR 級別 alert — 監控要 hook 進這個 log 訊號、否則 cert 真的過期才知道就太晚。</p>
<p><strong>跟 Ingress 整合</strong>：Ingress resource 加 annotation <code>cert-manager.io/cluster-issuer: letsencrypt-prod</code>（或 <code>cert-manager.io/issuer:</code>）、cert-manager 看到 Ingress 的 <code>tls.hosts</code> 自動建立對應 Certificate、issue 完寫進 <code>tls.secretName</code> 指定的 Secret、ingress controller 自動 reload 用新 cert。Gateway API 的整合機制類似、用 <code>cert-manager.io/issuer</code> annotation 在 <code>Gateway</code> resource。</p>
<p><strong>CertificateRequest Approval Policy（v1.4+）</strong>：每個 Certificate 建立會產生 CertificateRequest、由 Approver 決定要不要送給 issuer。預設 cert-manager 內建 approver 自動 approve、但可以加 admission policy（Kyverno / OPA / 自寫 webhook）限制「誰能在哪個 namespace 建什麼 SAN 的 cert」— 防 internal compromise 任意 issue cert 對外冒名。production 環境通常會在 platform-level 鎖 wildcard cert、防 application team 誤建涵蓋整個 zone 的 cert。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>cert-manager</th>
          <th>AWS ACM</th>
          <th>手動 certbot / OpenSSL</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>部署模型</td>
          <td>K8s controller、declarative <code>Certificate</code> resource</td>
          <td>AWS managed、Console / API request</td>
          <td>手動跑 CLI、cron 跑 renew</td>
      </tr>
      <tr>
          <td>Cert 部署面</td>
          <td>K8s Secret、任何 ingress controller / workload</td>
          <td>只能掛 ELB / CloudFront / API Gateway</td>
          <td>任何地方、但 deploy 要自己做</td>
      </tr>
      <tr>
          <td>Issuer 彈性</td>
          <td>多 issuer（ACME / Vault / Venafi / CA / AWS PCA）</td>
          <td>只能 Amazon CA</td>
          <td>任何 ACME provider、但要手寫 hook</td>
      </tr>
      <tr>
          <td>Auto-renewal</td>
          <td>內建 controller、預設 2/3 lifetime 點 renew</td>
          <td>AWS 自動 renew（DNS-validated only）</td>
          <td>自己寫 cron + reload script</td>
      </tr>
      <tr>
          <td>Wildcard 支援</td>
          <td>走 DNS01 challenge</td>
          <td>支援、需 DNS 驗證</td>
          <td>走 DNS01 hook</td>
      </tr>
      <tr>
          <td>私鑰位置</td>
          <td>K8s Secret（cluster 內、需 RBAC + etcd encryption）</td>
          <td>AWS 內、不可 export</td>
          <td>Local filesystem、要自己管</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>K8s cluster 內所有 cert、跨 issuer、internal mTLS</td>
          <td>AWS-only serving cert（ELB / CDN）</td>
          <td>非 K8s 的 server、舊系統</td>
      </tr>
      <tr>
          <td>退場成本</td>
          <td>中 — 改其他 ACME client 或回手動</td>
          <td>高 — 私鑰拿不出來、要重新 issue</td>
          <td>低 — 完全自管</td>
      </tr>
  </tbody>
</table>
<p>選 cert-manager 的核心訴求：<em>cluster 內 cert 跨 issuer 統一管理 + 自動 renew + 跟 Ingress / Gateway declarative 整合</em>。如果 cert 完全給 AWS service 用、不進 K8s workload、ACM 更簡單（不用裝 controller、AWS 自動處理）。如果是非 K8s 環境（VM、bare-metal Nginx）、certbot + cron 仍是合理選擇、不需要為了 cert 跑 K8s controller。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>DNS01 challenge 跟 cloud DNS 整合</strong>：cert-manager 支援多家 cloud DNS provider 作為 DNS01 solver — Route53、Cloud DNS（GCP）、Azure DNS、Cloudflare、ACMEDNS（自管 DNS proxy）。每個 provider 需要 <em>DNS zone 寫入 credential</em>（IAM role、service account key、API token）— 這份 credential 等於 <em>任意改該 zone DNS record 的權力</em>、blast radius 大、要走 <a href="/blog/backend/07-security-data-protection/identity-access-boundary/" data-link-title="7.2 身分與授權邊界" data-link-desc="以問題驅動方式整理身分、授權、會話與供應商身分鏈">least privilege</a> 限定到 specific zone + 只給 TXT record write、不要全 zone 全 record type。</p>
<p><strong>跟 Vault PKI engine 整合</strong>：cert-manager 可用 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault PKI engine</a> 作為 issuer backend — 在 cluster 內建 <code>Issuer</code> / <code>ClusterIssuer</code> type 為 <code>vault</code>、指向 Vault address + PKI mount path + auth method（Kubernetes auth / AppRole）。每張 cert 的 issue / revoke 都進 Vault audit log、跟 secret rotation 用同一套 evidence chain（呼應 <a href="/blog/backend/07-security-data-protection/credential-rotation-scoped-evidence/" data-link-title="7.27 Credential Rotation with Scoped Evidence 實作示範" data-link-desc="以 webhook/API credential 輪替示範 scope map、證據欄位與回退窗口如何一起設計。">Credential Rotation Scoped Evidence</a>）。typical 用法：short-lived workload mTLS cert（hours-level duration、minutes-level renewBefore）、靠 Vault PKI 短期 cert + cert-manager 自動換。</p>
<p><strong>跟 SPIRE 的互補</strong>：cert-manager 自動更新 cert、但 <em>cert 是給人讀的 DNS name</em>；SPIRE 自動建立 workload identity、<em>identity 是 SPIFFE ID</em>。兩者解不同問題 — cert-manager 解「Ingress / external API 的 TLS」、SPIRE 解「service A 要怎麼證明自己是 A 給 service B 看」。production 環境常 <em>並存</em>：edge cert 跟 user-facing TLS 用 cert-manager + Let&rsquo;s Encrypt、internal service mesh 用 SPIRE + SPIFFE。</p>
<p><strong>Trust bundle 管理（trust-manager）</strong>：trust-manager 是 cert-manager 姐妹專案、解決 <em>trust anchor（root CA bundle）跨 namespace 同步</em> 問題。傳統做法是每個 pod ConfigMap 各自塞 CA bundle、更新時要逐個改；trust-manager 提供 <code>Bundle</code> resource 一處定義、自動 distribute 到指定 namespace 的 ConfigMap。對應 <em>cert rotation</em> 跟 <em>CA rotation</em> 是兩條獨立 chain、後者是 trust-manager 的領域。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Challenge 卡在 pending</strong>：HTTP01 卡 = ingress 80 port 沒對 Internet、firewall / NLB 沒開、redirect 80→443 把 challenge 也轉了；DNS01 卡 = DNS provider credential 過期、IAM 沒 zone write 權、<code>_acme-challenge</code> record 沒寫進去 — <code>kubectl describe challenge</code> 看 reason</li>
<li><strong>Wildcard cert 用 HTTP01</strong>：申請失敗 + log 寫 &ldquo;wildcard not supported with HTTP-01&rdquo; — 改 DNS01 solver</li>
<li><strong>renewBefore 太短</strong>：renew 失敗只剩幾天才 alert、實際過期前來不及處理 — <code>renewBefore</code> 至少 duration / 3、production cert 給 30 天</li>
<li><strong>Secret 沒被 ingress 讀到</strong>：Certificate 已 Ready 但 ingress 還用舊 cert — ingress <code>tls.secretName</code> 拼錯、ingress controller 沒 reload、TLS handshake 用的 SNI 沒匹配</li>
<li><strong>ACME rate limit 撞牆</strong>：<a href="/blog/backend/07-security-data-protection/vendors/letsencrypt/" data-link-title="Let&#39;s Encrypt" data-link-desc="免費 &#43; 自動化的公共 ACME CA、90 天 TTL 強制自動化、跨雲跨平台 public TLS cert 的事實基礎">Let&rsquo;s Encrypt rate limit</a> 每週同 domain 50 cert / 同 account 300 pending — 反覆建錯 Certificate 重 issue 會撞、staging environment 用 <code>letsencrypt-staging</code> issuer 測過再上 prod</li>
<li><strong>ClusterIssuer 被 application team 誤改</strong>：沒設 RBAC、任何 namespace 都能 patch ClusterIssuer — 用 admission policy 鎖 ClusterIssuer 變更權給 platform team</li>
<li><strong>Approval Policy 缺失</strong>：任何 namespace 能建 wildcard cert、internal compromise 拿到 K8s API token 就能 issue 假冒 cert — 上 CertificateRequest Approval Policy + Kyverno / OPA rule</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>AWS-only serving cert（ELB / CloudFront）</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/aws-acm/" data-link-title="AWS ACM" data-link-desc="AWS-managed certificate provisioning、DNS validation &#43; auto-renewal、整合 ELB / CloudFront / API Gateway、Private CA 後端">AWS ACM</a></td>
      </tr>
      <tr>
          <td>非 K8s 環境（VM、bare-metal）的 ACME cert</td>
          <td>certbot / acme.sh / <a href="/blog/backend/07-security-data-protection/vendors/letsencrypt/" data-link-title="Let&#39;s Encrypt" data-link-desc="免費 &#43; 自動化的公共 ACME CA、90 天 TTL 強制自動化、跨雲跨平台 public TLS cert 的事實基礎">Let&rsquo;s Encrypt</a> 直接用</td>
      </tr>
      <tr>
          <td>Workload identity（不是 DNS-named cert）</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/spire/" data-link-title="SPIRE" data-link-desc="SPIFFE Runtime Environment、attested workload identity、short-lived SVID &#43; Trust Bundle、跨組織 federation">SPIRE</a>（SPIFFE-based）</td>
      </tr>
      <tr>
          <td>大量短期 internal cert + 完整 PKI 治理</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault PKI engine</a>（可配 cert-manager 為 client）</td>
      </tr>
      <tr>
          <td>公司既有 enterprise CA（Venafi / DigiCert）</td>
          <td>cert-manager + Venafi issuer / 商用 issuer plugin</td>
      </tr>
      <tr>
          <td>全公司 cert rotation 證據鏈</td>
          <td><a href="/blog/backend/07-security-data-protection/credential-rotation-scoped-evidence/" data-link-title="7.27 Credential Rotation with Scoped Evidence 實作示範" data-link-desc="以 webhook/API credential 輪替示範 scope map、證據欄位與回退窗口如何一起設計。">7.5 Credential Rotation Scoped Evidence</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>cert-manager Helm chart 的所有 value 細節跟版本相容性矩陣</li>
<li>每個 issuer backend 的完整 schema（acme / vault / venafi / ca / selfSigned）</li>
<li>Gateway API 跟 Ingress API 的 cert-manager annotation 完整對照</li>
<li>ACME RFC 8555 protocol 細節（HTTP01 / DNS01 / TLS-ALPN-01 challenge mechanism）</li>
<li>trust-manager 的 Bundle source 種類（inMemory / secret / configMap / defaultPackage）</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>cert-manager 在 07 案例庫沒有直接 vendor-level 事件、以下案例採對照引用：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 cert-manager 的關係（對照）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/transport-trust-and-certificate-lifecycle/" data-link-title="7.5 傳輸信任與憑證生命週期" data-link-desc="以問題驅動方式整理傳輸信任鏈、會話完整性與憑證節奏">Transport Trust and Certificate Lifecycle (section)</a></td>
          <td>cert-manager 是 cert lifecycle automation 的具體實作 — auto-renewal + Challenge solver + Approval Policy 是 lifecycle 治理三層機制</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/credential-rotation-scoped-evidence/" data-link-title="7.27 Credential Rotation with Scoped Evidence 實作示範" data-link-desc="以 webhook/API credential 輪替示範 scope map、證據欄位與回退窗口如何一起設計。">Credential Rotation Scoped Evidence (section)</a></td>
          <td>cert-manager 的 renewal 自動但 <em>revocation 流程不自動</em> — 舊 cert 失效後 fleet 層級 trust bundle update 是另一條 chain、走 trust-manager</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/edge-exposure/citrix-bleed-2023-session-hijack/" data-link-title="7.R7.3.3 Citrix Bleed 2023：會話被劫持與重放風險" data-link-desc="邊界設備會話資料外洩後，如何演變成帳號與服務風險">Citrix Bleed 2023 Session Hijack</a></td>
          <td>對照啟示 — cert 更新後 session 仍可能延續、cert-manager 只管 cert lifecycle、session invalidation 是另一層責任、不要把 cert rotation 當 session 失效手段</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/secrets-and-machine-credential-governance/" data-link-title="7.6 秘密管理與機器憑證治理" data-link-desc="以問題驅動方式整理 secret、token、key 與機器身份治理">7.6 秘密管理與機器憑證治理</a>、<a href="/blog/backend/07-security-data-protection/transport-trust-and-certificate-lifecycle/" data-link-title="7.5 傳輸信任與憑證生命週期" data-link-desc="以問題驅動方式整理傳輸信任鏈、會話完整性與憑證節奏">Transport Trust and Certificate Lifecycle</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/letsencrypt/" data-link-title="Let&#39;s Encrypt" data-link-desc="免費 &#43; 自動化的公共 ACME CA、90 天 TTL 強制自動化、跨雲跨平台 public TLS cert 的事實基礎">Let&rsquo;s Encrypt</a>（ACME issuer）、<a href="/blog/backend/07-security-data-protection/vendors/aws-acm/" data-link-title="AWS ACM" data-link-desc="AWS-managed certificate provisioning、DNS validation &#43; auto-renewal、整合 ELB / CloudFront / API Gateway、Private CA 後端">AWS ACM</a>（AWS-managed cert）、<a href="/blog/backend/07-security-data-protection/vendors/spire/" data-link-title="SPIRE" data-link-desc="SPIFFE Runtime Environment、attested workload identity、short-lived SVID &#43; Trust Bundle、跨組織 federation">SPIRE</a>（workload identity）</li>
<li>下游：<a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a>（PKI engine 作為 issuer backend）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（cert 過期 / mis-issue 事件如何 routing）</li>
<li>官方：<a href="https://cert-manager.io/docs/">cert-manager Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>Syft + Grype</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/syft-grype/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/syft-grype/</guid><description>&lt;p>Syft 跟 Grype 是 Anchore 開源的 &lt;em>姐妹工具&lt;/em>（Apache 2.0、免費）、各做一件事、用 pipe 串接成 &lt;em>SBOM-first&lt;/em> 的 supply chain scan 鏈：&lt;strong>Syft&lt;/strong> 掃 container image / 檔案系統 / 目錄、產出標準 SBOM（CycloneDX 1.5+ / SPDX 2.3 / SyftJSON）；&lt;strong>Grype&lt;/strong> 吃 SBOM 或直接 scan target、比對 Grype-DB 回報 CVE。設計哲學是 Unix philosophy — &lt;code>syft image:tag -o cyclonedx-json | grype&lt;/code> 等價於 &lt;code>grype image:tag&lt;/code>、但中間的 SBOM 是 &lt;em>正式 artifact&lt;/em>、可以單獨簽章、單獨保存、單獨給下游消費。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &amp;#43; Secret &amp;#43; License &amp;#43; SBOM、Apache 2.0、CI 友善">Trivy&lt;/a> 全包式設計不同、跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &amp;#43; Code (SAST) &amp;#43; Container &amp;#43; IaC &amp;#43; Cloud (CSPM)、Reachability analysis">Snyk&lt;/a> 商業 SaaS 路線也不同。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Syft + Grype 的核心定位是 &lt;em>SBOM-first 的 OSS supply chain scan tool chain&lt;/em>。SBOM 不是中間產物、是 &lt;em>正式可簽章 artifact&lt;/em>：Syft 產 SBOM 後通常用 &lt;a href="https://docs.sigstore.dev/">Sigstore cosign&lt;/a> &lt;code>attest --predicate sbom.cdx.json&lt;/code> 把 SBOM 簽進 image OCI metadata、跟 image 一起發布；下游團隊 / 客戶 / scan pipeline 拿 &lt;em>trusted SBOM&lt;/em> 跑 Grype、不需要重新 scan image。對 &lt;em>air-gapped 環境&lt;/em>、&lt;em>multi-team handoff&lt;/em>、&lt;em>合規場景&lt;/em>（EO 14028 / FedRAMP 要求交付 CycloneDX 或 SPDX）特別合適。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &amp;#43; Secret &amp;#43; License &amp;#43; SBOM、Apache 2.0、CI 友善">Trivy&lt;/a> 的差異是 &lt;em>分工 vs 全包&lt;/em>：Trivy 一個 binary 把 SBOM 生成 + vuln scan + IaC + secret + license 都做了；Syft + Grype 拆兩個工具、SBOM 互通流程適合、團隊偏好 Unix philosophy 選這條。功能覆蓋面 Trivy 略廣（含 IaC / secret scan）、Syft 的 SBOM 格式互通性是 OSS reference implementation。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &amp;#43; Code (SAST) &amp;#43; Container &amp;#43; IaC &amp;#43; Cloud (CSPM)、Reachability analysis">Snyk&lt;/a> 的差異更直接：Snyk 商業 SaaS、覆蓋廣（SAST / IaC / CSPM / Reachability）、有 dashboard 跟 fix PR；Syft + Grype 純 CLI、OSS 免費、聚焦 SBOM + vuln 兩件事、沒 server / 沒 dashboard、要 dashboard 走商業 Anchore Enterprise 或自接 JSON 到 Elasticsearch / Grafana。&lt;/p></description><content:encoded><![CDATA[<p>Syft 跟 Grype 是 Anchore 開源的 <em>姐妹工具</em>（Apache 2.0、免費）、各做一件事、用 pipe 串接成 <em>SBOM-first</em> 的 supply chain scan 鏈：<strong>Syft</strong> 掃 container image / 檔案系統 / 目錄、產出標準 SBOM（CycloneDX 1.5+ / SPDX 2.3 / SyftJSON）；<strong>Grype</strong> 吃 SBOM 或直接 scan target、比對 Grype-DB 回報 CVE。設計哲學是 Unix philosophy — <code>syft image:tag -o cyclonedx-json | grype</code> 等價於 <code>grype image:tag</code>、但中間的 SBOM 是 <em>正式 artifact</em>、可以單獨簽章、單獨保存、單獨給下游消費。跟 <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> 全包式設計不同、跟 <a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk</a> 商業 SaaS 路線也不同。</p>
<h2 id="服務定位">服務定位</h2>
<p>Syft + Grype 的核心定位是 <em>SBOM-first 的 OSS supply chain scan tool chain</em>。SBOM 不是中間產物、是 <em>正式可簽章 artifact</em>：Syft 產 SBOM 後通常用 <a href="https://docs.sigstore.dev/">Sigstore cosign</a> <code>attest --predicate sbom.cdx.json</code> 把 SBOM 簽進 image OCI metadata、跟 image 一起發布；下游團隊 / 客戶 / scan pipeline 拿 <em>trusted SBOM</em> 跑 Grype、不需要重新 scan image。對 <em>air-gapped 環境</em>、<em>multi-team handoff</em>、<em>合規場景</em>（EO 14028 / FedRAMP 要求交付 CycloneDX 或 SPDX）特別合適。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> 的差異是 <em>分工 vs 全包</em>：Trivy 一個 binary 把 SBOM 生成 + vuln scan + IaC + secret + license 都做了；Syft + Grype 拆兩個工具、SBOM 互通流程適合、團隊偏好 Unix philosophy 選這條。功能覆蓋面 Trivy 略廣（含 IaC / secret scan）、Syft 的 SBOM 格式互通性是 OSS reference implementation。跟 <a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk</a> 的差異更直接：Snyk 商業 SaaS、覆蓋廣（SAST / IaC / CSPM / Reachability）、有 dashboard 跟 fix PR；Syft + Grype 純 CLI、OSS 免費、聚焦 SBOM + vuln 兩件事、沒 server / 沒 dashboard、要 dashboard 走商業 Anchore Enterprise 或自接 JSON 到 Elasticsearch / Grafana。</p>
<p>關鍵 first-class concept：<strong>Source</strong>（OCI image / OCI archive / Docker daemon / dir / file / 既有 SBOM）、<strong>Catalog</strong>（Syft 內部 package inventory 結構）、<strong>Package</strong>、<strong>Vulnerability</strong>、<strong>Match</strong>（Grype 的 package ↔ CVE 配對）、<strong>Match Configuration</strong>（<code>grype.yaml</code> 設 severity gate / 比對策略）、<strong>Vulnerability DB</strong>（Grype-DB、Anchore 聚合 NVD + GHSA + 各 distro secdb）、<strong>Ignore Rule</strong>（CVE 例外、強制帶 expiration）。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>Syft 跟 Grype 各自的責任邊界、為什麼拆兩個工具比合一個工具好（SBOM 互通、attestation、air-gapped）</li>
<li>SBOM 格式（CycloneDX / SPDX / SyftJSON）的選擇、跟合規要求對應</li>
<li>Grype Match Configuration 跟 Ignore Rule 怎麼設、CI fail 條件怎麼定</li>
<li>何時改走 <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> 全包式、何時走 <a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk</a> 商業 SaaS</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Syft + Grype 配置是否健康、最少看四件事：</p>
<ul>
<li><strong>SBOM 格式跟保存</strong>：產出格式是否符合合規（多數 EO 14028 / FedRAMP 場景要 CycloneDX 或 SPDX、不是 SyftJSON）、SBOM 是否簽章（cosign attest）、是否集中保存（OCI registry 旁邊 / artifact store）、是否有 <em>baseline diff</em>（image 升級前後依賴變化）</li>
<li><strong>Grype DB 更新</strong>：DB 是否每日同步、air-gapped 場景是否 mirror 到內部 registry（Grype DB 是 OCI artifact、可 <code>oras pull</code> 鏡像）、DB version 是否進 SBOM scan record（重現性）</li>
<li><strong>Match Configuration</strong>：<code>grype.yaml</code> 的 severity gate（CI fail 條件、通常 high / critical fail）、<code>only-fixed: true</code> 是否開（只報有 patch 的 CVE）、<code>add-cpes-if-none: true</code> 對 binary-only package 行為</li>
<li><strong>Ignore Rule 治理</strong>：例外清單是否帶 <em>expiration</em>、<code>reason</code> 欄位是否填 ticket / decision 連結、quarterly review 機制、過期自動回到 fail 狀態</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">Supply Chain Integrity</a> 邊界的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>Syft 用法跟 Source 種類</strong>：<code>syft &lt;source&gt; -o &lt;format&gt;</code> 是核心 — source 可以是 OCI image（<code>registry/image:tag</code>）、OCI archive（<code>oci-archive:image.tar</code>）、Docker daemon（<code>docker:image:tag</code>）、目錄（<code>dir:./</code>）、單一檔案、甚至既有 SBOM（<code>sbom:./prev.cdx.json</code>、用來 <em>轉格式</em>）。format 包括 <code>cyclonedx-json</code> / <code>cyclonedx-xml</code> / <code>spdx-json</code> / <code>spdx-tag-value</code> / <code>syft-json</code> / <code>table</code>。production 通常產 <em>cyclonedx-json</em>（合規要求最常見）+ 保留 <em>syft-json</em>（Syft 自家最完整、未來 round-trip 用）。</p>
<p><strong>Package detector 廣度</strong>：Syft 自動偵測 OS package（apk / dpkg / rpm）+ 語言 dependency（npm / pip / gem / go module / cargo / maven / gradle / nuget / composer / hex / conan / swift / dart 等）+ binary analysis（Go binary 內 embedded module、Rust binary metadata、Java jar / war / ear nested）。對 <em>static binary</em> / <em>FAT image</em> 的支援是 Syft 的強項、比多數 SBOM tool 廣。但 <em>runtime-only dependency</em>（dlopen / dynamic load）SBOM 看不到、要靠 runtime workload protection（Falco / Cilium Tetragon 類工具、見 <a href="/blog/backend/07-security-data-protection/vendors/" data-link-title="資安與資料保護 Vendor 清單" data-link-desc="規劃身份、秘密、金鑰、入口防護、供應鏈與偵測工具的服務頁撰寫順序與教學大綱">7 後續候選 vendor 清單</a>）補。</p>
<p><strong>Grype 用法</strong>：<code>grype &lt;source&gt;</code> 或 <code>grype sbom:./image.cdx.json</code>。輸出 <code>table</code> / <code>json</code> / <code>cyclonedx-json</code>（CycloneDX VEX 格式）/ <code>sarif</code>（GitHub code scanning）/ <code>template</code>（Go template 自訂）。production CI 通常 <code>--output sarif</code> 上傳 GitHub code scanning + <code>--output json</code> 進內部 SIEM。<code>grype sbom:./prev.cdx.json</code> 模式是 <em>SBOM-only scan</em>、不碰 image — 適合 <em>下游團隊拿 SBOM 持續 monitor</em>、原始 image 已經 frozen 或不可達。</p>
<p><strong>Match Configuration（<code>grype.yaml</code>）</strong>：核心欄位包括 <code>fail-on-severity: high</code>（CI gate）、<code>only-fixed: true</code>（只回報有 fix 可用的 CVE、避免 noise）、<code>ignore</code> list（個別 CVE 例外）、<code>match</code> strategy（如何把 package CPE / PURL 對應到 CVE、預設策略對 90% 場景夠用、特殊 binary 場景才調）。所有設定走版控、<code>grype.yaml</code> 跟程式碼一起 review、避免 console 改。</p>
<p><strong>Ignore Rule 治理</strong>：<code>grype.yaml</code> 的 <code>ignore</code> entry 結構：<code>vulnerability</code> + <code>reason</code> + <code>expiration</code>（YYYY-MM-DD）+ optional <code>package.name</code> / <code>fix-state</code>。Anchore 設計 <em>沒有「永久 ignore」</em>、必須帶 expiration — 強制 quarterly review、避免「五年前 ignore 的 CVE 早被 fix 了還在清單裡」。reason 欄位填 ticket 編號或 ADR link、給未來的人 context。</p>
<p><strong>Cosign attest SBOM</strong>：<code>syft image:tag -o cyclonedx-json &gt; sbom.cdx.json &amp;&amp; cosign attest --predicate sbom.cdx.json --type cyclonedx --key cosign.key image:tag</code> — SBOM 被簽進 image 的 OCI signature manifest、下游 <code>cosign verify-attestation --type cyclonedx ...</code> 拿到 <em>cryptographically signed SBOM</em>。這把 SBOM 從「可被竄改的 JSON 檔」升級到 <em>trusted artifact</em>、是 <a href="https://slsa.dev/">SLSA L3+</a> provenance 的基礎。</p>
<p><strong>SLSA / SPDX 流程整合</strong>：Syft SBOM 是 build 階段產物、跟 SLSA provenance（誰 build 的、用什麼 builder、source commit 是什麼）併存、不互斥 — SBOM 答「裡面有什麼」、provenance 答「怎麼 build 的」。完整 supply chain trust 需要兩者 + cosign signature。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Syft + Grype</th>
          <th>Trivy</th>
          <th>Snyk</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>工具拆分</td>
          <td>兩個（Unix philosophy）</td>
          <td>一個（all-in-one binary）</td>
          <td>SaaS + CLI（多模組）</td>
      </tr>
      <tr>
          <td>授權</td>
          <td>OSS Apache 2.0</td>
          <td>OSS Apache 2.0</td>
          <td>商業（freemium、付費才解鎖完整）</td>
      </tr>
      <tr>
          <td>部署模型</td>
          <td>CLI、無 server</td>
          <td>CLI、無 server</td>
          <td>SaaS dashboard + CLI</td>
      </tr>
      <tr>
          <td>SBOM 格式</td>
          <td>CycloneDX 1.5+ / SPDX 2.3 / SyftJSON（reference 實作）</td>
          <td>CycloneDX / SPDX</td>
          <td>CycloneDX / SPDX（次要、scan 為主）</td>
      </tr>
      <tr>
          <td>Vuln 資料源</td>
          <td>Grype-DB（NVD + GHSA + 各 distro secdb 聚合）</td>
          <td>Trivy-DB（類似來源 + Aqua 加值）</td>
          <td>Snyk Intel（自家 research、含 reachability）</td>
      </tr>
      <tr>
          <td>額外掃描</td>
          <td>無（聚焦 SBOM + vuln）</td>
          <td>IaC / secret / license / k8s misconfig</td>
          <td>SAST / IaC / container / IaC / Open Source / Code</td>
      </tr>
      <tr>
          <td>Dashboard</td>
          <td>無（Anchore Enterprise 商業才有）</td>
          <td>無（Aqua 商業才有）</td>
          <td>內建 SaaS dashboard</td>
      </tr>
      <tr>
          <td>Air-gapped</td>
          <td>強 — Grype DB 是 OCI artifact、可 mirror</td>
          <td>強 — Trivy DB OCI artifact</td>
          <td>弱 — SaaS-only 為主（自管 server 是 Enterprise）</td>
      </tr>
      <tr>
          <td>Reachability</td>
          <td>無</td>
          <td>無</td>
          <td>有（Java / JS）</td>
      </tr>
      <tr>
          <td>Fix PR 自動化</td>
          <td>無</td>
          <td>無</td>
          <td>有（auto PR、Renovate-like）</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>OSS 偏好、SBOM 互通流程、air-gapped、Unix tool chain</td>
          <td>OSS 偏好、單一工具想包多事、k8s misconfig 也要</td>
          <td>商業 SaaS、需 dashboard / fix workflow / reachability</td>
      </tr>
  </tbody>
</table>
<p>選 Syft + Grype 的核心訴求：<em>要正式 SBOM 作為交付 artifact</em>（合規 / 多 team handoff）+ <em>偏好 OSS Unix philosophy</em>（兩個工具各做一件事、容易整合自家 pipeline）+ 不需要 SaaS dashboard（自家 SIEM / Grafana 已經有）。需要 IaC scan 一起做、看一下 Trivy 是不是更省整合成本；需要 fix workflow 跟 reachability、商業預算足、走 Snyk。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>SBOM attestation 完整鏈</strong>：build pipeline 順序通常是 — build image → <code>syft image -o cyclonedx-json &gt; sbom.cdx.json</code> → <code>cosign sign image</code> → <code>cosign attest --predicate sbom.cdx.json --type cyclonedx image</code> → push。下游 admission controller（Kyverno / Gatekeeper / Sigstore policy-controller）<code>verify-attestation</code> 拿 trusted SBOM、再 Grype scan、policy 決定是否允許 deploy。這條鏈把 SBOM 從 <em>文件</em> 升級成 <em>deploy gate</em>。</p>
<p><strong>Grype DB air-gapped sync</strong>：Grype DB 是 OCI artifact（<code>ghcr.io/anchore/grype/listing.json</code> + <code>db.tar.gz</code>）、<code>oras pull</code> 或 <code>grype db update</code> 取得。air-gapped 場景：DMZ 跑 <code>grype db update --skip-listing-content-check</code>、把 <code>~/.cache/grype/db/</code> 整個 sync 到內部 mirror registry、內部 grype 透過 <code>GRYPE_DB_UPDATE_URL</code> 指到內部 listing。DB 版本進 scan record、確保 <em>相同 SBOM + 相同 DB = 相同結果</em>（可重現）。</p>
<p><strong>Custom matcher / Ignore Rule 細部</strong>：Grype 預設 matcher 對 90% 場景夠、但 <em>Go binary</em>、<em>static-linked binary</em>、<em>custom C++ build</em> 可能需要 <code>add-cpes-if-none: true</code> 強制配對 CPE。Ignore Rule 支援 <code>vex-status</code> 欄位（accepted / under-investigation / fixed / not-affected）對齊 CycloneDX VEX 標準、輸出 VEX-enriched SBOM 給下游 / 客戶。</p>
<p><strong>Anchore Enterprise 商業整合</strong>：OSS Syft + Grype 不夠時、Anchore Enterprise 加：policy engine（GraphQL 寫複雜 policy）、dashboard、RBAC、SLA-backed support、跟 Kubernetes admission integration、跟 Jira / ServiceNow ticket 自動建單。OSS 是 90% 場景的起點、Enterprise 解的是 <em>policy + workflow</em> 而非 <em>scan ability</em>。</p>
<p><strong>SBOM diff（baseline 比對）</strong>：<code>syft</code> 自己沒內建 diff、但 <code>cyclonedx-cli diff</code> 或自家 script 可以比對 <em>image v1 SBOM</em> vs <em>image v2 SBOM</em>、找出新增 / 移除 / 升級的 package。用途：<a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/xz-backdoor-2024-open-source-supply-chain/" data-link-title="7.R7.2.4 XZ Backdoor 2024：開源供應鏈長期滲透" data-link-desc="開源維護鏈遭滲透後，為何會直接影響廣泛 Linux 發行流程">XZ backdoor</a> 之類「相同 version 但被植入後門」事件、單靠 SBOM 看不出來、但 <em>baseline + behavior anomaly</em> 雙軌可以提早警示。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Syft scan 找不到 package</strong>：image 是 <code>FROM scratch</code> 或 distroless、Syft 偵測不到 OS package metadata — 改 scan source 為 build 階段的 <code>dir:./</code> 或保留 builder image 的 SBOM</li>
<li><strong>Grype 報一堆 unfixed CVE</strong>：base image 老、有 CVE 但 upstream 還沒 patch — 設 <code>only-fixed: true</code> 過濾 noise、focus 在 actionable item；同時排程 base image 升級</li>
<li><strong>CI 突然 fail 變多</strong>：Grype DB 更新後新 CVE 揭露 — 看 DB version diff、評估是 <em>真新風險</em> 還是 <em>舊 package 被重新分類</em>、必要時用 Ignore Rule + expiration 過渡</li>
<li><strong>SBOM 格式下游不認</strong>：合規要求 SPDX、產的是 SyftJSON — 用 <code>syft convert syft-json:./sbom.json -o spdx-json</code> 轉格式（Syft 本身就是 SBOM 互轉工具）</li>
<li><strong>Air-gapped 環境 Grype 跑不動</strong>：DB 沒同步、scan 直接報 0 vulnerability（假陰性）— <code>grype db status</code> 看 DB age、mirror sync 機制檢查、加 staleness alarm</li>
<li><strong>Ignore Rule 過期回到 fail</strong>：CI 突然 fail、查 expiration 已過 — 預期行為、強制 quarterly review；補 rotation 機制（cronjob 提前一週 alert owner）</li>
<li><strong>Binary 偵測不到 module</strong>：Go binary stripped、<code>-trimpath</code> 後 module path 沒了 — build 改加 <code>-buildvcs=true</code> 保留 VCS info、或 build 階段 SBOM scan source code、不是 binary</li>
<li><strong>cosign verify-attestation 失敗</strong>：image 被 re-tag / re-push 後 attestation manifest 不對 — 用 image digest（<code>@sha256:...</code>）而非 tag 做 attest、tag 不可信</li>
<li><strong>Grype 不抓某個 ecosystem</strong>：例如新冒出的 package manager — Syft 沒實作 detector、Grype 也看不到；submit issue 或自己寫 catalogger 貢獻</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>一個工具想包 IaC / secret / k8s misconfig</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a></td>
      </tr>
      <tr>
          <td>需要 SAST / Reachability / Fix PR workflow</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk</a></td>
      </tr>
      <tr>
          <td>綁 GitHub 的 SAST + Dependabot</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GitHub Advanced Security</a></td>
      </tr>
      <tr>
          <td>Container runtime detection</td>
          <td>Falco / Cilium Tetragon（見 <a href="/blog/backend/07-security-data-protection/vendors/" data-link-title="資安與資料保護 Vendor 清單" data-link-desc="規劃身份、秘密、金鑰、入口防護、供應鏈與偵測工具的服務頁撰寫順序與教學大綱">7 後續候選 vendor 清單</a>）</td>
      </tr>
      <tr>
          <td>Image signing / attestation</td>
          <td><a href="https://docs.sigstore.dev/">Sigstore cosign</a></td>
      </tr>
      <tr>
          <td>Policy at admission</td>
          <td>Kyverno / OPA Gatekeeper（見 <a href="/blog/backend/07-security-data-protection/vendors/" data-link-title="資安與資料保護 Vendor 清單" data-link-desc="規劃身份、秘密、金鑰、入口防護、供應鏈與偵測工具的服務頁撰寫順序與教學大綱">7 後續候選 vendor 清單</a>）</td>
      </tr>
      <tr>
          <td>SBOM dashboard / enterprise policy / RBAC</td>
          <td>Anchore Enterprise（商業）</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>CycloneDX / SPDX 完整 schema 規格逐欄位解讀</li>
<li>Sigstore cosign / Rekor / Fulcio 完整架構（attest 鏈的 OIDC / transparency log）</li>
<li>SLSA framework 各 level 對應的 builder 要求</li>
<li>Anchore Enterprise policy DSL 完整語法</li>
<li>VEX（Vulnerability Exploitability eXchange）跟 CSAF 標準對照細節</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>07 案例庫沒有直接 Syft / Grype-level 事件、但供應鏈案例都是 SBOM-first 思維的對照：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 Syft + Grype 的關係</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/log4shell-cve-2021-44228-component-chain/" data-link-title="7.R7.2.7 Log4Shell 2021：共用元件風險與修補鏈" data-link-desc="共用元件漏洞如何同步影響多服務，並迫使團隊建立依賴治理 workflow">Log4Shell CVE-2021-44228</a></td>
          <td>對照啟示 — 預先用 Syft 產 SBOM 集中保存後、Log4Shell 公開時拿歷史 SBOM 跑 Grype 在分鐘級回答「我們哪些服務有用、含 transitive」</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/solarwinds-2020-sunburst/" data-link-title="7.R7.2.1 SolarWinds 2020：更新鏈被濫用" data-link-desc="合法更新流程遭植入後，攻擊者如何長期潛伏與橫向擴散">SolarWinds 2020 Sunburst</a></td>
          <td>對照啟示 — Syft 看 package layer、看不到 build-time backdoor 注入；需配 cosign attest + SLSA provenance 才完整</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/xz-backdoor-2024-open-source-supply-chain/" data-link-title="7.R7.2.4 XZ Backdoor 2024：開源供應鏈長期滲透" data-link-desc="開源維護鏈遭滲透後，為何會直接影響廣泛 Linux 發行流程">XZ Backdoor 2024</a></td>
          <td>對照啟示 — 相同 version 被植入後 SBOM 一樣、純比對 SBOM 看不出來；mitigation 是 SBOM diff 對 baseline + release tarball verify</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/kaseya-vsa-2021-msp-ransomware-chain/" data-link-title="7.R7.2.9 Kaseya VSA 2021：MSP 供應鏈擴散路徑" data-link-desc="管理平台事件透過 MSP 模型向多客戶擴散時，workflow 應如何分層應對">Kaseya VSA 2021</a></td>
          <td>對照啟示 — 多服務 SBOM 集中 inventory（哪 service 用哪 component）、緊急時可 <em>affected-services-by-package</em> 反查、不是逐 image scan</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">7.12 供應鏈完整性與 Artifact 信任</a></td>
          <td>Syft 是 SBOM reference implementation、章節原則對應 SBOM + signing + provenance 的 trust chain</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">7.12 供應鏈完整性與 Artifact 信任</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a>（一站式替代）、<a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk</a>（商業 SaaS）、<a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GitHub Advanced Security</a>（GitHub 內建）</li>
<li>下游：<a href="https://docs.sigstore.dev/">Sigstore cosign</a>（SBOM attestation）、admission policy（Kyverno / OPA Gatekeeper、見 <a href="/blog/backend/07-security-data-protection/vendors/" data-link-title="資安與資料保護 Vendor 清單" data-link-desc="規劃身份、秘密、金鑰、入口防護、供應鏈與偵測工具的服務頁撰寫順序與教學大綱">7 後續候選 vendor 清單</a>）</li>
<li>跨類：runtime workload protection（Falco / Cilium Tetragon、見 <a href="/blog/backend/07-security-data-protection/vendors/" data-link-title="資安與資料保護 Vendor 清單" data-link-desc="規劃身份、秘密、金鑰、入口防護、供應鏈與偵測工具的服務頁撰寫順序與教學大綱">7 後續候選 vendor 清單</a>）、<a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a>（cosign signing key 保存）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（新 CVE 揭露時的 SBOM-based fan-out 查詢）</li>
<li>官方：<a href="https://github.com/anchore/syft">Syft Documentation</a> / <a href="https://github.com/anchore/grype">Grype Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>Google Cloud Spanner</title><link>https://tarrragon.github.io/blog/backend/01-database/vendors/spanner/</link><pubDate>Wed, 13 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/01-database/vendors/spanner/</guid><description>&lt;p>Cloud Spanner 是 Google 內部 2007 年起跑、2017 年開放為 GCP 服務的 &lt;em>全球分散式 SQL OLTP&lt;/em>。內部撐 Google Ads / Play / Search 計費、外部支援 Blockchain.com、Sharechat、ZEE5 等。它的公開案例重點是每秒 10 億請求等級、線性擴展、強一致與 global distribution 可以同時成為 OLTP 設計目標。&lt;/p>
&lt;h2 id="教學路線全球強一致與-truetime-成本">教學路線：全球強一致與 TrueTime 成本&lt;/h2>
&lt;p>Spanner 服務頁的教學目標是把 global strong consistency、TrueTime、Paxos、region layout 與 processing unit 連成一條產品決策線。讀者讀完後要能判斷何時需要全球一致 SQL，並理解這種能力的 latency、成本與雲平台邊界。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>學習段&lt;/th>
 &lt;th>核心問題&lt;/th>
 &lt;th>對應段落&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Global consistency&lt;/td>
 &lt;td>強一致 SQL 為什麼需要時間邊界與 consensus&lt;/td>
 &lt;td>定位、適用場景、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/linearizability/" data-link-title="Linearizability" data-link-desc="每次操作看起來都在單一全域順序中即時生效的一致性語意">Linearizability&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Region layout&lt;/td>
 &lt;td>instance config、leader region、replica 如何影響 latency&lt;/td>
 &lt;td>容量規劃要點、常見陷阱&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Capacity unit&lt;/td>
 &lt;td>node / processing unit 如何取代傳統 shard 心智模型&lt;/td>
 &lt;td>容量特性、案例對照&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Use-case pressure&lt;/td>
 &lt;td>billing、subscription、ticketing、金融交易何時需要 Spanner&lt;/td>
 &lt;td>適用場景、案例對照&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>替代路由&lt;/td>
 &lt;td>何時用 PostgreSQL、CockroachDB、Aurora DSQL、DynamoDB&lt;/td>
 &lt;td>不適用場景、跟其他 vendor 的取捨&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="定位truetime--paxos-的全球線性-sql">定位：TrueTime + Paxos 的全球線性 SQL&lt;/h2>
&lt;p>Spanner 解決的是跨地理位置同時追求 strong consistency、linear scalability 與 global availability 的 OLTP 問題。&lt;/p>
&lt;p>&lt;strong>關鍵設計&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>TrueTime API&lt;/strong>：用 GPS + 原子鐘提供「全球 unambiguous 時間戳」、誤差 &amp;lt; 7ms&lt;/li>
&lt;li>&lt;strong>External consistency&lt;/strong>（線性化）：跨節點交易順序跟 wall clock 一致&lt;/li>
&lt;li>&lt;strong>Paxos-based replication&lt;/strong>：跨 zone / region &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/quorum/" data-link-title="Quorum" data-link-desc="分散式系統以多數節點同意作為提交或讀取有效性的門檻">quorum&lt;/a>&lt;/li>
&lt;li>&lt;strong>線性擴展&lt;/strong>：2 nodes → 45K reads/sec、4 nodes → 90K reads/sec、依此類推&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>容量特性&lt;/strong>（引自 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/spanner-planetary-scale-database-gcp/" data-link-title="9.C10 Cloud Spanner：每秒 10 億請求的全球一致性資料庫" data-link-desc="Google Cloud Spanner 內部峰值 10 億 req/sec、跨地區強一致 — 全球分散式 OLTP 容量參考">9.C10 Spanner 案例&lt;/a>）：&lt;/p>
&lt;ul>
&lt;li>內部峰值：&amp;gt; 10 億 requests / sec&lt;/li>
&lt;li>線性擴展（不像 USL 系統會在某點 plateau）&lt;/li>
&lt;li>跨 region quorum 延遲：50-200ms（視 region 距離）&lt;/li>
&lt;li>最小容量單位：100 processing units（PU）≈ 1/10 node、適合小負載&lt;/li>
&lt;/ul>
&lt;h2 id="適用場景">適用場景&lt;/h2>
&lt;p>&lt;strong>1. 金融交易、ticketing inventory、payment ledger&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>需要強一致，避免 double-spend、oversell 或帳務順序錯亂&lt;/li>
&lt;li>全球用戶但需要原子性&lt;/li>
&lt;li>對應案例：&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/spanner-planetary-scale-database-gcp/" data-link-title="9.C10 Cloud Spanner：每秒 10 億請求的全球一致性資料庫" data-link-desc="Google Cloud Spanner 內部峰值 10 億 req/sec、跨地區強一致 — 全球分散式 OLTP 容量參考">9.C10 Spanner&lt;/a> — Google Ads 計費與 Google Play 訂閱都需要把每次計費事件放進可驗證順序&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>2. 全球用戶的 OLTP（不只 read replica）&lt;/strong>：&lt;/p></description><content:encoded><![CDATA[<p>Cloud Spanner 是 Google 內部 2007 年起跑、2017 年開放為 GCP 服務的 <em>全球分散式 SQL OLTP</em>。內部撐 Google Ads / Play / Search 計費、外部支援 Blockchain.com、Sharechat、ZEE5 等。它的公開案例重點是每秒 10 億請求等級、線性擴展、強一致與 global distribution 可以同時成為 OLTP 設計目標。</p>
<h2 id="教學路線全球強一致與-truetime-成本">教學路線：全球強一致與 TrueTime 成本</h2>
<p>Spanner 服務頁的教學目標是把 global strong consistency、TrueTime、Paxos、region layout 與 processing unit 連成一條產品決策線。讀者讀完後要能判斷何時需要全球一致 SQL，並理解這種能力的 latency、成本與雲平台邊界。</p>
<table>
  <thead>
      <tr>
          <th>學習段</th>
          <th>核心問題</th>
          <th>對應段落</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Global consistency</td>
          <td>強一致 SQL 為什麼需要時間邊界與 consensus</td>
          <td>定位、適用場景、<a href="/blog/backend/knowledge-cards/linearizability/" data-link-title="Linearizability" data-link-desc="每次操作看起來都在單一全域順序中即時生效的一致性語意">Linearizability</a></td>
      </tr>
      <tr>
          <td>Region layout</td>
          <td>instance config、leader region、replica 如何影響 latency</td>
          <td>容量規劃要點、常見陷阱</td>
      </tr>
      <tr>
          <td>Capacity unit</td>
          <td>node / processing unit 如何取代傳統 shard 心智模型</td>
          <td>容量特性、案例對照</td>
      </tr>
      <tr>
          <td>Use-case pressure</td>
          <td>billing、subscription、ticketing、金融交易何時需要 Spanner</td>
          <td>適用場景、案例對照</td>
      </tr>
      <tr>
          <td>替代路由</td>
          <td>何時用 PostgreSQL、CockroachDB、Aurora DSQL、DynamoDB</td>
          <td>不適用場景、跟其他 vendor 的取捨</td>
      </tr>
  </tbody>
</table>
<h2 id="定位truetime--paxos-的全球線性-sql">定位：TrueTime + Paxos 的全球線性 SQL</h2>
<p>Spanner 解決的是跨地理位置同時追求 strong consistency、linear scalability 與 global availability 的 OLTP 問題。</p>
<p><strong>關鍵設計</strong>：</p>
<ul>
<li><strong>TrueTime API</strong>：用 GPS + 原子鐘提供「全球 unambiguous 時間戳」、誤差 &lt; 7ms</li>
<li><strong>External consistency</strong>（線性化）：跨節點交易順序跟 wall clock 一致</li>
<li><strong>Paxos-based replication</strong>：跨 zone / region <a href="/blog/backend/knowledge-cards/quorum/" data-link-title="Quorum" data-link-desc="分散式系統以多數節點同意作為提交或讀取有效性的門檻">quorum</a></li>
<li><strong>線性擴展</strong>：2 nodes → 45K reads/sec、4 nodes → 90K reads/sec、依此類推</li>
</ul>
<p><strong>容量特性</strong>（引自 <a href="/blog/backend/09-performance-capacity/cases/spanner-planetary-scale-database-gcp/" data-link-title="9.C10 Cloud Spanner：每秒 10 億請求的全球一致性資料庫" data-link-desc="Google Cloud Spanner 內部峰值 10 億 req/sec、跨地區強一致 — 全球分散式 OLTP 容量參考">9.C10 Spanner 案例</a>）：</p>
<ul>
<li>內部峰值：&gt; 10 億 requests / sec</li>
<li>線性擴展（不像 USL 系統會在某點 plateau）</li>
<li>跨 region quorum 延遲：50-200ms（視 region 距離）</li>
<li>最小容量單位：100 processing units（PU）≈ 1/10 node、適合小負載</li>
</ul>
<h2 id="適用場景">適用場景</h2>
<p><strong>1. 金融交易、ticketing inventory、payment ledger</strong>：</p>
<ul>
<li>需要強一致，避免 double-spend、oversell 或帳務順序錯亂</li>
<li>全球用戶但需要原子性</li>
<li>對應案例：<a href="/blog/backend/09-performance-capacity/cases/spanner-planetary-scale-database-gcp/" data-link-title="9.C10 Cloud Spanner：每秒 10 億請求的全球一致性資料庫" data-link-desc="Google Cloud Spanner 內部峰值 10 億 req/sec、跨地區強一致 — 全球分散式 OLTP 容量參考">9.C10 Spanner</a> — Google Ads 計費與 Google Play 訂閱都需要把每次計費事件放進可驗證順序</li>
</ul>
<p><strong>2. 全球用戶的 OLTP（不只 read replica）</strong>：</p>
<ul>
<li>跨 region 寫入、各地用戶寫入本地 region 仍維持全球強一致</li>
<li>它承擔的是 multi-region write path，而非 single primary + 跨 region read replica</li>
<li>對應案例：Blockchain.com（高頻 crypto 交易、強一致）</li>
</ul>
<p><strong>3. 想擺脫 sharding 複雜度</strong>：</p>
<ul>
<li>傳統大規模 SQL 常走應用層 sharding（管 shard key、跨 shard query、resharding）</li>
<li>Spanner 自動 partition，application 主要管理 schema、query shape 與 region layout</li>
<li>對應案例：<a href="/blog/backend/09-performance-capacity/cases/spanner-planetary-scale-database-gcp/" data-link-title="9.C10 Cloud Spanner：每秒 10 億請求的全球一致性資料庫" data-link-desc="Google Cloud Spanner 內部峰值 10 億 req/sec、跨地區強一致 — 全球分散式 OLTP 容量參考">9.C10 Spanner 案例</a> — 「節點數量是容量單位」，shard placement 由 Spanner 管理</li>
</ul>
<p><strong>4. PostgreSQL 相容路徑</strong>：</p>
<ul>
<li>2024 後 Spanner 提供 PostgreSQL dialect interface</li>
<li>從 PostgreSQL 應用遷入 Spanner 變得容易</li>
<li>跟 CockroachDB / Aurora DSQL 類似的策略</li>
</ul>
<h2 id="不適用場景">不適用場景</h2>
<p><strong>1. 跨洲低延遲（&lt; 50ms）需求</strong>：</p>
<ul>
<li>跨洲 quorum 物理上 100ms+ 不可壓縮</li>
<li>替代：single-region OLTP（Aurora、Cloud SQL）+ <a href="/blog/backend/knowledge-cards/eventual-consistency/" data-link-title="Eventual Consistency" data-link-desc="允許短暫不一致、最終收斂到同一資料狀態的一致性語意">eventual consistency</a> 跨 region 同步</li>
</ul>
<p><strong>2. 高 throughput 但容忍 eventual consistency</strong>：</p>
<ul>
<li>Spanner 強一致有溢價，eventual consistency workload 通常有更低成本選項</li>
<li>替代：Bigtable（wide-column、eventual）、DynamoDB Global Tables（KV、eventual）</li>
</ul>
<p><strong>3. 小規模 OLTP</strong>：</p>
<ul>
<li>100 PU 起跳、月費約 $65 起、比 Cloud SQL 貴</li>
<li>流量 &lt; 1000 RPS 的場景、Cloud SQL 更划算</li>
<li>Spanner 主要對 <em>中大規模 + 全球</em> workload</li>
</ul>
<p><strong>4. 跨雲需求</strong>：</p>
<ul>
<li>Spanner 是 GCP managed service，cross-cloud / on-prem 需求要看 CockroachDB、TiDB 或其他自管路線</li>
<li>替代：CockroachDB、TiDB（自管、可跨雲）</li>
</ul>
<p><strong>5. 需要 OLAP 分析能力</strong>：</p>
<ul>
<li>Spanner 定位在 OLTP，analytics workload 交給 BigQuery 或其他 OLAP 系統</li>
<li>替代：跟 BigQuery 整合做 ETL、或用 Spanner Graph（2024 推出）</li>
</ul>
<h2 id="跟其他-vendor-的取捨">跟其他 vendor 的取捨</h2>
<p><strong>vs Aurora DSQL（AWS 2024 推出、概念對標 Spanner）</strong>：</p>
<ul>
<li>Spanner：用 TrueTime hardware、生產驗證 17 年（Google 內部）+ 7 年（公開）</li>
<li>Aurora DSQL：新（2024）、PostgreSQL 相容、serverless</li>
<li>選 Spanner：GCP 生態、需要極致成熟度</li>
<li>選 Aurora DSQL：AWS 生態、需要 PostgreSQL ORM 相容</li>
</ul>
<p><strong>vs CockroachDB</strong>：</p>
<ul>
<li>Spanner：managed、TrueTime hardware、GCP 限定</li>
<li>CockroachDB：自管、HLC + Raft（不靠 TrueTime）、跨雲</li>
<li>選 Spanner：想把 operation 交給 GCP managed service，並需要 Google 規模驗證</li>
<li>選 CockroachDB：跨雲 / on-prem、PostgreSQL 相容、自管彈性</li>
</ul>
<p><strong>vs TiDB</strong>：</p>
<ul>
<li>Spanner：GCP-only、PostgreSQL-like</li>
<li>TiDB：可自管 + Cloud、MySQL 相容、中國 / 亞洲生態深</li>
<li>選 Spanner：英語 / 歐美生態</li>
<li>選 TiDB：MySQL 應用、亞洲市場</li>
</ul>
<p><strong>vs Aurora（traditional single-region scaling）</strong>：</p>
<ul>
<li>Spanner：全球分散式</li>
<li>Aurora：single-region scaling</li>
<li>選 Spanner：流量明確跨 region + 需要強一致</li>
<li>選 Aurora：流量集中一個 region（多數情況）</li>
</ul>
<p><strong>vs Cosmos DB（multi-region write）</strong>：</p>
<ul>
<li>Spanner：strong consistency 跨 region</li>
<li>Cosmos DB：5 個 <a href="/blog/backend/knowledge-cards/consistency-level/" data-link-title="Consistency Level" data-link-desc="資料系統對讀寫一致性語意的可選擇層級">consistency level</a>s、AP 系統（含 strong 但語義不同）</li>
<li>選 Spanner：需要 linearizable（金融、ticketing）</li>
<li>選 Cosmos DB：可接受 session / eventual、Azure 生態、需要 multi-model</li>
</ul>
<p><strong>vs Bigtable</strong>：</p>
<ul>
<li>Spanner：SQL、強一致、OLTP</li>
<li>Bigtable：wide-column、eventual replication、時序 / IoT / 大資料</li>
<li>兩者互補：Bigtable 承擔大資料 / wide-column，Spanner 承擔強一致 OLTP</li>
</ul>
<p><strong>vs PostgreSQL（baseline）</strong>：</p>
<ul>
<li>PostgreSQL：single-primary、跨 region async replication、90% 場景夠用</li>
<li>Spanner：全球線性化、強一致跨 region、需要 GCP + 接受 latency / 成本</li>
<li>從 PostgreSQL 升級 Spanner 的判準：流量明確跨 region，且跨 region 一致性是 product requirement</li>
<li>詳見 <a href="/blog/backend/01-database/vendors/postgresql/" data-link-title="PostgreSQL" data-link-desc="多用途 OLTP 主流關聯式資料庫、MVCC、豐富 SQL 特性、是 Aurora / Cosmos DB / Spanner / CockroachDB / Aurora DSQL 的相容目標">PostgreSQL vendor page</a> 取捨段 + <a href="/blog/backend/01-database/global-distributed-oltp/" data-link-title="1.11 全球分散式 OLTP" data-link-desc="Spanner / Aurora DSQL / Cosmos DB multi-region write / CockroachDB / TiDB 的全球一致性取捨">1.11 全球分散式 OLTP</a></li>
</ul>
<h2 id="容量規劃要點">容量規劃要點</h2>
<p>從 09 案例庫 + Spanner 文件提煉：</p>
<p><strong>1. 節點數量 = 容量單位</strong>：</p>
<ul>
<li>節點配置通常用較長週期 review，並在事件高峰前預先調整</li>
<li>線性擴展讓 forecast 簡單（2x 流量 → 2x 節點）</li>
<li>對應 <a href="/blog/backend/09-performance-capacity/capacity-planning/" data-link-title="9.6 容量規劃模型" data-link-desc="peak forecast、headroom budget、growth curve、autoscaling sizing">9.6 容量規劃模型</a> 的「不可水平擴容服務」反向 — Spanner 是 <em>可水平擴容</em> 但需要 <em>提前 provision</em></li>
</ul>
<p><strong>2. 跨 region quorum 配置</strong>：</p>
<ul>
<li>multi-region instance 可選擇哪些 region 是 voting member</li>
<li>voting region 數量決定 failure domain</li>
<li>跨大洲 voting 延遲高、跨大陸內可接受</li>
</ul>
<p><strong>3. 100 PU 起跳的 granular sizing</strong>：</p>
<ul>
<li>早期 Spanner 最小單位 1 node（約 $1000+/month）、中小負載難用</li>
<li>後來推出 100 PU（1/10 node、約 $65/month）、讓小負載也能 evaluate</li>
</ul>
<p><strong>4. 跨環境與新產品能力要查官方文件</strong>：</p>
<ul>
<li>Spanner 的跨環境、graph、PostgreSQL dialect 與 change streams 能力持續演進</li>
<li>實作前要用官方文件確認可用 region、版本、限制與 pricing</li>
</ul>
<p><strong>5. TrueTime 是 Spanner 價值之一</strong>：</p>
<ul>
<li>Spanner 還有 schema migration without downtime、change streams、interleaved tables</li>
<li>評估 Spanner 要同時看跨 region 強一致與整體 SQL 工程能力</li>
</ul>
<h2 id="deep-article已完成">Deep article（已完成）</h2>
<p>本批 4 篇 deep article 已完成、覆蓋 Spanner 從 TrueTime 到 Cloud SQL 遷移的核心 production 議題：</p>
<table>
  <thead>
      <tr>
          <th>主題</th>
          <th>文章</th>
          <th>對應 production 議題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>TrueTime 是手段、line-rate scaling 才是設計目的、commit wait 數學</td>
          <td><a href="truetime-api-depth/">truetime-api-depth</a></td>
          <td>9.C10 Google internal dogfood 線性擴展模式、ε 暴衝失敗模式、cross-region voting latency 影響</td>
      </tr>
      <tr>
          <td>external consistency / serializability / linearizability 精確定義差異</td>
          <td><a href="consistency-models-comparison/">consistency-models-comparison</a></td>
          <td>PG SSI / CockroachDB / Spanner / Aurora DSQL line-rate scaling 對照、9.C10 cross-region quorum 100-200ms</td>
      </tr>
      <tr>
          <td>Schema migration without downtime + interleaved tables 物理 layout</td>
          <td><a href="schema-migration-interleaved-tables/">schema-migration-interleaved-tables</a></td>
          <td>TrueTime version timestamp、5 production 踩雷、跟 PostgreSQL online schema change 對照</td>
      </tr>
      <tr>
          <td>Cloud SQL for PostgreSQL → Spanner（Type E paradigm shift）playbook</td>
          <td><a href="migrate-from-cloud-sql-pg/">migrate-from-cloud-sql-pg</a></td>
          <td>sizing barrier（100 pu 起跳）+ &lt; 50ms write latency no-go、cost crossover 報告、9.C10 dogfood 邊界</td>
      </tr>
      <tr>
          <td>Change Streams (CDC)：data change record、watch partition、下游整合</td>
          <td><a href="change-streams-cdc/">change-streams-cdc</a></td>
          <td>OLTP 變更餵搜尋 / 快取 / 分析、child partition 接力、retention 失敗、跟 DynamoDB Streams 對照</td>
      </tr>
      <tr>
          <td>PostgreSQL dialect vs GoogleSQL、相容子集邊界、dialect 不可逆</td>
          <td><a href="postgresql-dialect/">postgresql-dialect</a></td>
          <td>PostgreSQL 生態遷入、相容性 audit、dialect 鎖定的高代價回退、何時選 PG dialect</td>
      </tr>
      <tr>
          <td>Spanner Graph (2024)：property graph、跟 relational 共存、GQL</td>
          <td><a href="spanner-graph/">spanner-graph</a></td>
          <td>多跳關係查詢、edge table layout 不可逆設計代價、super node 扇出、何時用專用 graph DB</td>
      </tr>
      <tr>
          <td>Spanner ↔ BigQuery federation：OLTP/OLAP 分工、Data Boost</td>
          <td><a href="bigquery-federation/">bigquery-federation</a></td>
          <td>分析查詢拖垮 OLTP、Data Boost workload 隔離、federation vs change-stream 落地、何時分出去</td>
      </tr>
  </tbody>
</table>
<p>DB4 cross-vendor entry：先看 <a href="../cockroachdb/aurora-dsql-spanner-decision-tree/">CockroachDB / Aurora DSQL / Spanner 決策樹</a> 識別 driver path、再進本 vendor 深度。</p>
<h2 id="後續擴充仍待補">後續擴充（仍待補）</h2>
<ul>
<li>Spanner Graph 進階查詢 lab（GQL pattern、super node 處理、遍歷效能調校）</li>
<li>Data Boost 容量規劃與成本模型 deep dive</li>
<li>Change Streams → Dataflow hands-on lab（建 stream、部署 pipeline、驗證 end-to-end）</li>
<li>Spanner regional → multi-region topology 升級 playbook</li>
</ul>
<h2 id="anti-recommendation-與升級路由">Anti-recommendation 與升級路由</h2>
<p>Spanner 的 global strong consistency 是高價值能力，也會把 latency、region layout 與 GCP lock-in 帶進核心架構。這一段先說何時維持 Cloud SQL / Aurora，再說何時升級 Spanner、CockroachDB、Aurora DSQL 或 Bigtable / DynamoDB。</p>
<table>
  <thead>
      <tr>
          <th>機制 / 路線</th>
          <th>維持簡單設計的條件</th>
          <th>升級訊號</th>
          <th>主要引用路徑</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Cloud SQL / Aurora</td>
          <td>single-region primary 足夠、跨 region 只需 async DR / read</td>
          <td>跨 region 寫入順序是產品契約、double-spend / oversell 代價高</td>
          <td><a href="/blog/backend/01-database/vendors/aurora/" data-link-title="AWS Aurora" data-link-desc="AWS managed PostgreSQL / MySQL、storage / compute 分離、&#43;75% 效能改善的 production 證據">Aurora vendor</a>、<a href="/blog/backend/knowledge-cards/rpo/" data-link-title="RPO" data-link-desc="說明恢復點目標如何定義可接受資料損失範圍">RPO</a></td>
      </tr>
      <tr>
          <td>Spanner regional</td>
          <td>單 region 強一致與水平擴容已足夠</td>
          <td>需要 multi-region availability、regional failure survival</td>
          <td><a href="/blog/backend/knowledge-cards/quorum/" data-link-title="Quorum" data-link-desc="分散式系統以多數節點同意作為提交或讀取有效性的門檻">Quorum</a>、<a href="/blog/backend/knowledge-cards/external-consistency/" data-link-title="External Consistency" data-link-desc="交易可見順序與外部真實時間順序一致的強一致性語意">External Consistency</a></td>
      </tr>
      <tr>
          <td>Spanner multi-region</td>
          <td>GCP 生態、SQL workload、global consistency 是核心需求</td>
          <td>跨洲 p99 目標過低、成本或 GCP lock-in 成為主要風險</td>
          <td><a href="/blog/backend/knowledge-cards/latency-budget/" data-link-title="Latency Budget" data-link-desc="把 user-perceived latency 拆到每個 stage 的配額、反推架構選擇">Latency Budget</a>、<a href="/blog/backend/knowledge-cards/global-oltp/" data-link-title="Global OLTP" data-link-desc="跨地理區域仍維持交易一致性的 OLTP 設計責任與代價">Global OLTP</a></td>
      </tr>
      <tr>
          <td>CockroachDB</td>
          <td>GCP-only managed 服務可接受</td>
          <td>跨雲、on-prem、自管或 PostgreSQL wire 相容是硬需求</td>
          <td><a href="/blog/backend/01-database/vendors/cockroachdb/" data-link-title="CockroachDB" data-link-desc="分散式 SQL、PostgreSQL 相容、跨區強一致、Spanner 的開源 / 跨雲替代">CockroachDB vendor</a></td>
      </tr>
      <tr>
          <td>Aurora DSQL</td>
          <td>團隊已在 GCP 或需要 Spanner 成熟度</td>
          <td>AWS 生態、serverless distributed SQL、PostgreSQL 相容是主訴求</td>
          <td><a href="/blog/backend/01-database/vendors/postgresql/migrate-to-aurora-dsql/" data-link-title="PostgreSQL → Aurora DSQL Migration：PG wire-compatible Distributed SQL 的 Paradigm Shift" data-link-desc="Aurora DSQL（2024-12 re:Invent preview / 2025-05 GA）是 AWS 推的 PG wire-compatible *active-active distributed SQL*、跟 self-managed PG / Aurora PG 不同 paradigm（OCC &#43; snapshot isolation &#43; multi-region strong consistency）。Migration 結構是 *protocol drop-in &#43; paradigm shift*：app SQL 不太改、但 transaction retry / extension 缺位 / 多 region 一致性需重設計。本文走 DSQL vs Aurora PG vs self-managed PG 三軸對比、為什麼遷的三條 driver（global write / operational zero-touch / region resiliency）、Type E phased plan、5 production 踩雷（transaction retry 沒處理 / extension 缺位 / sequence throughput 限制 / Aurora PG 直升 DSQL 不可行 / region failover semantic）、跟 PG → Aurora 跟 PG → CockroachDB 對比">PG → Aurora DSQL Migration</a></td>
      </tr>
      <tr>
          <td>Bigtable / DynamoDB</td>
          <td>workload 可接受 eventual consistency 或 KV / wide-column</td>
          <td>強一致 SQL 的協調成本高於產品收益</td>
          <td><a href="/blog/backend/01-database/vendors/dynamodb/" data-link-title="DynamoDB" data-link-desc="AWS managed key-value、partition-based scaling、9000 萬 RPS sustained 實戰證據">DynamoDB vendor</a></td>
      </tr>
  </tbody>
</table>
<p>Spanner 的簡單路徑是先證明跨 region 一致性是產品需求。若只是想要全球 read latency，read replica、cache、edge KV 或 eventual consistency pipeline 可能更划算；Spanner 適合把「全球寫入順序正確」視為產品承諾的資料。</p>
<p>Region layout 的升級路徑要先定義 leader、voting replica 與使用者地理分布。跨洲 quorum 會把物理延遲放進 transaction path，因此 latency budget、降級策略與 read staleness policy 要一起寫進設計。</p>
<h2 id="已知-limitation-與後續路由">已知 limitation 與後續路由</h2>
<p>Spanner overview 目前完成 global SQL 判斷。下一輪 deep article / playbook 應補 TrueTime、external consistency、PostgreSQL dialect、interleaved tables、change streams、Cloud SQL / PostgreSQL → Spanner migration 與 Spanner / BigQuery federation。</p>
<h2 id="案例對照">案例對照</h2>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>規模</th>
          <th>教學重點</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/cases/spanner-planetary-scale-database-gcp/" data-link-title="9.C10 Cloud Spanner：每秒 10 億請求的全球一致性資料庫" data-link-desc="Google Cloud Spanner 內部峰值 10 億 req/sec、跨地區強一致 — 全球分散式 OLTP 容量參考">9.C10 Cloud Spanner</a></td>
          <td>&gt; 10 億 req/sec、線性擴展</td>
          <td>全球強一致 OLTP 標竿</td>
      </tr>
  </tbody>
</table>
<p>Spanner case 的讀法是先看一致性需求，再看容量數字。10 億 req/sec 證明它能水平擴展，但讀者真正要回收的是「計費、訂閱、庫存、交易順序」這類需要 global external consistency 的產品壓力。</p>
<h2 id="反向-sibling-路由">反向 sibling 路由</h2>
<p>Spanner 的反向 sibling 路由用來把 global strong consistency 和雲端代管責任一起判讀。若讀者從 PostgreSQL / MySQL 過來，先確認是否具產品契約等級的 external consistency 需求；若只是 managed SQL 與 replica scaling，回 <a href="/blog/backend/01-database/vendors/aurora/" data-link-title="AWS Aurora" data-link-desc="AWS managed PostgreSQL / MySQL、storage / compute 分離、&#43;75% 效能改善的 production 證據">Aurora vendor</a>；若要 PostgreSQL-like distributed SQL 且需要自管或多雲彈性，對照 <a href="/blog/backend/01-database/vendors/cockroachdb/" data-link-title="CockroachDB" data-link-desc="分散式 SQL、PostgreSQL 相容、跨區強一致、Spanner 的開源 / 跨雲替代">CockroachDB vendor</a>；若 access pattern 是固定 KV / document，先看 <a href="/blog/backend/01-database/vendors/dynamodb/" data-link-title="DynamoDB" data-link-desc="AWS managed key-value、partition-based scaling、9000 萬 RPS sustained 實戰證據">DynamoDB vendor</a> 或 <a href="/blog/backend/01-database/vendors/cosmosdb/" data-link-title="Azure Cosmos DB" data-link-desc="全球分散式 multi-model DB、5 個 consistency levels、Microsoft 自家 dogfood 證據">Cosmos DB vendor</a>。</p>
<p>這條路由的判準是交易順序是否跨 region 影響產品正確性。Spanner 的價值在 external consistency、schema 與 SQL 能力、全球 deployment 與 Google Cloud operation model 的組合；若產品只需要 eventual / session consistency，較輕的 NoSQL 或 managed SQL 常有更低成本。</p>
<h2 id="常見陷阱">常見陷阱</h2>
<ul>
<li><strong>誤以為跨 region 強一致沒有延遲代價</strong>：跨洲 quorum 100-200ms 是物理成本</li>
<li><strong>設計 schema 像傳統 PostgreSQL</strong>：Spanner 有 interleaved tables、適當用能加速查詢</li>
<li><strong>所有讀取都用強一致</strong>：read-only transaction 可選 bounded staleness，reporting 類路徑常能用 <a href="/blog/backend/knowledge-cards/stale-read/" data-link-title="Stale Read" data-link-desc="讀取到落後於最新寫入版本的舊資料">stale read</a> 換較低成本</li>
<li><strong>單 region 用 Spanner</strong>：浪費、Cloud SQL / Aurora 更便宜</li>
<li><strong>不評估 100 PU 起跳</strong>：早年 1 node minimum、現在 100 PU 起、small workload 也可以 POC</li>
</ul>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>完整 T1 對照：<a href="/blog/backend/01-database/vendors/" data-link-title="資料庫 Vendor 清單" data-link-desc="規劃 SQL、managed SQL、document、KV 與 distributed SQL 的服務頁撰寫順序與教學大綱">01-database vendors index</a></li>
<li>平行：<a href="/blog/backend/01-database/vendors/aurora/" data-link-title="AWS Aurora" data-link-desc="AWS managed PostgreSQL / MySQL、storage / compute 分離、&#43;75% 效能改善的 production 證據">Aurora vendor</a>、<a href="/blog/backend/01-database/vendors/dynamodb/" data-link-title="DynamoDB" data-link-desc="AWS managed key-value、partition-based scaling、9000 萬 RPS sustained 實戰證據">DynamoDB vendor</a>、<a href="/blog/backend/01-database/vendors/cockroachdb/" data-link-title="CockroachDB" data-link-desc="分散式 SQL、PostgreSQL 相容、跨區強一致、Spanner 的開源 / 跨雲替代">CockroachDB vendor</a></li>
<li>上游：<a href="/blog/backend/01-database/global-distributed-oltp/" data-link-title="1.11 全球分散式 OLTP" data-link-desc="Spanner / Aurora DSQL / Cosmos DB multi-region write / CockroachDB / TiDB 的全球一致性取捨">1.11 全球分散式 OLTP</a></li>
<li>跨模組：<a href="/blog/backend/09-performance-capacity/capacity-planning/" data-link-title="9.6 容量規劃模型" data-link-desc="peak forecast、headroom budget、growth curve、autoscaling sizing">9.6 容量規劃模型</a> — 全球 OLTP 的容量規劃特殊性</li>
<li>Last reviewed：2026-05-22（processing units / PostgreSQL interface / TrueTime 文件屬時間敏感 claim）</li>
<li>官方：<a href="https://cloud.google.com/spanner">Cloud Spanner</a>、<a href="https://cloud.google.com/spanner/docs/true-time-external-consistency">TrueTime: Time Distributed in Spanner</a></li>
</ul>
]]></content:encoded></item><item><title>GCP Cloud Operations</title><link>https://tarrragon.github.io/blog/backend/04-observability/vendors/gcp-cloud-operations/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/04-observability/vendors/gcp-cloud-operations/</guid><description>&lt;p>GCP Cloud Operations（前 Stackdriver）是 GCP 原生 observability 套件、承擔三個責任：GCP 服務內建 Cloud Logging / Monitoring / Trace（無需配置）、跟 GCP 資源 model 深度整合（project / folder / org）、BigQuery 匯出長期 logs 跟分析。設計取捨偏向「GCP 生態 turnkey + BigQuery 整合 + Cloud Profiler 持續 profiling」、跨雲跟進階 distributed tracing 是限制。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>用 gcloud / Console 查 Cloud Logging / Monitoring&lt;/li>
&lt;li>設計 structured logging + log-based metrics&lt;/li>
&lt;li>用 Cloud Monitoring uptime checks + SLO + alerting policy&lt;/li>
&lt;li>用 Cloud Trace + Cloud Profiler 做 application performance&lt;/li>
&lt;li>配置 BigQuery 匯出長期 logs 跟分析&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑5-分鐘把-cloud-operations-跑起來">最短路徑：5 分鐘把 Cloud Operations 跑起來&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 1. GCP 預設啟用 Cloud Logging / Monitoring（free tier 額度）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: GKE / Cloud Run / Cloud Functions 自動 log + metric&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="c1"># 2. 查詢 logs&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: gcloud logging read &amp;#39;resource.type=&amp;#34;gae_app&amp;#34; AND severity&amp;gt;=ERROR&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">&lt;span class="c1"># 3. 用 Logs Explorer 視覺化查詢&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: Console → Logging → Logs Explorer&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="日常操作與決策形狀">日常操作與決策形狀&lt;/h2>
&lt;h3 id="cloud-logging-結構化-logs">Cloud Logging 結構化 logs&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>jsonPayload：結構化 log（推薦）&lt;/li>
&lt;li>Severity 7 級（DEBUG / INFO / NOTICE / WARNING / ERROR / CRITICAL / ALERT）&lt;/li>
&lt;li>Resource type / Resource labels：自動帶入&lt;/li>
&lt;li>對應 &lt;a href="https://tarrragon.github.io/blog/backend/04-observability/cases/cloud-trace-otlp-adoption/" data-link-title="4.C5 Google Cloud：Cloud Trace 導入 OTLP 入口" data-link-desc="觀測平台從專有入口擴展到 OTLP 標準通道的案例。">4.C5 Cloud Trace OTLP&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="log-based-metrics">Log-based metrics&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>Counter metric：log 出現次數&lt;/li>
&lt;li>Distribution metric：log field 數值分布&lt;/li>
&lt;li>適合：把 application log 轉成 metric trigger alert&lt;/li>
&lt;li>對應指令：&lt;code>gcloud logging metrics create&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="cloud-monitoring-uptime-checks--slo">Cloud Monitoring uptime checks / SLO&lt;/h3>
&lt;p>子議題：&lt;/p></description><content:encoded><![CDATA[<p>GCP Cloud Operations（前 Stackdriver）是 GCP 原生 observability 套件、承擔三個責任：GCP 服務內建 Cloud Logging / Monitoring / Trace（無需配置）、跟 GCP 資源 model 深度整合（project / folder / org）、BigQuery 匯出長期 logs 跟分析。設計取捨偏向「GCP 生態 turnkey + BigQuery 整合 + Cloud Profiler 持續 profiling」、跨雲跟進階 distributed tracing 是限制。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>用 gcloud / Console 查 Cloud Logging / Monitoring</li>
<li>設計 structured logging + log-based metrics</li>
<li>用 Cloud Monitoring uptime checks + SLO + alerting policy</li>
<li>用 Cloud Trace + Cloud Profiler 做 application performance</li>
<li>配置 BigQuery 匯出長期 logs 跟分析</li>
</ol>
<h2 id="最短路徑5-分鐘把-cloud-operations-跑起來">最短路徑：5 分鐘把 Cloud Operations 跑起來</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 1. GCP 預設啟用 Cloud Logging / Monitoring（free tier 額度）</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># TODO: GKE / Cloud Run / Cloud Functions 自動 log + metric</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 2. 查詢 logs</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="c1"># TODO: gcloud logging read &#39;resource.type=&#34;gae_app&#34; AND severity&gt;=ERROR&#39;</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="c1"># 3. 用 Logs Explorer 視覺化查詢</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="c1"># TODO: Console → Logging → Logs Explorer</span></span></span></code></pre></div><h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="cloud-logging-結構化-logs">Cloud Logging 結構化 logs</h3>
<p>子議題：</p>
<ul>
<li>jsonPayload：結構化 log（推薦）</li>
<li>Severity 7 級（DEBUG / INFO / NOTICE / WARNING / ERROR / CRITICAL / ALERT）</li>
<li>Resource type / Resource labels：自動帶入</li>
<li>對應 <a href="/blog/backend/04-observability/cases/cloud-trace-otlp-adoption/" data-link-title="4.C5 Google Cloud：Cloud Trace 導入 OTLP 入口" data-link-desc="觀測平台從專有入口擴展到 OTLP 標準通道的案例。">4.C5 Cloud Trace OTLP</a></li>
</ul>
<h3 id="log-based-metrics">Log-based metrics</h3>
<p>子議題：</p>
<ul>
<li>Counter metric：log 出現次數</li>
<li>Distribution metric：log field 數值分布</li>
<li>適合：把 application log 轉成 metric trigger alert</li>
<li>對應指令：<code>gcloud logging metrics create</code></li>
</ul>
<h3 id="cloud-monitoring-uptime-checks--slo">Cloud Monitoring uptime checks / SLO</h3>
<p>子議題：</p>
<ul>
<li>Uptime check：HTTP / HTTPS / TCP / ICMP 多地點 probe</li>
<li>SLO：service indicator + objective + window + burn rate alert</li>
<li>Multi-window SLO alert（類 Honeycomb burn rate）</li>
<li>對應 <a href="/blog/backend/knowledge-cards/burn-rate/" data-link-title="Burn Rate" data-link-desc="說明 error budget 消耗速度如何支援告警與事故分級">knowledge cards burn-rate</a></li>
</ul>
<h3 id="cloud-trace">Cloud Trace</h3>
<p>子議題：</p>
<ul>
<li>接受 OTLP（Cloud Trace 2.0+）</li>
<li>自動採集 GCP service（Cloud Run / GKE / App Engine）</li>
<li>對應 <a href="/blog/backend/04-observability/cases/cloud-trace-otlp-adoption/" data-link-title="4.C5 Google Cloud：Cloud Trace 導入 OTLP 入口" data-link-desc="觀測平台從專有入口擴展到 OTLP 標準通道的案例。">4.C5 Cloud Trace OTLP adoption</a></li>
<li>跟 X-Ray 比、distributed tracing 較基礎</li>
</ul>
<h2 id="deep-article">Deep Article</h2>
<ul>
<li><a href="cloud-monitoring-mql/">Cloud Monitoring Metrics Model 與 MQL</a>：GCP metrics model、MQL vs PromQL、custom metrics 設計、alerting policy 與 Managed Prometheus 整合</li>
<li><a href="cloud-logging-export-compliance/">Cloud Logging 查詢、匯出與合規</a>：查詢語言、log router / sink 匯出、retention 設計、organization-level 聚合、audit log 與 PII / CMEK 合規治理</li>
</ul>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<h3 id="cloud-profiler">Cloud Profiler</h3>
<p>子議題：</p>
<ul>
<li>持續 profiling（CPU / Heap / Wall time / Mutex）</li>
<li>支援 Go / Java / Python / Node</li>
<li>Flame graph 視覺化</li>
<li>跟 Pyroscope / Datadog Profiler 對照</li>
</ul>
<h3 id="bigquery-匯出長期儲存">BigQuery 匯出長期儲存</h3>
<p>子議題：</p>
<ul>
<li>Log Router：定義 sink 把 logs 匯出 BigQuery / GCS / Pub/Sub</li>
<li>BigQuery 適合長期 + 分析查詢（SQL）</li>
<li>對應 <a href="/blog/backend/04-observability/cases/healthcare-access-traceability-and-retention/" data-link-title="Healthcare：存取可追溯性與保留邊界" data-link-desc="在資料主權限制下，建立可追溯存取證據與分層保留策略。">4.C3 Healthcare retention</a></li>
<li>Cost：BigQuery storage 比 Cloud Logging cheaper</li>
</ul>
<h3 id="error-reporting">Error Reporting</h3>
<p>子議題：</p>
<ul>
<li>自動聚合 application error</li>
<li>各語言 client library（Python / Java / Node / Go）</li>
<li>跟 Sentry 對照（Sentry 更深 / 更廣）</li>
</ul>
<h3 id="cloud-monitoring-agent">Cloud Monitoring agent</h3>
<p>子議題：</p>
<ul>
<li>Ops Agent（取代 Stackdriver agent）：統一 logs + metrics 採集</li>
<li>支援 GCE / Bare metal / AWS / on-prem</li>
<li>配置：YAML config + receivers / processors / exporters（類 OTel Collector）</li>
</ul>
<h3 id="multi-project--multi-region-治理">Multi-project / Multi-region 治理</h3>
<p>子議題：</p>
<ul>
<li>Aggregated logging sink：跨 project 集中 logs</li>
<li>Cross-project SLO</li>
<li>Workspace（前 Stackdriver workspace）已 deprecated、改用 Metrics Scope</li>
</ul>
<h3 id="otlp-integration">OTLP integration</h3>
<p>子議題：</p>
<ul>
<li>Cloud Trace 接受 OTLP（2024 GA）</li>
<li>Cloud Monitoring 接受 OTel metrics（via OTel Collector + GCP exporter）</li>
<li>Logs in OTel 跟 Cloud Logging 整合（成熟中）</li>
<li>對應 <a href="/blog/backend/04-observability/cases/cloud-trace-otlp-adoption/" data-link-title="4.C5 Google Cloud：Cloud Trace 導入 OTLP 入口" data-link-desc="觀測平台從專有入口擴展到 OTLP 標準通道的案例。">4.C5 Cloud Trace OTLP</a></li>
</ul>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<h3 id="logs-沒出現">Logs 沒出現</h3>
<p>操作原則：先看 resource type / project 是否對、再看 IAM 權限。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># TODO: gcloud logging read --project=&lt;id&gt; --resource-type=...</span></span></span></code></pre></div><h3 id="monitoring-查不到-metric">Monitoring 查不到 metric</h3>
<p>操作原則：metric name + project + filter 是否對。對應 Metrics Explorer 確認 metric 存在。</p>
<h3 id="slo-alert-noise">SLO alert noise</h3>
<p>操作原則：multi-window burn rate 設計避免噪音。</p>
<h3 id="cloud-trace-太空">Cloud Trace 太空</h3>
<p>操作原則：sampling 不足或 SDK 沒配置。判讀：Cloud Trace 看 span count + 確認 SDK Cloud Trace exporter 設定。</p>
<h3 id="bigquery-匯出-cost-爆">BigQuery 匯出 cost 爆</h3>
<p>操作原則：sink filter 沒收斂、所有 logs 都匯。判讀：Cloud Logging usage 看 export volume。</p>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>多雲統一觀測</td>
          <td><a href="/blog/backend/04-observability/vendors/datadog/" data-link-title="Datadog" data-link-desc="All-in-one SaaS 觀測平台、APM / Logs / Metrics / RUM / Security">Datadog</a> / <a href="/blog/backend/04-observability/vendors/grafana-stack/" data-link-title="Grafana Stack" data-link-desc="Grafana / Loki / Tempo / Mimir / Pyroscope 全棧">Grafana Stack</a> / <a href="/blog/backend/04-observability/vendors/opentelemetry/" data-link-title="OpenTelemetry" data-link-desc="可觀測性開放標準、SDK 與 Collector">OTel</a></td>
      </tr>
      <tr>
          <td>進階 APM 廣度</td>
          <td><a href="/blog/backend/04-observability/vendors/datadog/" data-link-title="Datadog" data-link-desc="All-in-one SaaS 觀測平台、APM / Logs / Metrics / RUM / Security">Datadog</a></td>
      </tr>
      <tr>
          <td>High-cardinality debug</td>
          <td><a href="/blog/backend/04-observability/vendors/honeycomb/" data-link-title="Honeycomb" data-link-desc="High-cardinality observability 平台、events-based 模型">Honeycomb</a></td>
      </tr>
      <tr>
          <td>Logs full-text 進階</td>
          <td><a href="/blog/backend/04-observability/vendors/elastic-stack/" data-link-title="Elastic Stack" data-link-desc="ELK：Elasticsearch / Logstash / Kibana &#43; Beats / APM">Elastic</a> / Loki</td>
      </tr>
      <tr>
          <td>AWS / Azure 生態</td>
          <td><a href="/blog/backend/04-observability/vendors/aws-cloudwatch/" data-link-title="AWS CloudWatch" data-link-desc="AWS 原生觀測性服務、Logs / Metrics / Traces (X-Ray)">CloudWatch</a> / Azure Monitor</td>
      </tr>
      <tr>
          <td>Error tracking 進階</td>
          <td><a href="/blog/backend/04-observability/vendors/sentry/" data-link-title="Sentry" data-link-desc="Error tracking 主流、APM / Profiling / Session Replay 擴展">Sentry</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>gcloud / Cloud Console UI 操作詳細</li>
<li>各 GCP 服務的內建 metric 完整列表</li>
<li>Cloud Trace span structure 細節</li>
<li>BigQuery SQL syntax</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<h3 id="直接相關案例">直接相關案例</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>主討論議題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/cloud-trace-otlp-adoption/" data-link-title="4.C5 Google Cloud：Cloud Trace 導入 OTLP 入口" data-link-desc="觀測平台從專有入口擴展到 OTLP 標準通道的案例。">4.C5 Cloud Trace OTLP</a></td>
          <td>OTLP 在 GCP 的採用路徑</td>
      </tr>
  </tbody>
</table>
<h3 id="跨-vendor-對照">跨 vendor 對照</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>對 Cloud Operations 的對應</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/fintech-audit-evidence-observability/" data-link-title="FinTech：審計證據鏈的可觀測性設計" data-link-desc="把交易與存取事件轉成可回查證據，降低合規審核與事故判讀落差。">4.C1 Fintech audit</a></td>
          <td>Cloud Logging + BigQuery 作為審計證據與長期分析</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/healthcare-access-traceability-and-retention/" data-link-title="Healthcare：存取可追溯性與保留邊界" data-link-desc="在資料主權限制下，建立可追溯存取證據與分層保留策略。">4.C3 Healthcare retention</a></td>
          <td>BigQuery 匯出長期 retention</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/failure-otel-migration-signal-drift/" data-link-title="4.C9 反例：OTel 遷移後訊號漂移" data-link-desc="雙軌採集未對齊導致告警與 SLO 判讀失真。">4.C9 OTel migration signal drift</a></td>
          <td>（反例）Cloud Trace ↔ OTLP 雙軌語意對齊</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/contrast-observability-rollout-by-scale/" data-link-title="4.C10 對照：規模差異下的觀測遷移" data-link-desc="觀測遷移在不同規模團隊下的流程與風險差異。">4.C10 規模對照</a></td>
          <td>GCP-only 場景優先 Cloud Operations</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游概念：<a href="/blog/backend/04-observability/telemetry-data-quality/" data-link-title="4.17 Telemetry Data Quality" data-link-desc="把 missing signal、schema drift、sampling bias 與 timestamp skew 變成資料品質問題">4.17 Telemetry Data Quality</a></li>
<li>平行 vendor：<a href="/blog/backend/04-observability/vendors/opentelemetry/" data-link-title="OpenTelemetry" data-link-desc="可觀測性開放標準、SDK 與 Collector">OpenTelemetry</a>、<a href="/blog/backend/04-observability/vendors/aws-cloudwatch/" data-link-title="AWS CloudWatch" data-link-desc="AWS 原生觀測性服務、Logs / Metrics / Traces (X-Ray)">CloudWatch</a></li>
<li>下游能力：<a href="/blog/backend/04-observability/observability-evidence-package/" data-link-title="4.20 Observability Evidence Package" data-link-desc="把 log、metric、trace、audit 與資料品質限制包成可交接證據">4.20 Observability Evidence Package</a></li>
</ul>
]]></content:encoded></item><item><title>Instatus</title><link>https://tarrragon.github.io/blog/backend/08-incident-response/vendors/instatus/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/08-incident-response/vendors/instatus/</guid><description>&lt;p>Instatus 是輕量 status page SaaS、承擔三個責任：簡潔現代 UI 的 status page、component + incident management、跟 IR 工具整合（incident.io / Rootly / FireHydrant）。設計取捨偏向「價格親民 + UI 現代 + 中小團隊適用」、是 Atlassian Statuspage 的 budget-friendly 替代。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Instatus 主打 &lt;em>fast + cheap + custom domain&lt;/em>、產品形狀直接對標 &lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/vendors/atlassian-statuspage/" data-link-title="Atlassian Statuspage" data-link-desc="公開狀態頁 SaaS、Atlassian 出品、enterprise polish &amp;#43; Atlassian 生態整合、subscriber notification &amp;#43; component dependency 是核心責任">Atlassian Statuspage&lt;/a> 的核心功能（component / incident / subscriber / custom domain），但價格約 1/3-1/5、free tier 就包含 custom domain SSL。typical 客戶是中小 SaaS、indie hacker / 個人 project、不需要 enterprise SLA 但要對外呈現專業感的團隊；不適合需要 audit log、SAML SSO、複雜 access role、SLA 報表的大企業 — 那是 Statuspage / &lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/vendors/firehydrant/" data-link-title="FireHydrant" data-link-desc="IR &amp;#43; retrospective 平台、Slack / Teams 整合、service catalog &amp;#43; runbook automation 為核心">FireHydrant&lt;/a> status 模組的場域。&lt;/p>
&lt;p>Instatus 的取捨設計：UI 走 &lt;em>modern + minimal&lt;/em>、頁面 load 快（自稱 ~50ms）、subscriber notification provider 多元（Email / SMS / Slack / Discord / Teams / Telegram / RSS / Webhook），用 &lt;em>generous free tier&lt;/em> 拉初期用戶、進階功能（更多 component、更多 subscriber、white-label、SLA report）走分層 pricing。&lt;/p>
&lt;p>關鍵張力：&lt;em>cheap + custom domain from free tier&lt;/em> ↔ &lt;em>enterprise governance（SAML / audit / role）&lt;/em>。Instatus 故意把 enterprise governance 砍掉以壓 pricing、所以團隊規模成長到需要區分多角色 / 留 audit trail 時、會撞到產品天花板、要評估遷移。提早估算 &lt;em>什麼時候撞到天花板&lt;/em> 比事故當下才發現省事很多。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;ol>
&lt;li>建 Instatus + 設 component&lt;/li>
&lt;li>寫 incident template + update&lt;/li>
&lt;li>配置 subscriber notification&lt;/li>
&lt;li>API 從 IR 平台 push&lt;/li>
&lt;li>評估 Instatus vs Statuspage / Cachet&lt;/li>
&lt;/ol>
&lt;h2 id="最短判讀路徑">最短判讀路徑&lt;/h2>
&lt;p>判斷 Instatus 是否健康承載對外狀態揭露、最少看四件事：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>誰能 publish update&lt;/strong>：team member 角色設計（admin / member / read-only）、incident update 是否走 PR / approval、誤發 update 的回收路徑（edit / delete + email correction）&lt;/li>
&lt;li>&lt;strong>Component 數量 vs pricing tier&lt;/strong>：current tier 的 component limit、現有 / 規劃中的 component 數、跨 tier 切換的成本影響（升 tier 還是合併 component）&lt;/li>
&lt;li>&lt;strong>Custom domain SSL&lt;/strong>：&lt;code>status.example.com&lt;/code> 的 CNAME 是否生效、SSL cert 自動 renew 是否健康（Instatus 用 Let&amp;rsquo;s Encrypt 自動簽發、需在 DNS 加 CAA record 授權）、未來 domain 變更的遷移流程&lt;/li>
&lt;li>&lt;strong>Subscriber notification 健康度&lt;/strong>：subscriber 數量是否逼近 tier 限制、Email / SMS provider quota / bounce rate、Slack / Discord webhook 是否還有效&lt;/li>
&lt;/ul>
&lt;p>四件事任一缺失、就是事故揭露通道有風險、應該優先補完。&lt;/p></description><content:encoded><![CDATA[<p>Instatus 是輕量 status page SaaS、承擔三個責任：簡潔現代 UI 的 status page、component + incident management、跟 IR 工具整合（incident.io / Rootly / FireHydrant）。設計取捨偏向「價格親民 + UI 現代 + 中小團隊適用」、是 Atlassian Statuspage 的 budget-friendly 替代。</p>
<h2 id="服務定位">服務定位</h2>
<p>Instatus 主打 <em>fast + cheap + custom domain</em>、產品形狀直接對標 <a href="/blog/backend/08-incident-response/vendors/atlassian-statuspage/" data-link-title="Atlassian Statuspage" data-link-desc="公開狀態頁 SaaS、Atlassian 出品、enterprise polish &#43; Atlassian 生態整合、subscriber notification &#43; component dependency 是核心責任">Atlassian Statuspage</a> 的核心功能（component / incident / subscriber / custom domain），但價格約 1/3-1/5、free tier 就包含 custom domain SSL。typical 客戶是中小 SaaS、indie hacker / 個人 project、不需要 enterprise SLA 但要對外呈現專業感的團隊；不適合需要 audit log、SAML SSO、複雜 access role、SLA 報表的大企業 — 那是 Statuspage / <a href="/blog/backend/08-incident-response/vendors/firehydrant/" data-link-title="FireHydrant" data-link-desc="IR &#43; retrospective 平台、Slack / Teams 整合、service catalog &#43; runbook automation 為核心">FireHydrant</a> status 模組的場域。</p>
<p>Instatus 的取捨設計：UI 走 <em>modern + minimal</em>、頁面 load 快（自稱 ~50ms）、subscriber notification provider 多元（Email / SMS / Slack / Discord / Teams / Telegram / RSS / Webhook），用 <em>generous free tier</em> 拉初期用戶、進階功能（更多 component、更多 subscriber、white-label、SLA report）走分層 pricing。</p>
<p>關鍵張力：<em>cheap + custom domain from free tier</em> ↔ <em>enterprise governance（SAML / audit / role）</em>。Instatus 故意把 enterprise governance 砍掉以壓 pricing、所以團隊規模成長到需要區分多角色 / 留 audit trail 時、會撞到產品天花板、要評估遷移。提早估算 <em>什麼時候撞到天花板</em> 比事故當下才發現省事很多。</p>
<h2 id="本章目標">本章目標</h2>
<ol>
<li>建 Instatus + 設 component</li>
<li>寫 incident template + update</li>
<li>配置 subscriber notification</li>
<li>API 從 IR 平台 push</li>
<li>評估 Instatus vs Statuspage / Cachet</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Instatus 是否健康承載對外狀態揭露、最少看四件事：</p>
<ul>
<li><strong>誰能 publish update</strong>：team member 角色設計（admin / member / read-only）、incident update 是否走 PR / approval、誤發 update 的回收路徑（edit / delete + email correction）</li>
<li><strong>Component 數量 vs pricing tier</strong>：current tier 的 component limit、現有 / 規劃中的 component 數、跨 tier 切換的成本影響（升 tier 還是合併 component）</li>
<li><strong>Custom domain SSL</strong>：<code>status.example.com</code> 的 CNAME 是否生效、SSL cert 自動 renew 是否健康（Instatus 用 Let&rsquo;s Encrypt 自動簽發、需在 DNS 加 CAA record 授權）、未來 domain 變更的遷移流程</li>
<li><strong>Subscriber notification 健康度</strong>：subscriber 數量是否逼近 tier 限制、Email / SMS provider quota / bounce rate、Slack / Discord webhook 是否還有效</li>
</ul>
<p>四件事任一缺失、就是事故揭露通道有風險、應該優先補完。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="component--incident--subscriber">Component / incident + Subscriber</h3>
<p>Component 是對外揭露單位、status（operational / degraded / partial outage / major outage / maintenance）的抽象顆粒度影響事故揭露的 <em>精準度</em> — 拆太細用戶看不懂、太粗反而失真。實務上跟內部 service map 對齊但 <em>外部可理解語言</em>、例如「Web App」「API」「Login」「Webhooks」、而不是內部 microservice 名稱。</p>
<p>子議題：</p>
<ul>
<li>Component status（跟 Statuspage 相似、操作 surface 簡潔）</li>
<li>Incident template + maintenance window（pre-defined template 讓事故 update 走標準格式、避免臨場寫錯）</li>
<li>Email / SMS / Slack / RSS / Discord / Teams / Telegram / Webhook subscriber、各 channel 的 quota / 失敗模式不同</li>
</ul>
<h3 id="api--ir-整合">API + IR 整合</h3>
<p>REST API 用 token 認證、可程式化 create incident / update / resolve / 改 component status。典型整合：incident.io / Rootly / <a href="/blog/backend/08-incident-response/vendors/firehydrant/" data-link-title="FireHydrant" data-link-desc="IR &#43; retrospective 平台、Slack / Teams 整合、service catalog &#43; runbook automation 為核心">FireHydrant</a> 觸發事故後同步推 Instatus、避免 SOC / on-call 還要手動雙寫。webhook 也支援反向通知、Instatus 上的 incident 變更通知到 IR 平台。</p>
<p>token 是高權限資源（任何持有 token 的 caller 可對外發布 incident）、應該存在 secrets manager、不放程式碼 / 環境變數明文、定期 rotate；CI / IR 平台用獨立 token、出事可單獨 revoke 不影響其他整合。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Instatus</th>
          <th>Atlassian Statuspage</th>
          <th>Better Stack Status</th>
          <th>Cachet (OSS)</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>計費模型</td>
          <td>分層 SaaS、free tier 含 custom domain</td>
          <td>分層 SaaS、custom domain 需付費 tier</td>
          <td>分層 SaaS、跟 monitoring 綁</td>
          <td>OSS 自管、零 license 成本</td>
      </tr>
      <tr>
          <td>UI / 速度</td>
          <td>現代 + 快（~50ms load）</td>
          <td>成熟但偏重</td>
          <td>現代、跟 monitoring 整合</td>
          <td>基本、視自管 stack</td>
      </tr>
      <tr>
          <td>Custom domain</td>
          <td>free tier 即支援、auto SSL</td>
          <td>付費 tier、auto SSL</td>
          <td>付費 tier</td>
          <td>自架 + 自管 cert</td>
      </tr>
      <tr>
          <td>Subscriber</td>
          <td>Email / SMS / Slack / Discord / Teams / Telegram / RSS / Webhook</td>
          <td>同類但部分需高 tier</td>
          <td>Email / Slack 為主</td>
          <td>自實作</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>中小 SaaS / indie hacker / 個人 project</td>
          <td>Enterprise + 跨團隊治理</td>
          <td>已用 Better Stack monitoring</td>
          <td>嚴格資料自管、零外部 SaaS</td>
      </tr>
      <tr>
          <td>退場成本</td>
          <td>低 — 標準 component / incident 結構</td>
          <td>中</td>
          <td>中</td>
          <td>高 — 自管 ops</td>
      </tr>
  </tbody>
</table>
<p>選 Instatus 的核心訴求：<em>cheap + fast UI + custom domain 從 free tier 就有</em>、且不需要 enterprise SLA / SAML / audit 報表。組織成長到要 SAML SSO / multi-team approval / SLA report 時、再評估遷移到 Statuspage 或 IR 平台內建 status。</p>
<p>遷移成本：標準 component / incident 結構讓 Instatus → Statuspage 的搬遷相對單純（資料模型一致、subscriber 列表可匯出）、但 <em>subscriber 重新確認 opt-in</em> 通常是最大痛點 — 切換 domain / provider 時、許多 email subscriber 不會自動轉移、要走再次訂閱流程。</p>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<h3 id="custom-css--branding--multi-language">Custom CSS + branding + Multi-language</h3>
<p><code>status.example.com</code> 走 CNAME 指到 Instatus 配發的 host、SSL 由 Instatus 透過 Let&rsquo;s Encrypt 自動簽發 + renew、不用自己管 cert。custom CSS / logo 在中高 tier 開放、可改色票 / 字型 / layout、適合需要跟主站視覺一致的 SaaS；不要為了美觀過度客製、status page 第一順位是 <em>清楚揭露事故</em>、視覺只是輔助。</p>
<p>multi-language 支援同一 incident 用多語 update、適合對外服務跨地區用戶。注意 <em>誰負責翻譯</em> — 事故當下沒人有空一條條翻、實務上 incident update 寫英文 + 主要語言、其餘語言用 fallback 或事後補。</p>
<h3 id="ir-平台-auto-create-incident">IR 平台 auto-create incident</h3>
<p>Instatus 提供 REST API + webhook、典型整合是 IR 平台偵測事故後 <em>自動 create + update</em> status page incident、收尾時 <em>自動 resolve</em>。常見 pattern：<a href="/blog/backend/08-incident-response/vendors/pagerduty/" data-link-title="PagerDuty" data-link-desc="On-call / alerting 主流 SaaS、IR 平台演化">PagerDuty</a> / <a href="/blog/backend/08-incident-response/vendors/opsgenie/" data-link-title="Opsgenie" data-link-desc="Atlassian on-call、跟 Jira / Statuspage 套件整合、JSM Premium migration 議題">Opsgenie</a> 觸發 high-severity alert → webhook → Instatus API create incident → resolve 時同步收尾。</p>
<p>要點是 <em>誰是 SSoT</em>：incident timeline 由 IR 平台維護、Instatus 是對外揭露 view、不能讓 status page 變第二份 timeline 否則兩邊會漂移。實務上對外揭露的 update 是 IR timeline 的 <em>過濾子集</em>（去掉內部 root cause / 人名 / 攻擊細節）、不是原文同步。</p>
<h3 id="metrics-公開">Metrics 公開</h3>
<p>子議題：uptime / response time、從 monitor source（如外部 uptime monitor、或自家 metrics）拉資料、決定哪些 metric 對外揭露。揭露太細（例：每個 endpoint p99）會讓潛在攻擊者 reverse-engineer attack surface 跟容量上限；只揭露用戶感受得到的 SLI（前台 availability / API success rate）通常足夠、敏感內部指標留在內部 dashboard。</p>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<ul>
<li><strong>Subscriber 沒收到</strong>：跟 Statuspage 類似、provider quota / bounce / spam filter；SMS 在某些地區需要區號白名單；事故當下若大量 subscriber 同時收到 alert、Email provider 可能短時間 throttle、要留 buffer</li>
<li><strong>Custom domain 失效</strong>：DNS CNAME 設定錯 / Let&rsquo;s Encrypt 簽發失敗（CAA record 衝突、需在 DNS 加 <code>letsencrypt.org</code> 授權）/ SSL renew 卡住 — 事故發生時才發現 cert 過期是最常見的二次事故</li>
<li><strong>API 失敗</strong>：rate limit / token 失效 / webhook signature 驗證錯誤；高 severity 事故時 IR 平台可能短時間發大量 update、要確認 rate limit 不會把 update 卡住</li>
<li><strong>Pricing tier 切換成本</strong>：升 tier 取得更多 component / subscriber、但降 tier 可能要先刪 component 或 subscriber 才生效、規劃要先估好成長曲線</li>
<li><strong>Subscriber list 上限</strong>：tier 有 subscriber 上限、逼近時要嘛升 tier、要嘛清理 inactive subscriber（長期 bounce / unsubscribe）；不要等到滿了才處理、新 subscriber 註冊失敗會直接傷品牌信任</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Enterprise SLA / SAML SSO / audit</td>
          <td><a href="/blog/backend/08-incident-response/vendors/atlassian-statuspage/" data-link-title="Atlassian Statuspage" data-link-desc="公開狀態頁 SaaS、Atlassian 出品、enterprise polish &#43; Atlassian 生態整合、subscriber notification &#43; component dependency 是核心責任">Atlassian Statuspage</a></td>
      </tr>
      <tr>
          <td>OSS 自管 / 嚴格資料留在自家環境</td>
          <td>Cachet</td>
      </tr>
      <tr>
          <td>IR 平台內建 status</td>
          <td><a href="/blog/backend/08-incident-response/vendors/firehydrant/" data-link-title="FireHydrant" data-link-desc="IR &#43; retrospective 平台、Slack / Teams 整合、service catalog &#43; runbook automation 為核心">FireHydrant</a></td>
      </tr>
      <tr>
          <td>Alert / on-call SSoT</td>
          <td><a href="/blog/backend/08-incident-response/vendors/pagerduty/" data-link-title="PagerDuty" data-link-desc="On-call / alerting 主流 SaaS、IR 平台演化">PagerDuty</a> / <a href="/blog/backend/08-incident-response/vendors/opsgenie/" data-link-title="Opsgenie" data-link-desc="Atlassian on-call、跟 Jira / Statuspage 套件整合、JSM Premium migration 議題">Opsgenie</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>完整 API reference / Pricing 細節 / Custom CSS 範本</li>
<li>SLA report 設計（Instatus 提供基本 uptime 計算、複雜 SLA 報表走 Statuspage 或 IR 平台）</li>
<li>Status page 對外揭露的法務 / 合約義務（合約 SLA、credit 計算）— 屬法務 / 商務、不在本頁</li>
<li>IR timeline 設計本身（誰寫、誰簽 — 屬 <a href="/blog/backend/08-incident-response/incident-decision-log/" data-link-title="8.19 Incident Decision Log" data-link-desc="把事中假設、決策、證據、回退條件與責任人留下可復盤紀錄">8.19 Incident Decision Log</a> 的範圍）</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p><strong>Instatus 主打輕量、低成本公開狀態頁</strong>：本案例庫的案例多為大型平台、以 Atlassian Statuspage 揭露事故；Instatus 缺乏直接 vendor-level case、可參照的閱讀脈絡是「事故對外揭露的最小可行樣式」、特別適合中小 SaaS 跟 indie 開發者拿來對照自家 status page 的最低門檻。</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>對應主題</th>
          <th>對 Instatus 用戶的啟示</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/08-incident-response/cases/heroku/" data-link-title="Heroku" data-link-desc="Heroku PaaS 事故與 router 層架構脈絡">Heroku cases</a></td>
          <td>平台型服務的 component 拆分與訂閱範例</td>
          <td>component 拆分顆粒度可借鏡（Web / API / Build / Dyno）、中小 SaaS 不需要拆到 region 等級、但要分前後台</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/08-incident-response/cases/discord/" data-link-title="Discord" data-link-desc="Discord Gateway scale-out 事故與容量驚奇">Discord cases</a></td>
          <td>事件導向產品的最小事故時序揭露對照</td>
          <td>incident update 節奏 — 第一則確認、後續更新、resolve 收尾、indie 級服務也至少跑這三段、不能 silent recovery</td>
      </tr>
  </tbody>
</table>
<p>待補 candidate：從 Statuspage 遷移至 Instatus 的中小型 SaaS cost-saving story、indie hacker 個人 project 從零搭 status page 的最小配置（含 custom domain + 一個 component + 一個 incident template）。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/08-incident-response/incident-decision-log/" data-link-title="8.19 Incident Decision Log" data-link-desc="把事中假設、決策、證據、回退條件與責任人留下可復盤紀錄">8.19 Incident Decision Log</a>（決定哪些 timeline event 該對外揭露）</li>
<li>平行：<a href="/blog/backend/08-incident-response/vendors/atlassian-statuspage/" data-link-title="Atlassian Statuspage" data-link-desc="公開狀態頁 SaaS、Atlassian 出品、enterprise polish &#43; Atlassian 生態整合、subscriber notification &#43; component dependency 是核心責任">Atlassian Statuspage</a>、<a href="/blog/backend/08-incident-response/vendors/firehydrant/" data-link-title="FireHydrant" data-link-desc="IR &#43; retrospective 平台、Slack / Teams 整合、service catalog &#43; runbook automation 為核心">FireHydrant</a>、<a href="/blog/backend/08-incident-response/vendors/pagerduty/" data-link-title="PagerDuty" data-link-desc="On-call / alerting 主流 SaaS、IR 平台演化">PagerDuty</a>、<a href="/blog/backend/08-incident-response/vendors/opsgenie/" data-link-title="Opsgenie" data-link-desc="Atlassian on-call、跟 Jira / Statuspage 套件整合、JSM Premium migration 議題">Opsgenie</a></li>
<li>下游：<a href="/blog/backend/08-incident-response/incident-evidence-write-back/" data-link-title="8.22 Incident Evidence Write-back" data-link-desc="把事故證據、決策與復盤結論回寫到 observability、reliability 與 runbook">8.22 Incident Evidence Write-back</a>（事故結束後對外揭露的 timeline / post-mortem 整理）</li>
<li>跨類：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（一次看完 IR / status / on-call vendor map）</li>
</ul>
]]></content:encoded></item><item><title>LitmusChaos</title><link>https://tarrragon.github.io/blog/backend/06-reliability/vendors/litmuschaos/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/06-reliability/vendors/litmuschaos/</guid><description>&lt;p>LitmusChaos 是 CNCF graduated 的 Kubernetes chaos engineering 平台、承擔三個責任：ChaosHub experiment marketplace（現成 experiment 直接用）、ChaosWorkflow 編排多步驟實驗、Probe-based steady state validation。設計取捨偏向「現成 experiment 庫 + workflow-centric + CNCF graduated 治理」、是 Chaos Mesh 的近競品、Harness 提供商業版（ChaosNative）。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>部署 Litmus 到 K8s&lt;/li>
&lt;li>從 ChaosHub 引用現成 experiment&lt;/li>
&lt;li>寫 ChaosWorkflow（多步驟 + probe）&lt;/li>
&lt;li>設計 Probe（HTTP / Cmd / K8s / Prometheus）做 steady state&lt;/li>
&lt;li>評估 Litmus vs Chaos Mesh vs Gremlin 的選用&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑5-分鐘把-litmus-跑起來">最短路徑：5 分鐘把 Litmus 跑起來&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 1. 安裝&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: helm install litmus litmus/litmus -n litmus --create-namespace&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="c1"># 2. 從 ChaosHub 引用 experiment&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: kubectl apply -f https://hub.litmuschaos.io/...&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">&lt;span class="c1"># 3. 跑 experiment + 看 ChaosResult&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: kubectl apply -f chaosengine.yaml&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">9&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: kubectl describe chaosresult &amp;lt;name&amp;gt;&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="日常操作與決策形狀">日常操作與決策形狀&lt;/h2>
&lt;h3 id="crd-設計">CRD 設計&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>ChaosExperiment：experiment 定義&lt;/li>
&lt;li>ChaosEngine：bind experiment 到 target&lt;/li>
&lt;li>ChaosResult：執行結果&lt;/li>
&lt;/ul>
&lt;h3 id="chaoshub-experiment">ChaosHub experiment&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>現成 experiment marketplace&lt;/li>
&lt;li>Generic / Kafka / Cassandra / GCP / AWS / VMware experiments&lt;/li>
&lt;li>自訂 experiment 上傳 Hub&lt;/li>
&lt;/ul>
&lt;h3 id="chaosworkflow">ChaosWorkflow&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>Argo Workflow-based&lt;/li>
&lt;li>多步驟 chaos 編排&lt;/li>
&lt;li>Schedule trigger&lt;/li>
&lt;/ul>
&lt;h2 id="進階主題按需閱讀">進階主題（按需閱讀）&lt;/h2>
&lt;h3 id="probe-based-steady-state">Probe-based steady state&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>HTTP probe / Cmd probe / K8s probe / Prometheus probe&lt;/li>
&lt;li>跟 chaos 同步 / 序列執行&lt;/li>
&lt;li>Success threshold 設計&lt;/li>
&lt;/ul>
&lt;h3 id="chaoscentercontrol-plane">ChaosCenter（control plane）&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>跨 cluster chaos 管理&lt;/li>
&lt;li>ChaosResult dashboard&lt;/li>
&lt;li>RBAC 控制&lt;/li>
&lt;/ul>
&lt;h3 id="harness-chaosnative商業">Harness ChaosNative（商業）&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>商業支援版本&lt;/li>
&lt;li>跟 Harness CD 整合&lt;/li>
&lt;li>Enterprise governance&lt;/li>
&lt;/ul>
&lt;h3 id="跟-chaos-mesh-對照">跟 Chaos Mesh 對照&lt;/h3>
&lt;p>子議題：&lt;/p></description><content:encoded><![CDATA[<p>LitmusChaos 是 CNCF graduated 的 Kubernetes chaos engineering 平台、承擔三個責任：ChaosHub experiment marketplace（現成 experiment 直接用）、ChaosWorkflow 編排多步驟實驗、Probe-based steady state validation。設計取捨偏向「現成 experiment 庫 + workflow-centric + CNCF graduated 治理」、是 Chaos Mesh 的近競品、Harness 提供商業版（ChaosNative）。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>部署 Litmus 到 K8s</li>
<li>從 ChaosHub 引用現成 experiment</li>
<li>寫 ChaosWorkflow（多步驟 + probe）</li>
<li>設計 Probe（HTTP / Cmd / K8s / Prometheus）做 steady state</li>
<li>評估 Litmus vs Chaos Mesh vs Gremlin 的選用</li>
</ol>
<h2 id="最短路徑5-分鐘把-litmus-跑起來">最短路徑：5 分鐘把 Litmus 跑起來</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 1. 安裝</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># TODO: helm install litmus litmus/litmus -n litmus --create-namespace</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 2. 從 ChaosHub 引用 experiment</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="c1"># TODO: kubectl apply -f https://hub.litmuschaos.io/...</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="c1"># 3. 跑 experiment + 看 ChaosResult</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="c1"># TODO: kubectl apply -f chaosengine.yaml</span>
</span></span><span class="line"><span class="ln">9</span><span class="cl"><span class="c1"># TODO: kubectl describe chaosresult &lt;name&gt;</span></span></span></code></pre></div><h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="crd-設計">CRD 設計</h3>
<p>子議題：</p>
<ul>
<li>ChaosExperiment：experiment 定義</li>
<li>ChaosEngine：bind experiment 到 target</li>
<li>ChaosResult：執行結果</li>
</ul>
<h3 id="chaoshub-experiment">ChaosHub experiment</h3>
<p>子議題：</p>
<ul>
<li>現成 experiment marketplace</li>
<li>Generic / Kafka / Cassandra / GCP / AWS / VMware experiments</li>
<li>自訂 experiment 上傳 Hub</li>
</ul>
<h3 id="chaosworkflow">ChaosWorkflow</h3>
<p>子議題：</p>
<ul>
<li>Argo Workflow-based</li>
<li>多步驟 chaos 編排</li>
<li>Schedule trigger</li>
</ul>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<h3 id="probe-based-steady-state">Probe-based steady state</h3>
<p>子議題：</p>
<ul>
<li>HTTP probe / Cmd probe / K8s probe / Prometheus probe</li>
<li>跟 chaos 同步 / 序列執行</li>
<li>Success threshold 設計</li>
</ul>
<h3 id="chaoscentercontrol-plane">ChaosCenter（control plane）</h3>
<p>子議題：</p>
<ul>
<li>跨 cluster chaos 管理</li>
<li>ChaosResult dashboard</li>
<li>RBAC 控制</li>
</ul>
<h3 id="harness-chaosnative商業">Harness ChaosNative（商業）</h3>
<p>子議題：</p>
<ul>
<li>商業支援版本</li>
<li>跟 Harness CD 整合</li>
<li>Enterprise governance</li>
</ul>
<h3 id="跟-chaos-mesh-對照">跟 Chaos Mesh 對照</h3>
<p>子議題：</p>
<ul>
<li>Litmus：workflow-centric、ChaosHub</li>
<li>Chaos Mesh：CRD-driven、Dashboard 友善</li>
<li>選擇判讀：現成 experiment 庫 → Litmus；fault types 多樣 → Chaos Mesh</li>
</ul>
<h3 id="chaos-as-code">Chaos as Code</h3>
<p>子議題：</p>
<ul>
<li>ChaosWorkflow YAML version control</li>
<li>GitOps integration</li>
<li>PR-based chaos review</li>
</ul>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<h3 id="experiment-fail-to-start">Experiment fail to start</h3>
<p>操作原則：ServiceAccount + RBAC 不對、experiment image pull 失敗。判讀：<code>kubectl describe chaosengine</code>。</p>
<h3 id="probe-失敗">Probe 失敗</h3>
<p>操作原則：probe 條件設錯 / target 沒準備好。判讀：ChaosResult 看 probe verdict。</p>
<h3 id="hub-experiment-引用版本不對">Hub experiment 引用版本不對</h3>
<p>操作原則：experiment.yaml 跟 Litmus version 不對齊。判讀：Litmus version + experiment compatibility。</p>
<h3 id="workflow-卡住">Workflow 卡住</h3>
<p>操作原則：Argo Workflow 卡 → 看 Argo pod log。</p>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>多 fault types / Dashboard</td>
          <td><a href="/blog/backend/06-reliability/vendors/chaos-mesh/" data-link-title="Chaos Mesh" data-link-desc="Kubernetes-native chaos engineering（CNCF incubating）">Chaos Mesh</a></td>
      </tr>
      <tr>
          <td>非 K8s / 商業</td>
          <td><a href="/blog/backend/06-reliability/vendors/gremlin/" data-link-title="Gremlin" data-link-desc="商業 chaos engineering 平台、跨平台與 GameDay">Gremlin</a></td>
      </tr>
      <tr>
          <td>Integration test</td>
          <td><a href="/blog/backend/06-reliability/vendors/toxiproxy/" data-link-title="Toxiproxy" data-link-desc="TCP-level fault injection proxy（Shopify 開源）">Toxiproxy</a></td>
      </tr>
      <tr>
          <td>AWS-native</td>
          <td>AWS Fault Injection Service</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>ChaosHub 各 experiment 詳細 parameter</li>
<li>Argo Workflow 內部</li>
<li>Litmus 商業版本 detail</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<table>
  <thead>
      <tr>
          <th>案例方向</th>
          <th>對應主題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/06-reliability/cases/netflix/steady-state-chaos-and-fit/" data-link-title="Netflix：Steady State、Chaos 與 FIT 的驗證路徑" data-link-desc="把故障注入從工具操作升級成可驗證流程：先定義穩態，再設計注入與回復條件。">Netflix：Steady State、Chaos 與 FIT</a></td>
          <td>hypothesis-driven experiment 對應 ChaosHub workflow</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/06-reliability/cases/spotify/platform-engineering-and-reliability-contracts/" data-link-title="Spotify：平台工程與可靠性契約" data-link-desc="用平台契約統一服務團隊的可靠性最低標準，降低跨團隊變更造成的隱性風險。">Spotify：平台工程與可靠性契約</a></td>
          <td>squad-based 採用 chaos 的平台化路徑</td>
      </tr>
  </tbody>
</table>
<p><strong>Case 庫稀薄</strong>：本 cases/ 目錄目前沒有以 LitmusChaos 為主軸的案例。</p>
<ul>
<li><strong>待補 LitmusChaos customer case</strong>：CNCF graduated 後客戶採用案例、Harness ChaosNative 客戶</li>
<li><strong>候選 case</strong>：Meta（K8s-native region failover chaos）、Microsoft（Chaos Studio 對照組）— 若未來收錄需先在 cases/ 補正文</li>
</ul>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游概念：<a href="/blog/backend/06-reliability/experiment-safety-boundary/" data-link-title="6.20 Experiment Safety Boundary" data-link-desc="定義 chaos、load test、DR drill 的 [blast radius](/backend/knowledge-cards/blast-radius/)、停止條件與權限約束">6.20 Experiment Safety Boundary</a></li>
<li>平行 vendor：<a href="/blog/backend/06-reliability/vendors/chaos-mesh/" data-link-title="Chaos Mesh" data-link-desc="Kubernetes-native chaos engineering（CNCF incubating）">Chaos Mesh</a>、<a href="/blog/backend/06-reliability/vendors/gremlin/" data-link-title="Gremlin" data-link-desc="商業 chaos engineering 平台、跨平台與 GameDay">Gremlin</a></li>
<li>下游能力：<a href="/blog/backend/08-incident-response/" data-link-title="模組八：事故處理與復盤" data-link-desc="用 IR 領域詞彙建問題節點、以服務級案例庫累積事故脈絡，先建概念與案例庫再進實作交接">8 incident response</a></li>
</ul>
]]></content:encoded></item><item><title>Traefik</title><link>https://tarrragon.github.io/blog/backend/05-deployment-platform/vendors/traefik/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/05-deployment-platform/vendors/traefik/</guid><description>&lt;p>Traefik 是 cloud-native reverse proxy / ingress、承擔三個責任：auto-discovery（從 Docker / K8s / Consul / file 自動發現 backend）、dynamic config（不 reload、即時更新）、ACME 自動 TLS（Let&amp;rsquo;s Encrypt 整合）。設計取捨偏向「cloud-native 簡潔 + auto-discovery 為核心 + middleware chain extensibility」、適合 Docker / K8s 中小規模、大規模 / 複雜 traffic management 跟 nginx / envoy 比相對弱。&lt;/p>
&lt;p>對「Docker / K8s ingress、需要 auto-discovery、ACME 自動 TLS、配置簡潔」這條路徑、Traefik 是 cloud-native first 選擇。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>部署 Traefik 到 Docker / K8s&lt;/li>
&lt;li>配置 dynamic provider（labels / annotations / CRD / file）&lt;/li>
&lt;li>配置 ACME 自動 TLS&lt;/li>
&lt;li>設計 middleware chain（auth / rate limit / circuit breaker）&lt;/li>
&lt;li>評估 Traefik vs nginx vs Envoy 的選用&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑5-分鐘把-traefik-跑起來">最短路徑：5 分鐘把 Traefik 跑起來&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 1. Docker 跑 Traefik + dashboard&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">docker run -d -p 80:80 -p 8080:8080 &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> -v /var/run/docker.sock:/var/run/docker.sock &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> traefik:v3 --api.insecure&lt;span class="o">=&lt;/span>&lt;span class="nb">true&lt;/span> --providers.docker
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="c1"># 2. 用 docker label 配置 routing&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">docker run -d --label &lt;span class="s2">&amp;#34;traefik.http.routers.demo.rule=Host(\`demo.local\`)&amp;#34;&lt;/span> nginx
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="c1"># 3. 訪 dashboard 驗證&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">curl -s http://localhost:8080/api/http/routers &lt;span class="p">|&lt;/span> jq &lt;span class="s1">&amp;#39;.[].rule&amp;#39;&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="日常操作與決策形狀">日常操作與決策形狀&lt;/h2>
&lt;h3 id="provider-auto-discovery">Provider auto-discovery&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>Docker provider：從 container labels 讀 config&lt;/li>
&lt;li>Kubernetes Ingress provider：從 Ingress resource&lt;/li>
&lt;li>Kubernetes CRD provider：Traefik IngressRoute CRD&lt;/li>
&lt;li>Consul / Etcd provider：從 KV store&lt;/li>
&lt;li>File provider：YAML / TOML 靜態 file&lt;/li>
&lt;/ul>
&lt;h3 id="ingressroutek8s-crd">IngressRoute（K8s CRD）&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>Traefik CRD：IngressRoute / Middleware / TLSOption / ServersTransport&lt;/li>
&lt;li>比 Ingress 表達力強（middleware chain / TLS option / multi-protocol）&lt;/li>
&lt;li>跟 Gateway API 對比&lt;/li>
&lt;/ul>
&lt;h3 id="middleware-chain">Middleware chain&lt;/h3>
&lt;p>子議題：&lt;/p></description><content:encoded><![CDATA[<p>Traefik 是 cloud-native reverse proxy / ingress、承擔三個責任：auto-discovery（從 Docker / K8s / Consul / file 自動發現 backend）、dynamic config（不 reload、即時更新）、ACME 自動 TLS（Let&rsquo;s Encrypt 整合）。設計取捨偏向「cloud-native 簡潔 + auto-discovery 為核心 + middleware chain extensibility」、適合 Docker / K8s 中小規模、大規模 / 複雜 traffic management 跟 nginx / envoy 比相對弱。</p>
<p>對「Docker / K8s ingress、需要 auto-discovery、ACME 自動 TLS、配置簡潔」這條路徑、Traefik 是 cloud-native first 選擇。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>部署 Traefik 到 Docker / K8s</li>
<li>配置 dynamic provider（labels / annotations / CRD / file）</li>
<li>配置 ACME 自動 TLS</li>
<li>設計 middleware chain（auth / rate limit / circuit breaker）</li>
<li>評估 Traefik vs nginx vs Envoy 的選用</li>
</ol>
<h2 id="最短路徑5-分鐘把-traefik-跑起來">最短路徑：5 分鐘把 Traefik 跑起來</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># 1. Docker 跑 Traefik + dashboard</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">docker run -d -p 80:80 -p 8080:8080 <span class="se">\
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="se"></span>  -v /var/run/docker.sock:/var/run/docker.sock <span class="se">\
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="se"></span>  traefik:v3 --api.insecure<span class="o">=</span><span class="nb">true</span> --providers.docker
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="c1"># 2. 用 docker label 配置 routing</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">docker run -d --label <span class="s2">&#34;traefik.http.routers.demo.rule=Host(\`demo.local\`)&#34;</span> nginx
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="c1"># 3. 訪 dashboard 驗證</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">curl -s http://localhost:8080/api/http/routers <span class="p">|</span> jq <span class="s1">&#39;.[].rule&#39;</span></span></span></code></pre></div><h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="provider-auto-discovery">Provider auto-discovery</h3>
<p>子議題：</p>
<ul>
<li>Docker provider：從 container labels 讀 config</li>
<li>Kubernetes Ingress provider：從 Ingress resource</li>
<li>Kubernetes CRD provider：Traefik IngressRoute CRD</li>
<li>Consul / Etcd provider：從 KV store</li>
<li>File provider：YAML / TOML 靜態 file</li>
</ul>
<h3 id="ingressroutek8s-crd">IngressRoute（K8s CRD）</h3>
<p>子議題：</p>
<ul>
<li>Traefik CRD：IngressRoute / Middleware / TLSOption / ServersTransport</li>
<li>比 Ingress 表達力強（middleware chain / TLS option / multi-protocol）</li>
<li>跟 Gateway API 對比</li>
</ul>
<h3 id="middleware-chain">Middleware chain</h3>
<p>子議題：</p>
<ul>
<li>內建 middleware：headers / rate limit / basic auth / forward auth / retry / circuit breaker / compress / IP whitelist</li>
<li>自訂 middleware：plugin（Yaegi-based）</li>
<li>順序：定義 middleware → 在 router 引用</li>
</ul>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<h3 id="acme-自動-tls">ACME 自動 TLS</h3>
<p>子議題：</p>
<ul>
<li>Let&rsquo;s Encrypt 整合（自動憑證 + 續期）</li>
<li>DNS challenge（適合 wildcard）vs HTTP challenge（適合單 domain）</li>
<li>多 resolver 配置（staging / production / 不同 CA）</li>
<li>對應 ACME storage（local / KV / Traefik Hub）</li>
</ul>
<h3 id="provider-weight--priority">Provider weight / priority</h3>
<p>子議題：</p>
<ul>
<li>多 provider 同時跑、config 來源衝突處理</li>
<li>Provider 優先順序</li>
<li>對應 dynamic config debug</li>
</ul>
<h3 id="traefik-hubmanaged">Traefik Hub（managed）</h3>
<p>子議題：</p>
<ul>
<li>Traefik Hub：商業 managed control plane</li>
<li>適合：跨 cluster 統一管理 / API Gateway portal</li>
<li>跟 self-host Traefik 對比</li>
</ul>
<h3 id="跟-nginx--envoy-對比">跟 nginx / Envoy 對比</h3>
<p>子議題：</p>
<ul>
<li>Traefik 強：cloud-native auto-discovery、配置簡潔</li>
<li>nginx 強：穩定 + 配置控制力 + 大量 community recipe</li>
<li>Envoy 強：xDS dynamic config、advanced traffic management</li>
<li>選型判讀：Docker / K8s 小中規模 → Traefik；複雜 traffic → Envoy；標準 HTTP → nginx</li>
</ul>
<h3 id="plugin-機制yaegi">Plugin 機制（Yaegi）</h3>
<p>子議題：</p>
<ul>
<li>Traefik plugins 用 Yaegi（Go interpreter）跑、不需 recompile</li>
<li>Plugin catalog（社群 + 官方）</li>
<li>適合：客戶 auth / metric / transformation 小邏輯</li>
<li>對應 Envoy WASM extension 對比</li>
</ul>
<h3 id="multi-protocol">Multi-protocol</h3>
<p>子議題：</p>
<ul>
<li>HTTP / HTTPS / TCP / UDP</li>
<li>gRPC（HTTP/2）原生支援</li>
<li>WebSocket sticky session</li>
</ul>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<h3 id="service-沒被發現">Service 沒被發現</h3>
<p>操作原則：先看 provider 是否啟用、再看 label / annotation / CRD 配置。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">curl -s http://localhost:8080/api/http/services <span class="p">|</span> jq <span class="s1">&#39;.[].name&#39;</span></span></span></code></pre></div><h3 id="route-衝突">Route 衝突</h3>
<p>操作原則：兩個 router 同 rule，看 priority 排序。判讀：dashboard 看 router list。</p>
<h3 id="acme-rate-limit">ACME rate limit</h3>
<p>操作原則：Let&rsquo;s Encrypt 有 rate limit、staging environment 先測再切 production。</p>
<h3 id="middleware-chain-順序錯">Middleware chain 順序錯</h3>
<p>操作原則：middleware 順序影響行為（auth before rate limit vs after）。判讀：dashboard 看 middleware order。</p>
<h3 id="dashboard-連不上">Dashboard 連不上</h3>
<p>操作原則：dashboard 預設 8080、需要 entrypoint 配置。判讀：traefik.yml + entrypoints 設定。</p>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>配置控制力 / 大量 community 模板</td>
          <td><a href="/blog/backend/05-deployment-platform/vendors/nginx/" data-link-title="nginx" data-link-desc="HTTP server / reverse proxy / LB / ingress">nginx</a></td>
      </tr>
      <tr>
          <td>Advanced traffic / xDS</td>
          <td><a href="/blog/backend/05-deployment-platform/vendors/envoy/" data-link-title="Envoy" data-link-desc="Cloud-native service proxy、xDS dynamic config、Istio / Gateway 底層">Envoy</a></td>
      </tr>
      <tr>
          <td>AWS managed</td>
          <td><a href="/blog/backend/05-deployment-platform/vendors/aws-elb/" data-link-title="AWS ELB（ALB / NLB / CLB）" data-link-desc="AWS managed load balancer、ALB（L7）/ NLB（L4）/ CLB（legacy）">AWS ELB</a></td>
      </tr>
      <tr>
          <td>Service mesh</td>
          <td>Istio / Linkerd / Consul Connect</td>
      </tr>
      <tr>
          <td>Gateway API standard</td>
          <td>Envoy Gateway / Contour</td>
      </tr>
      <tr>
          <td>純 dev / local</td>
          <td>Docker Compose + direct port mapping</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Traefik plugin 開發</li>
<li>Yaegi Go interpreter 細節</li>
<li>Traefik Hub 商業細節</li>
<li>各 cloud provider 整合差異</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<h3 id="跨-vendor-對照">跨 vendor 對照</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>對 Traefik 的對應</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/05-deployment-platform/cases/failure-platform-cutover-without-drain/" data-link-title="5.C9 反例：平台切流未先 Draining" data-link-desc="切流時忽略連線清退造成請求錯誤與重試風暴。">5.C9 cutover without drain</a></td>
          <td>Traefik auto-discovery 在 service 下線時、要靠 health check + grace period 等價 drain</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/05-deployment-platform/cases/contrast-platform-migration-by-scale/" data-link-title="5.C10 對照：規模差異下的平台遷移" data-link-desc="平台遷移策略在小中大型組織下的差異。">5.C10 規模對照</a></td>
          <td>Docker / K8s 中小規模選 Traefik 簡潔、大規模通常升階到 Envoy / ingress-nginx 或 mesh</td>
      </tr>
  </tbody>
</table>
<p><strong>待補 Traefik 案例</strong>：Traefik Labs customer story、IngressRoute CRD 大規模採用、Traefik Hub 早期 adopter。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游概念：<a href="/blog/backend/05-deployment-platform/load-balancer-contract/" data-link-title="5.3 load balancer 合約" data-link-desc="整理 idle timeout、draining 與 health check">5.3 LB Contract</a></li>
<li>平行 vendor：<a href="/blog/backend/05-deployment-platform/vendors/nginx/" data-link-title="nginx" data-link-desc="HTTP server / reverse proxy / LB / ingress">nginx</a>、<a href="/blog/backend/05-deployment-platform/vendors/envoy/" data-link-title="Envoy" data-link-desc="Cloud-native service proxy、xDS dynamic config、Istio / Gateway 底層">Envoy</a></li>
<li>下游能力：<a href="/blog/backend/05-deployment-platform/vendors/kubernetes/" data-link-title="Kubernetes" data-link-desc="Container orchestration 主流、GKE / EKS / AKS / 自管">Kubernetes vendor 頁</a></li>
</ul>
]]></content:encoded></item><item><title>AWS ACM</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-acm/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-acm/</guid><description>&lt;p>AWS Certificate Manager (ACM) 是 AWS-managed 的 &lt;em>certificate provisioning 服務&lt;/em>、解決兩件事：&lt;em>public TLS cert 全自動化&lt;/em>（Amazon Trust Services 簽發、DNS validation 通過後 60 天前自動 renew）跟 &lt;em>AWS-managed service 的 cert 整合&lt;/em>（&lt;a href="https://docs.aws.amazon.com/acm/latest/userguide/acm-services.html">ELB / CloudFront / API Gateway / App Runner&lt;/a> 直接 attach、不需要客戶持有私鑰）。內部 mTLS / 自管 endpoint 的 private cert 走另一個產品 ACM Private CA（PCA）— ACM 是 &lt;em>frontend&lt;/em>、PCA 是 &lt;em>自管 CA hierarchy backend&lt;/em>。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>ACM 的核心定位是 &lt;em>AWS 平台內 cert 的全託管 lifecycle&lt;/em>。客戶不持私鑰、不跑 ACME client、不手動 renew — 但代價是 ACM public cert &lt;em>只能 attach 到 AWS-managed service&lt;/em>（ELB / CloudFront / API Gateway / App Runner / Nitro Enclaves）、不能 export 給自管 Nginx / EC2 應用。Private cert 必須有 ACM Private CA (PCA) 後端、ACM 自己不是 CA。&lt;/p>
&lt;p>跟其他 cert 工具的場景重疊度低、定位是分工互補：&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/cert-manager/" data-link-title="cert-manager" data-link-desc="K8s 原生 certificate lifecycle automation、支援 Let&amp;#39;s Encrypt / Vault PKI / Venafi 等多 issuer、auto-renewal &amp;#43; Challenge solver">cert-manager&lt;/a> 走 cluster 內 K8s workload cert（Ingress / service mesh）、&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/letsencrypt/" data-link-title="Let&amp;#39;s Encrypt" data-link-desc="免費 &amp;#43; 自動化的公共 ACME CA、90 天 TTL 強制自動化、跨雲跨平台 public TLS cert 的事實基礎">Let&amp;rsquo;s Encrypt&lt;/a> 走跨平台公共 ACME cert（可 export 任何地方使用）、ACM Private CA 走自管 CA hierarchy（root + intermediate、客戶控制 policy）。常見組合：AWS-native endpoint 用 ACM、K8s workload + 自管伺服器走 cert-manager + Let&amp;rsquo;s Encrypt、內部 mTLS root 走 PCA。詳細差異見「核心取捨表」。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本頁、讀者能判斷：&lt;/p>
&lt;ol>
&lt;li>ACM public cert vs private cert vs imported cert 各自的使用邊界（能 attach 哪些 service、能不能 export）&lt;/li>
&lt;li>DNS validation vs Email validation 的差異、跟 auto-renewal 條件的關聯&lt;/li>
&lt;li>跨 region 跟 CloudFront 的 us-east-1 限制如何處理&lt;/li>
&lt;li>何時 ACM 不夠用、要改走 cert-manager / Let&amp;rsquo;s Encrypt / ACM Private CA&lt;/li>
&lt;/ol>
&lt;h2 id="最短判讀路徑">最短判讀路徑&lt;/h2>
&lt;p>判斷 ACM cert 部署是否健康、最少看四件事：&lt;/p></description><content:encoded><![CDATA[<p>AWS Certificate Manager (ACM) 是 AWS-managed 的 <em>certificate provisioning 服務</em>、解決兩件事：<em>public TLS cert 全自動化</em>（Amazon Trust Services 簽發、DNS validation 通過後 60 天前自動 renew）跟 <em>AWS-managed service 的 cert 整合</em>（<a href="https://docs.aws.amazon.com/acm/latest/userguide/acm-services.html">ELB / CloudFront / API Gateway / App Runner</a> 直接 attach、不需要客戶持有私鑰）。內部 mTLS / 自管 endpoint 的 private cert 走另一個產品 ACM Private CA（PCA）— ACM 是 <em>frontend</em>、PCA 是 <em>自管 CA hierarchy backend</em>。</p>
<h2 id="服務定位">服務定位</h2>
<p>ACM 的核心定位是 <em>AWS 平台內 cert 的全託管 lifecycle</em>。客戶不持私鑰、不跑 ACME client、不手動 renew — 但代價是 ACM public cert <em>只能 attach 到 AWS-managed service</em>（ELB / CloudFront / API Gateway / App Runner / Nitro Enclaves）、不能 export 給自管 Nginx / EC2 應用。Private cert 必須有 ACM Private CA (PCA) 後端、ACM 自己不是 CA。</p>
<p>跟其他 cert 工具的場景重疊度低、定位是分工互補：<a href="/blog/backend/07-security-data-protection/vendors/cert-manager/" data-link-title="cert-manager" data-link-desc="K8s 原生 certificate lifecycle automation、支援 Let&#39;s Encrypt / Vault PKI / Venafi 等多 issuer、auto-renewal &#43; Challenge solver">cert-manager</a> 走 cluster 內 K8s workload cert（Ingress / service mesh）、<a href="/blog/backend/07-security-data-protection/vendors/letsencrypt/" data-link-title="Let&#39;s Encrypt" data-link-desc="免費 &#43; 自動化的公共 ACME CA、90 天 TTL 強制自動化、跨雲跨平台 public TLS cert 的事實基礎">Let&rsquo;s Encrypt</a> 走跨平台公共 ACME cert（可 export 任何地方使用）、ACM Private CA 走自管 CA hierarchy（root + intermediate、客戶控制 policy）。常見組合：AWS-native endpoint 用 ACM、K8s workload + 自管伺服器走 cert-manager + Let&rsquo;s Encrypt、內部 mTLS root 走 PCA。詳細差異見「核心取捨表」。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>ACM public cert vs private cert vs imported cert 各自的使用邊界（能 attach 哪些 service、能不能 export）</li>
<li>DNS validation vs Email validation 的差異、跟 auto-renewal 條件的關聯</li>
<li>跨 region 跟 CloudFront 的 us-east-1 限制如何處理</li>
<li>何時 ACM 不夠用、要改走 cert-manager / Let&rsquo;s Encrypt / ACM Private CA</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 ACM cert 部署是否健康、最少看四件事：</p>
<ul>
<li><strong>Cert 跟 service 整合</strong>：cert ARN 是否真的 attach 到 ELB / CloudFront / API Gateway listener、<code>DescribeCertificate</code> 的 <code>InUseBy</code> 有沒有資源、有 cert 但沒 attach 等於 issue 失敗</li>
<li><strong>DNS validation 設定</strong>：cert 是 DNS 還是 Email validation、DNS 的 CNAME record 是否還留在 DNS（auto-renewal 需要這條 record 持續存在）、Route53 vs 外部 DNS 的責任分界</li>
<li><strong>Renewal status</strong>：<code>DescribeCertificate</code> 的 <code>RenewalSummary.RenewalStatus</code> 是 <code>SUCCESS</code> / <code>PENDING_AUTO_RENEWAL</code> / <code>FAILED</code>、失敗時 <code>RenewalStatusReason</code> 是什麼（多半是 DNS record 被刪、CNAME 不再回應）</li>
<li><strong>CloudTrail 證據</strong>：<code>RequestCertificate</code> / <code>ImportCertificate</code> / <code>DeleteCertificate</code> 的 caller identity、是否有非預期的 cert 建立或刪除（防誤刪 / 惡意刪）</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/07-security-data-protection/transport-trust-and-certificate-lifecycle/" data-link-title="7.5 傳輸信任與憑證生命週期" data-link-desc="以問題驅動方式整理傳輸信任鏈、會話完整性與憑證節奏">Transport Trust and Certificate Lifecycle</a> 的覆蓋缺口。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>Request public cert</strong>：對 internet-facing endpoint（網站、API）issue public cert、走 <code>RequestCertificate</code> API、選 DNS validation。ACM 給一組 CNAME record、放進 DNS（Route53 可一鍵 create）、ACM 自動驗證 + issue。Cert 生效後 attach 到 ELB / CloudFront / API Gateway listener。Issuer 是 Amazon Trust Services、所有主流瀏覽器 / OS trust store 都認。</p>
<p><strong>Request private cert（需 PCA 後端）</strong>：內部 service mTLS root、走 <code>RequestCertificate</code> 但指定 PCA ARN。ACM 透過 PCA 簽 cert、cert chain 是組織內部 CA hierarchy。Trust store 必須在各 workload 手動建立（不像 public cert 自動 trust）。</p>
<p><strong>DNS validation vs Email validation</strong>：DNS validation 是預設 + 推薦 — CNAME record 放進 DNS 後、ACM 持續驗證 domain ownership、auto-renewal 全自動。Email validation 是 legacy、ACM 寄信到 domain 的 WHOIS / 預設 admin email、人工點連結驗證；auto-renewal 不會自動完成、cert 到期前必須手動 re-validate。Production 一律用 DNS validation。</p>
<p><strong>Auto-renewal 條件</strong>：ACM 在 cert lifetime 60 天前嘗試 renew、條件嚴格：(1) cert 是 ACM-issued（不是 imported）(2) DNS validation 走 CNAME record 仍存在且可回應 (3) cert 至少 attach 到一個 AWS service。三個條件任一不滿足、renewal 不自動觸發、cert 會 expire。Imported cert <em>完全不自動 renew</em>、必須在 expiry 前手動 re-import。</p>
<p><strong>跟 ELB / CloudFront / API Gateway 整合</strong>：ELB / API Gateway 用所在 region 的 ACM cert、CloudFront 例外 — <em>只認 us-east-1 region 的 ACM cert</em>（CloudFront edge 是 global、cert metadata 統一從 us-east-1 拉）。Multi-region app 要在每個 region 各 request 一份 cert、CloudFront 那份固定放 us-east-1。</p>
<p><strong>Imported certificate</strong>：自管 cert（外部 CA 簽的、舊系統遷移過來的）可以 import 進 ACM、拿到 ARN 後一樣 attach 到 AWS service。代價是 <em>ACM 不會 renew</em>、expiry 前必須手動 re-import 新版。常見事故源：imported cert 過期、AWS service 突然 serve expired cert、Browser 顯示警告。建議 imported cert 都設 CloudWatch alarm 監 <code>DaysToExpiry</code>。</p>
<p><strong>跟 <a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM</a> 整合</strong>：誰能 issue / delete cert 走 IAM policy 控制 — <code>acm:RequestCertificate</code> / <code>acm:DeleteCertificate</code> / <code>acm:ImportCertificate</code>。Tag-based access control 可以限定「只有帶 <code>team=platform</code> tag 的 cert 才能被 platform team IAM role 改」、防誤刪 production cert。Cert 是 region-scoped resource、IAM policy 可指定 <code>Resource</code> ARN 限定 region / cert ID。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>ACM (public)</th>
          <th>ACM Private CA (PCA)</th>
          <th>cert-manager + Let&rsquo;s Encrypt</th>
          <th>手動 OpenSSL CA</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>部署模型</td>
          <td>AWS managed</td>
          <td>AWS managed CA hierarchy</td>
          <td>K8s cluster 內 self-hosted controller</td>
          <td>手動腳本</td>
      </tr>
      <tr>
          <td>私鑰持有</td>
          <td>AWS 持有、客戶不能 export</td>
          <td>AWS 持有 CA key、subordinate 可 export</td>
          <td>cluster 內 Secret、可 export</td>
          <td>自己持有</td>
      </tr>
      <tr>
          <td>Issuer</td>
          <td>Amazon Trust Services（public trust store）</td>
          <td>客戶自管 CA（內部 trust）</td>
          <td>Let&rsquo;s Encrypt / 任何 ACME CA</td>
          <td>自簽</td>
      </tr>
      <tr>
          <td>適用 endpoint</td>
          <td>AWS-managed service（ELB / CloudFront / API GW）</td>
          <td>內部 mTLS、AWS service 也可用</td>
          <td>K8s workload、Ingress、任何持有 PEM 的服務</td>
          <td>實驗 / 內部小規模</td>
      </tr>
      <tr>
          <td>Auto-renewal</td>
          <td>DNS validation 全自動</td>
          <td>透過 ACM 自動</td>
          <td>cert-manager 自動</td>
          <td>自己寫 cron</td>
      </tr>
      <tr>
          <td>跨雲 / 跨平台</td>
          <td>弱 — AWS 內</td>
          <td>弱 — AWS 內</td>
          <td>強 — K8s 在哪都可</td>
          <td>強</td>
      </tr>
      <tr>
          <td>計費</td>
          <td>public cert 免費</td>
          <td>per CA + per cert（PCA 較貴）</td>
          <td>免費（Let&rsquo;s Encrypt）</td>
          <td>免費</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>AWS-heavy + edge endpoint</td>
          <td>內部 mTLS root + AWS 整合</td>
          <td>K8s workload + 跨雲</td>
          <td>實驗、極小規模</td>
      </tr>
      <tr>
          <td>退場成本</td>
          <td>中 — cert 重 issue 但 service 配置要改</td>
          <td>高 — CA hierarchy 遷移痛苦</td>
          <td>低 — PEM 在手、換 issuer 容易</td>
          <td>低</td>
      </tr>
  </tbody>
</table>
<p>選 ACM 的核心訴求：cert 主要 attach 到 AWS-managed service、希望 cert 完全 hands-off、不需要 export 私鑰、能接受 AWS lock-in。需要 export PEM 或跨雲 / 自管 endpoint、改走 cert-manager + Let&rsquo;s Encrypt。需要內部 mTLS root + CA hierarchy 控制、走 ACM Private CA。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>ACM Private CA hierarchy</strong>：PCA 支援 root CA + 多層 intermediate CA、生產建議 root CA 離線（CA 簽完 intermediate 後 disable）、日常簽發走 subordinate CA。Subordinate CA compromise 時 revoke 該層、root 不受影響。Cert policy（path length、key usage、name constraint）在 CA 建立時設定、之後無法改、設計時要算對。</p>
<p><strong>Cross-region cert（CloudFront 的 us-east-1 限制）</strong>：CloudFront 是 global service、但 attach 的 ACM cert <em>必須在 us-east-1</em>。Multi-region 部署：每個 region 各 issue 一份 cert 給該 region 的 ELB / API Gateway、CloudFront 的那份單獨在 us-east-1 issue。Terraform / CloudFormation 要顯式宣告 provider region。</p>
<p><strong>Imported cert 跟 auto-renewal 邊界</strong>：imported cert（外部 CA 簽的）ACM 知道存在、可以 attach、但 <em>不 renew</em>。常見事故：團隊 import cert 後忘了；幾個月後 cert 到期；CloudFront / ELB serve expired cert；客戶看到 browser 警告。對策：所有 imported cert 設 CloudWatch alarm <code>DaysToExpiry &lt; 30</code>、<code>AlmostExpired</code> event 推 EventBridge → PagerDuty。長期策略是把 imported cert 都遷移成 ACM-issued cert（如果 domain ownership 可驗證）。</p>
<p><strong>Tag-based access control</strong>：cert 加 tag（<code>team=platform</code>、<code>env=prod</code>）後、IAM policy 用 <code>Condition</code> 限定：只有同 tag 的 role 才能 update / delete。防誤刪 production cert（dev IAM role 跑 cleanup script 不會誤刪 prod）。配合 <a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM</a> 的 ABAC 模型運作。</p>
<p><strong>Wildcard cert 跟 SAN cert</strong>：ACM 支援 wildcard（<code>*.example.com</code> 涵蓋一層 subdomain）跟 SAN（一張 cert 多個 domain，最多 100 個）。Wildcard 簡化部署但 blast radius 大 — 一張 cert compromise 等於整個 subdomain tree 出事；SAN cert 細粒度但管理成本高。Production 建議按服務邊界拆 — 每個 service 一張 cert、不共用 wildcard，除非確實有大量短 lifecycle subdomain。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Cert PENDING_VALIDATION 一直卡住</strong>：DNS validation CNAME record 沒放對、或 DNS provider 緩存太久 — 用 <code>dig</code> 直接查 CNAME 是否生效、Route53 + ACM 整合通常幾分鐘、外部 DNS 可能 30 分鐘以上</li>
<li><strong>Cert renewal FAILED</strong>：<code>RenewalStatusReason</code> 多半是 <code>DOMAIN_VALIDATION_DENIED</code>（CNAME record 被刪了）或 cert 沒 attach 到任何 service — 補回 CNAME record、或把 cert attach 到至少一個 resource</li>
<li><strong>CloudFront 找不到 cert</strong>：cert 在 us-east-1 以外的 region issue — 在 us-east-1 重 issue、或用 Terraform 顯式跨 provider 設定</li>
<li><strong>Imported cert expired</strong>：忘了 manual renewal、AWS service serve expired cert — CloudWatch alarm + EventBridge 推 alert、長期遷成 ACM-issued</li>
<li><strong>ACM cert 無法用在 EC2 自管 Nginx</strong>：public cert 私鑰不能 export 是設計限制 — 改用 ACM Private CA 或 Let&rsquo;s Encrypt + cert-manager</li>
<li><strong>誤刪 production cert</strong>：沒設 tag-based protection、admin script bug — 開 deletion protection（暫時無內建、用 IAM Condition 限定 delete operation + 24h cooldown via Lambda）+ CloudTrail alert 上 <code>acm:DeleteCertificate</code></li>
<li><strong>Cross-account cert 共用</strong>：ACM cert 不支援 RAM 共用 — 跨 account 要在每個 account 各 issue（或用 PCA + RAM 共用 PCA、各 account 從 PCA issue）</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>K8s workload mTLS / Ingress TLS</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/cert-manager/" data-link-title="cert-manager" data-link-desc="K8s 原生 certificate lifecycle automation、支援 Let&#39;s Encrypt / Vault PKI / Venafi 等多 issuer、auto-renewal &#43; Challenge solver">cert-manager</a> + Let&rsquo;s Encrypt / 內部 issuer</td>
      </tr>
      <tr>
          <td>自管 Nginx / EC2 / 跨雲 endpoint</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/letsencrypt/" data-link-title="Let&#39;s Encrypt" data-link-desc="免費 &#43; 自動化的公共 ACME CA、90 天 TTL 強制自動化、跨雲跨平台 public TLS cert 的事實基礎">Let&rsquo;s Encrypt</a> + 自管 ACME client</td>
      </tr>
      <tr>
          <td>內部 mTLS root + CA hierarchy 控制</td>
          <td>ACM Private CA（PCA）或 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a> PKI engine</td>
      </tr>
      <tr>
          <td>Workload identity（SPIFFE）跨平台</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/spire/" data-link-title="SPIRE" data-link-desc="SPIFFE Runtime Environment、attested workload identity、short-lived SVID &#43; Trust Bundle、跨組織 federation">SPIRE</a></td>
      </tr>
      <tr>
          <td>Cert renewal 證據鏈（rotation evidence）</td>
          <td><a href="/blog/backend/07-security-data-protection/credential-rotation-scoped-evidence/" data-link-title="7.27 Credential Rotation with Scoped Evidence 實作示範" data-link-desc="以 webhook/API credential 輪替示範 scope map、證據欄位與回退窗口如何一起設計。">7.5 Credential Rotation Scoped Evidence</a></td>
      </tr>
      <tr>
          <td>Cert + session invalidation 邊界</td>
          <td><a href="/blog/backend/07-security-data-protection/entrypoint-and-server-protection/" data-link-title="7.3 入口治理與伺服器防護" data-link-desc="以問題驅動方式整理對外入口、管理平面與伺服器邊界">7.3 入口治理</a>、cert renew 跟 session token 是兩條獨立 lifecycle</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>ACM Private CA 完整 hierarchy 設計（root CA 離線儲存、HSM-backed CA key、CRL / OCSP responder 部署）</li>
<li>ACM API 完整 CLI reference 跟 Terraform resource 詳盡欄位</li>
<li>TLS protocol 本身（TLS 1.2 vs 1.3、cipher suite、handshake 流程）</li>
<li>Certificate Transparency log 跟 SCT embedding 內部機制</li>
<li>各 browser / OS trust store 的更新週期</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>ACM 在 07 案例庫沒有直接 vendor-level 事件、以下採對照引用：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 ACM 的關係（對照）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/transport-trust-and-certificate-lifecycle/" data-link-title="7.5 傳輸信任與憑證生命週期" data-link-desc="以問題驅動方式整理傳輸信任鏈、會話完整性與憑證節奏">Transport Trust and Certificate Lifecycle (section)</a></td>
          <td>ACM 是 AWS 平台 cert lifecycle 自動化的具體落地 — DNS validation + auto-renewal 是 <em>自動化覆蓋率</em> 的指標、imported cert 是覆蓋缺口、要單獨設 alarm 兜底</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/edge-exposure/citrix-bleed-2023-session-hijack/" data-link-title="7.R7.3.3 Citrix Bleed 2023：會話被劫持與重放風險" data-link-desc="邊界設備會話資料外洩後，如何演變成帳號與服務風險">Citrix Bleed 2023 Session Hijack</a></td>
          <td>對照啟示 — cert 自動 renew 不等於 session 自動 invalidate、舊 session token 在新 cert 下仍可重放、session lifecycle 是另一層責任、不在 ACM 範圍</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/credential-rotation-scoped-evidence/" data-link-title="7.27 Credential Rotation with Scoped Evidence 實作示範" data-link-desc="以 webhook/API credential 輪替示範 scope map、證據欄位與回退窗口如何一起設計。">Credential Rotation Scoped Evidence (section)</a></td>
          <td>ACM renewal 自動、但 <em>Certificate Transparency log 比對</em> + <em>fleet-wide trust bundle update</em> 是另一條 evidence chain、要跟 SBOM / CMDB 對齊</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/transport-trust-and-certificate-lifecycle/" data-link-title="7.5 傳輸信任與憑證生命週期" data-link-desc="以問題驅動方式整理傳輸信任鏈、會話完整性與憑證節奏">7.4 傳輸信任與憑證生命週期</a>、<a href="/blog/backend/07-security-data-protection/entrypoint-and-server-protection/" data-link-title="7.3 入口治理與伺服器防護" data-link-desc="以問題驅動方式整理對外入口、管理平面與伺服器邊界">7.3 入口治理與伺服器防護</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/cert-manager/" data-link-title="cert-manager" data-link-desc="K8s 原生 certificate lifecycle automation、支援 Let&#39;s Encrypt / Vault PKI / Venafi 等多 issuer、auto-renewal &#43; Challenge solver">cert-manager</a>、<a href="/blog/backend/07-security-data-protection/vendors/letsencrypt/" data-link-title="Let&#39;s Encrypt" data-link-desc="免費 &#43; 自動化的公共 ACME CA、90 天 TTL 強制自動化、跨雲跨平台 public TLS cert 的事實基礎">Let&rsquo;s Encrypt</a>、<a href="/blog/backend/07-security-data-protection/vendors/spire/" data-link-title="SPIRE" data-link-desc="SPIFFE Runtime Environment、attested workload identity、short-lived SVID &#43; Trust Bundle、跨組織 federation">SPIRE</a></li>
<li>下游：<a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM</a>（誰能 issue / delete cert）、<a href="/blog/backend/07-security-data-protection/vendors/aws-kms/" data-link-title="AWS KMS" data-link-desc="AWS 原生 key management service、envelope encryption / digital signing / Multi-Region Key、Key Policy &#43; Grant 雙軌授權">AWS KMS</a>（PCA CA key 後端）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（cert expiry / mis-issuance 進 IR 流程）</li>
<li>官方：<a href="https://docs.aws.amazon.com/acm/">AWS Certificate Manager Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>Azure Cosmos DB</title><link>https://tarrragon.github.io/blog/backend/01-database/vendors/cosmosdb/</link><pubDate>Wed, 13 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/01-database/vendors/cosmosdb/</guid><description>&lt;p>Azure Cosmos DB 是 Microsoft 全球分散式 multi-model database、提供 SQL / MongoDB / Cassandra / Gremlin / Table 五種 API、五個 consistency levels、自動 multi-region write。Microsoft 自家 Microsoft 365 用它做 analytics、ASOS 在 Black Friday 撐 1.67 億請求 24 小時、Minecraft Earth 測試 1M RU/s — 是 Azure 上 NoSQL / Document 工作負載的旗艦。&lt;/p>
&lt;h2 id="教學路線multi-model-api-與全球寫入">教學路線：Multi-model API 與全球寫入&lt;/h2>
&lt;p>Cosmos DB 服務頁的教學目標是把 API model、consistency level、RU/s、logical partition 與 multi-region write 放在同一個 Azure 服務決策中。讀者讀完後要能判斷 Cosmos DB 是遷移相容層、全球 NoSQL 平台，還是特定 Azure workload 的容量抽象。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>學習段&lt;/th>
 &lt;th>核心問題&lt;/th>
 &lt;th>對應段落&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>API model&lt;/td>
 &lt;td>SQL API、MongoDB API、Cassandra API 各自服務哪種遷移或資料形狀&lt;/td>
 &lt;td>定位、跟其他 vendor 的取捨&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Consistency level&lt;/td>
 &lt;td>session、bounded staleness、strong consistency 如何改變產品語意&lt;/td>
 &lt;td>容量規劃要點、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/consistency-level/" data-link-title="Consistency Level" data-link-desc="資料系統對讀寫一致性語意的可選擇層級">Consistency Level&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>RU/s capacity&lt;/td>
 &lt;td>request unit 如何把 query、index、payload 轉成成本與節流&lt;/td>
 &lt;td>容量特性、案例對照&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Global write&lt;/td>
 &lt;td>multi-region write 何時值得承擔衝突與一致性成本&lt;/td>
 &lt;td>適用場景、案例對照&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>替代路由&lt;/td>
 &lt;td>何時用 MongoDB、DynamoDB、Spanner、PostgreSQL 或 analytics&lt;/td>
 &lt;td>不適用場景、下一步路由&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="定位multi-model--multi-region-write">定位：multi-model + multi-region write&lt;/h2>
&lt;p>Cosmos DB 跟其他 DB 最大差異是 &lt;em>multi-model&lt;/em>。一個服務同時支援 5 種 API、每個 API 對應不同資料模型。應用層選擇用哪個 API、底層是同一個分散式 KV store。&lt;/p>
&lt;p>&lt;strong>5 個 API&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>SQL API&lt;/strong>：document（JSON）+ SQL-like query、Cosmos DB native&lt;/li>
&lt;li>&lt;strong>MongoDB API&lt;/strong>：wire-protocol 相容 MongoDB&lt;/li>
&lt;li>&lt;strong>Cassandra API&lt;/strong>：wire-protocol 相容 Cassandra&lt;/li>
&lt;li>&lt;strong>Gremlin API&lt;/strong>：graph database&lt;/li>
&lt;li>&lt;strong>Table API&lt;/strong>：簡單 KV（Azure Table Storage 升級版）&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>5 個 consistency levels&lt;/strong>（從強到弱）：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Strong&lt;/strong>：在支援的 account / region 配置內提供最強一致性，通常帶來最高 latency&lt;/li>
&lt;li>&lt;strong>Bounded staleness&lt;/strong>：訂版本 / 時間差異上限&lt;/li>
&lt;li>&lt;strong>Session&lt;/strong>：同 session 內強一致（最常用）&lt;/li>
&lt;li>&lt;strong>Consistent prefix&lt;/strong>：保證寫入順序&lt;/li>
&lt;li>&lt;strong>Eventual&lt;/strong>：最便宜、最終一致&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>容量特性&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>容量單位：RU/s（Request Unit per second）— 把 read / write / query 統一抽象&lt;/li>
&lt;li>1 RU = strongly consistent read of 1KB document&lt;/li>
&lt;li>配置擴容延遲：99 百分位 5 秒內生效&lt;/li>
&lt;li>每個 logical partition 上限：10,000 RU/s&lt;/li>
&lt;li>測試最高：1,000,000 RU/s（&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/minecraft-earth-cosmos-db-global/" data-link-title="9.C11 Minecraft Earth：Azure Cosmos DB 上的全球分散式 AR 遊戲" data-link-desc="Minecraft Earth 用 Cosmos DB 跨地區分散、測試到 100 萬 RU/s 仍維持承諾延遲">Minecraft Earth 案例&lt;/a>）&lt;/li>
&lt;/ul>
&lt;h2 id="適用場景">適用場景&lt;/h2>
&lt;p>&lt;strong>1. Azure 生態的 multi-model 需求&lt;/strong>：&lt;/p></description><content:encoded><![CDATA[<p>Azure Cosmos DB 是 Microsoft 全球分散式 multi-model database、提供 SQL / MongoDB / Cassandra / Gremlin / Table 五種 API、五個 consistency levels、自動 multi-region write。Microsoft 自家 Microsoft 365 用它做 analytics、ASOS 在 Black Friday 撐 1.67 億請求 24 小時、Minecraft Earth 測試 1M RU/s — 是 Azure 上 NoSQL / Document 工作負載的旗艦。</p>
<h2 id="教學路線multi-model-api-與全球寫入">教學路線：Multi-model API 與全球寫入</h2>
<p>Cosmos DB 服務頁的教學目標是把 API model、consistency level、RU/s、logical partition 與 multi-region write 放在同一個 Azure 服務決策中。讀者讀完後要能判斷 Cosmos DB 是遷移相容層、全球 NoSQL 平台，還是特定 Azure workload 的容量抽象。</p>
<table>
  <thead>
      <tr>
          <th>學習段</th>
          <th>核心問題</th>
          <th>對應段落</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>API model</td>
          <td>SQL API、MongoDB API、Cassandra API 各自服務哪種遷移或資料形狀</td>
          <td>定位、跟其他 vendor 的取捨</td>
      </tr>
      <tr>
          <td>Consistency level</td>
          <td>session、bounded staleness、strong consistency 如何改變產品語意</td>
          <td>容量規劃要點、<a href="/blog/backend/knowledge-cards/consistency-level/" data-link-title="Consistency Level" data-link-desc="資料系統對讀寫一致性語意的可選擇層級">Consistency Level</a></td>
      </tr>
      <tr>
          <td>RU/s capacity</td>
          <td>request unit 如何把 query、index、payload 轉成成本與節流</td>
          <td>容量特性、案例對照</td>
      </tr>
      <tr>
          <td>Global write</td>
          <td>multi-region write 何時值得承擔衝突與一致性成本</td>
          <td>適用場景、案例對照</td>
      </tr>
      <tr>
          <td>替代路由</td>
          <td>何時用 MongoDB、DynamoDB、Spanner、PostgreSQL 或 analytics</td>
          <td>不適用場景、下一步路由</td>
      </tr>
  </tbody>
</table>
<h2 id="定位multi-model--multi-region-write">定位：multi-model + multi-region write</h2>
<p>Cosmos DB 跟其他 DB 最大差異是 <em>multi-model</em>。一個服務同時支援 5 種 API、每個 API 對應不同資料模型。應用層選擇用哪個 API、底層是同一個分散式 KV store。</p>
<p><strong>5 個 API</strong>：</p>
<ul>
<li><strong>SQL API</strong>：document（JSON）+ SQL-like query、Cosmos DB native</li>
<li><strong>MongoDB API</strong>：wire-protocol 相容 MongoDB</li>
<li><strong>Cassandra API</strong>：wire-protocol 相容 Cassandra</li>
<li><strong>Gremlin API</strong>：graph database</li>
<li><strong>Table API</strong>：簡單 KV（Azure Table Storage 升級版）</li>
</ul>
<p><strong>5 個 consistency levels</strong>（從強到弱）：</p>
<ol>
<li><strong>Strong</strong>：在支援的 account / region 配置內提供最強一致性，通常帶來最高 latency</li>
<li><strong>Bounded staleness</strong>：訂版本 / 時間差異上限</li>
<li><strong>Session</strong>：同 session 內強一致（最常用）</li>
<li><strong>Consistent prefix</strong>：保證寫入順序</li>
<li><strong>Eventual</strong>：最便宜、最終一致</li>
</ol>
<p><strong>容量特性</strong>：</p>
<ul>
<li>容量單位：RU/s（Request Unit per second）— 把 read / write / query 統一抽象</li>
<li>1 RU = strongly consistent read of 1KB document</li>
<li>配置擴容延遲：99 百分位 5 秒內生效</li>
<li>每個 logical partition 上限：10,000 RU/s</li>
<li>測試最高：1,000,000 RU/s（<a href="/blog/backend/09-performance-capacity/cases/minecraft-earth-cosmos-db-global/" data-link-title="9.C11 Minecraft Earth：Azure Cosmos DB 上的全球分散式 AR 遊戲" data-link-desc="Minecraft Earth 用 Cosmos DB 跨地區分散、測試到 100 萬 RU/s 仍維持承諾延遲">Minecraft Earth 案例</a>）</li>
</ul>
<h2 id="適用場景">適用場景</h2>
<p><strong>1. Azure 生態的 multi-model 需求</strong>：</p>
<ul>
<li>同一服務多種 use case（document、graph、KV 共存）</li>
<li>想把多個 NoSQL 資料模型集中在 Azure 服務邊界內治理</li>
<li>對應案例：<a href="/blog/backend/09-performance-capacity/cases/microsoft-365-cosmos-db-analytics/" data-link-title="9.C30 Microsoft 365：從 MongoDB 遷移到 Cosmos DB 的分析平台" data-link-desc="Microsoft 365 把使用分析平台從 MongoDB 遷移到 Cosmos DB、planet-scale 全球分散式分析">9.C30 Microsoft 365</a> — Microsoft 自家用 Cosmos DB 撐分析平台</li>
</ul>
<p><strong>2. 全球零售 + 季節性高峰</strong>：</p>
<ul>
<li>multi-region write 讓全球用戶寫入本地 region</li>
<li>對應案例：<a href="/blog/backend/09-performance-capacity/cases/asos-cosmos-db-black-friday/" data-link-title="9.C21 ASOS：Cosmos DB 在 Black Friday 撐 1.67 億請求" data-link-desc="ASOS 在 2016 Black Friday 用 Azure Cosmos DB 撐 24 小時 1.67 億請求、3500 req/sec、48ms 平均延遲">9.C21 ASOS</a> — Black Friday 24 小時 1.67 億請求、3500 RPS 峰值、48ms 平均延遲</li>
</ul>
<p><strong>3. 全球分散式遊戲後端</strong>：</p>
<ul>
<li>AR / 即時遊戲跨地區同步</li>
<li>session consistency 對遊戲足夠、不需 strong</li>
<li>對應案例：<a href="/blog/backend/09-performance-capacity/cases/minecraft-earth-cosmos-db-global/" data-link-title="9.C11 Minecraft Earth：Azure Cosmos DB 上的全球分散式 AR 遊戲" data-link-desc="Minecraft Earth 用 Cosmos DB 跨地區分散、測試到 100 萬 RU/s 仍維持承諾延遲">9.C11 Minecraft Earth</a> — AR 遊戲玩家位置、跨 region 寫入</li>
</ul>
<p><strong>4. MongoDB 應用想要 <em>managed + 全球分散</em></strong>：</p>
<ul>
<li>Cosmos DB MongoDB API wire protocol compatible</li>
<li>應用層主要驗證相容差異，底層改成分散式架構</li>
<li>對應案例：<a href="/blog/backend/09-performance-capacity/cases/microsoft-365-cosmos-db-analytics/" data-link-title="9.C30 Microsoft 365：從 MongoDB 遷移到 Cosmos DB 的分析平台" data-link-desc="Microsoft 365 把使用分析平台從 MongoDB 遷移到 Cosmos DB、planet-scale 全球分散式分析">9.C30 Microsoft 365</a> — MongoDB → Cosmos DB MongoDB API、planet-scale 分析</li>
</ul>
<p><strong>5. 想用 multi-region active-active write</strong>：</p>
<ul>
<li>不像 Spanner / Aurora DSQL 是 PC 系統、Cosmos DB 是 AP 系統</li>
<li>用 LWW（Last-Writer-Wins）或 stored procedure 處理 conflict</li>
<li>適合可接受 eventual / session consistency 的 multi-region write workload；需要 global SQL linearizability 時轉 Spanner / Aurora DSQL</li>
</ul>
<h2 id="不適用場景">不適用場景</h2>
<p><strong>1. 跨雲需求</strong>：</p>
<ul>
<li>Cosmos DB only on Azure</li>
<li>替代：MongoDB Atlas（cross-cloud）、CockroachDB（自管）</li>
</ul>
<p><strong>2. Linearizable 全球 OLTP</strong>：</p>
<ul>
<li>Cosmos DB Strong consistency 的適用範圍要按 account / region 配置判讀；全球 linearizable SQL 需求通常轉 Spanner / Aurora DSQL</li>
<li>替代：Spanner / Aurora DSQL（真正全球 linearizable）</li>
</ul>
<p><strong>3. 預算極敏感的小 workload</strong>：</p>
<ul>
<li>最低 400 RU/s（約 $25/month）</li>
<li>小流量場景、Azure SQL Database 更便宜</li>
</ul>
<p><strong>4. 純 OLAP 分析</strong>：</p>
<ul>
<li>Cosmos DB 定位在 OLTP / document，analytics workload 交給 Synapse、BigQuery 或 Snowflake</li>
<li>替代：Azure Synapse、BigQuery、Snowflake</li>
</ul>
<p><strong>5. 嚴格 ACID 跨 partition transaction</strong>：</p>
<ul>
<li>Cosmos DB Transaction 限 same logical partition</li>
<li>跨 partition 的 multi-row transaction 要改用 workflow、stored procedure 邊界或 distributed SQL</li>
<li>替代：Spanner / Aurora DSQL</li>
</ul>
<h2 id="跟其他-vendor-的取捨">跟其他 vendor 的取捨</h2>
<p><strong>vs DynamoDB（AWS）</strong>：</p>
<ul>
<li>Cosmos DB：multi-model（5 API）、5 consistency levels、multi-region write</li>
<li>DynamoDB：KV 為主、strong / eventual consistency、Global Tables 以 LWW 處理 multi-region conflict</li>
<li>選 Cosmos DB：Azure 生態、需要 multi-model、需要 consistency 細粒度控制</li>
<li>選 DynamoDB：AWS 生態、純 KV、AWS-native 整合（Lambda、Streams）</li>
</ul>
<p><strong>vs Spanner（GCP）</strong>：</p>
<ul>
<li>Cosmos DB：AP 系統、5 consistency levels、multi-model</li>
<li>Spanner：CP 系統、external consistency、SQL only</li>
<li>選 Cosmos DB：可接受 eventual / session、需要 multi-model</li>
<li>選 Spanner：需要 <a href="/blog/backend/knowledge-cards/linearizability/" data-link-title="Linearizability" data-link-desc="每次操作看起來都在單一全域順序中即時生效的一致性語意">linearizability</a> 與 SQL workload</li>
</ul>
<p><strong>vs MongoDB Atlas</strong>：</p>
<ul>
<li>Cosmos DB MongoDB API：Azure-only、managed、global 強</li>
<li>MongoDB Atlas：跨雲（AWS / GCP / Azure）、原生 MongoDB 行為</li>
<li>選 Cosmos DB：已在 Azure、想要更好 global distribution</li>
<li>選 MongoDB Atlas：跨雲、需要 MongoDB 完整功能（aggregation pipeline 等 native 行為）</li>
</ul>
<p><strong>vs Cassandra / ScyllaDB</strong>：</p>
<ul>
<li>Cosmos DB Cassandra API：managed Azure</li>
<li>Cassandra / ScyllaDB：自管、跨雲</li>
<li>選 Cosmos DB：Azure 生態、想把 operation 交給 managed service</li>
<li>選 Cassandra：跨雲、自管、極限 throughput tuning</li>
</ul>
<p><strong>vs Azure SQL Hyperscale</strong>：</p>
<ul>
<li>Cosmos DB：NoSQL / document、global 分散</li>
<li>Azure SQL Hyperscale：傳統 SQL OLTP、storage / compute 分離、AWS Aurora 對應</li>
<li>選 Cosmos DB：document model、global 分散</li>
<li>選 Azure SQL：SQL workload、應用已用 SQL Server</li>
<li>對應 <a href="/blog/backend/09-performance-capacity/cases/clearent-azure-sql-hyperscale-payments/" data-link-title="9.C32 Clearent：Azure SQL Hyperscale 撐每年 5 億筆支付交易" data-link-desc="Clearent 在 Azure SQL Hyperscale 上處理每年 5 億筆支付交易、autoscale &#43; 微服務架構">9.C32 Clearent Azure SQL Hyperscale</a> — SQL 工作負載選 Hyperscale，document / NoSQL workload 才進 Cosmos DB</li>
</ul>
<p><strong>vs PostgreSQL（SQL baseline）</strong>：</p>
<ul>
<li>PostgreSQL：SQL、強一致、single-primary、跨雲可用</li>
<li>Cosmos DB：NoSQL / multi-model、AP 系統、Azure-only、global 分散</li>
<li>選 PostgreSQL：SQL workload、跨雲、需要進階 SQL 特性</li>
<li>選 Cosmos DB：Azure 生態、document / KV / multi-model、需要 global distribution</li>
</ul>
<p><strong>vs Aurora（AWS managed SQL）</strong>：</p>
<ul>
<li>Aurora：AWS、SQL（PostgreSQL / MySQL）、single-region scaling</li>
<li>Cosmos DB：Azure、NoSQL / multi-model、global write</li>
<li>兩者分別站在 cloud provider 與 data model 兩個維度；同需求下通常先看既有雲平台（AWS → Aurora、Azure → Cosmos / Azure SQL）</li>
</ul>
<p><strong>vs CockroachDB（cross-cloud distributed SQL）</strong>：</p>
<ul>
<li>CockroachDB：跨雲、PostgreSQL wire、distributed SQL、強一致</li>
<li>Cosmos DB：Azure-only、multi-model、5 consistency levels、AP 系統</li>
<li>選 CockroachDB：要 SQL + 跨雲 + 強一致</li>
<li>選 Cosmos DB：要 NoSQL + Azure 生態 + 細粒度 consistency 選擇</li>
</ul>
<h2 id="容量規劃要點">容量規劃要點</h2>
<p><strong>1. RU/s 抽象化把 read / write / query 統一</strong>：</p>
<ul>
<li>不像 DynamoDB 拆 RCU / WCU、Cosmos DB 用單一 RU</li>
<li>簡化容量規劃、但要算「不同操作各吃多少 RU」</li>
<li>1 RU = 1 KB strong read、寫 ~5 RU、複雜 query 數百 RU</li>
</ul>
<p><strong>2. partition key 設計跟 DynamoDB 一樣關鍵</strong>：</p>
<ul>
<li>每個 logical partition 上限 10,000 RU/s</li>
<li>partition key 不均 → hot partition</li>
<li>對應 <a href="/blog/backend/09-performance-capacity/cases/minecraft-earth-cosmos-db-global/" data-link-title="9.C11 Minecraft Earth：Azure Cosmos DB 上的全球分散式 AR 遊戲" data-link-desc="Minecraft Earth 用 Cosmos DB 跨地區分散、測試到 100 萬 RU/s 仍維持承諾延遲">9.C11 Minecraft Earth</a> — synthetic partition key 強制分散</li>
<li>詳見 <a href="/blog/backend/knowledge-cards/hot-partition/" data-link-title="Hot Partition" data-link-desc="說明分散式 KV / OLTP 中、單一 partition 流量遠超其他的容量問題">Hot Partition 卡片</a></li>
</ul>
<p><strong>3. multi-region 配置</strong>：</p>
<ul>
<li>開啟跨 region 後、容量在每個 region 都 mirror、成本乘以 region 數</li>
<li>對應 <a href="/blog/backend/09-performance-capacity/cases/genesys-dynamodb-99999-availability/" data-link-title="9.C24 Genesys：用 DynamoDB 在 15 region 跑出 99.999% 可用性" data-link-desc="Genesys 客服平台用 DynamoDB 為預設資料層、跨 15 主 region &#43; 5 衛星 region、達成 12 個月 99.999% 可用性">9.C24 Genesys</a> — 跟 DynamoDB Global Tables 同類思維、各 region 獨立容量</li>
</ul>
<p><strong>4. Consistency level 影響成本</strong>：</p>
<ul>
<li>Strong consistency：跨 region quorum、單個 read 約 2x RU</li>
<li>Session：cost 跟 eventual 接近、但提供同 session 一致</li>
<li>Eventual：最便宜</li>
</ul>
<p><strong>5. Autoscale provisioned throughput</strong>：</p>
<ul>
<li>訂 max RU/s、實際用多少算多少（10% min）</li>
<li>適合：流量 unpredictable、想降低 on-demand 成本治理負擔</li>
</ul>
<p><strong>6. Serverless mode</strong>：</p>
<ul>
<li>按 request 計費，適合稀疏與小流量 workload</li>
<li>適合：dev / test、小流量、稀疏 workload</li>
</ul>
<h2 id="deep-article已完成">Deep article（已完成）</h2>
<p>本批 5 篇 deep article 已完成、覆蓋 Cosmos DB 從 consistency level 選擇到 multi-region write conflict 的核心 production 議題：</p>
<table>
  <thead>
      <tr>
          <th>主題</th>
          <th>文章</th>
          <th>對應 production 議題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Session 預設、Bounded staleness、Strong 邊界跟跨 collection 分流策略</td>
          <td><a href="consistency-levels-engineering/">consistency-levels-engineering</a></td>
          <td>Session 為何是 production 預設、per-request override、Strong + multi-region 互斥 cross-link</td>
      </tr>
      <tr>
          <td>Synthetic / composite / hierarchical partition key + 不可逆性硬約束</td>
          <td><a href="partition-key-design/">partition-key-design</a></td>
          <td>10000 RU/s 上限、不可改、跟 DynamoDB / MongoDB 可逆性對比</td>
      </tr>
      <tr>
          <td>RU/s 思維、payload、index、provisioned vs autoscale vs serverless</td>
          <td><a href="ru-cost-model-sizing/">ru-cost-model-sizing</a></td>
          <td>ASOS Black Friday + Minecraft Earth 1M RU/s 壓測、autoscale reactive 限制</td>
      </tr>
      <tr>
          <td>MongoDB API vs SQL API：三型遷移、dogfood、multi-model、跨雲 hedging</td>
          <td><a href="mongodb-api-vs-sql-api/">mongodb-api-vs-sql-api</a></td>
          <td>Microsoft 365 dogfood 邊界、document model 遷移三型 SSoT</td>
      </tr>
      <tr>
          <td>Multi-region active-active + LWW / custom merge / Strong 互斥</td>
          <td><a href="multi-region-write-conflict/">multi-region-write-conflict</a></td>
          <td>Strong + multi-region 互斥的 AP 取捨 SSoT、廣告 SLA vs 實測可用性鏈路</td>
      </tr>
  </tbody>
</table>
<p>第二批 deep article 把 Cosmos DB 從核心容量 / 一致性議題推進到 server-side 邏輯、CDC、不同產品釐清與 OLTP / OLAP federation：</p>
<table>
  <thead>
      <tr>
          <th>主題</th>
          <th>文章</th>
          <th>對應 production 議題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Change Feed (CDC)：persistent change log、Azure Functions trigger</td>
          <td><a href="change-feed-cdc/">change-feed-cdc</a></td>
          <td>latest-version vs all-versions-and-deletes、lease container、DynamoDB Streams 對照</td>
      </tr>
      <tr>
          <td>Stored procedure / trigger（JavaScript）：partition-scoped 交易</td>
          <td><a href="stored-procedure-trigger/">stored-procedure-trigger</a></td>
          <td>single-partition atomicity、bounded execution、多數邏輯應在 application 層</td>
      </tr>
      <tr>
          <td>Cosmos DB for PostgreSQL（Citus-based 分散式 PG、不同產品）</td>
          <td><a href="cosmos-for-postgresql/">cosmos-for-postgresql</a></td>
          <td>定位釐清、distribution column、何時選它而非核心 Cosmos / single-node PG</td>
      </tr>
      <tr>
          <td>Cosmos DB ↔ Azure Synapse Link：OLTP / OLAP <a href="/blog/backend/knowledge-cards/federation/" data-link-title="Federation" data-link-desc="跨系統信任與授權交換的聯邦機制">federation</a></td>
          <td><a href="synapse-link-federation/">synapse-link-federation</a></td>
          <td>analytical store、HTAP、RU 隔離、何時 federate 到專用 OLAP</td>
      </tr>
  </tbody>
</table>
<p>Migration playbook：</p>
<table>
  <thead>
      <tr>
          <th>主題</th>
          <th>文章</th>
          <th>對應遷移議題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>從 MongoDB / Cassandra 遷入 Cosmos DB</td>
          <td><a href="migrate-from-mongodb-cassandra/">migrate-from-mongodb-cassandra</a></td>
          <td>protocol-compat API drop-in（Type B）vs native API paradigm shift（Type E）、相容性邊界、dual-write cutover</td>
      </tr>
  </tbody>
</table>
<p>跨 vendor entry：先看 <a href="../db3-vendor-selection/">DB3 vendor selection</a>（MongoDB / DynamoDB / Cosmos DB 三方選型 + workload shape 前置判讀），再進本 vendor 的 deep article。</p>
<h2 id="後續擴充仍待補">後續擴充（仍待補）</h2>
<ul>
<li>Hierarchical partition key 與 partition split / merge 運維</li>
<li>Autoscale vs serverless 的成本切換決策樹</li>
<li>Hands-on lab 入口（對齊 PostgreSQL / MySQL / SQLite hands-on 形態）</li>
<li>Backup / PITR 與 continuous backup tier 選擇</li>
<li>Gremlin / Table API 的適用邊界與遷入</li>
</ul>
<h2 id="anti-recommendation-與升級路由">Anti-recommendation 與升級路由</h2>
<p>Cosmos DB 的 multi-model 能把遷移阻力降到很低，也會讓 API compatibility、RU/s、partition key 與 consistency level 同時變成設計責任。這一段先說何時維持單一 API model，再說何時升級 multi-region write、Synapse Link、MongoDB Atlas、Spanner 或 Azure SQL。</p>
<table>
  <thead>
      <tr>
          <th>機制 / 路線</th>
          <th>維持簡單設計的條件</th>
          <th>升級訊號</th>
          <th>主要引用路徑</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>單一 API model</td>
          <td>document / MongoDB / Cassandra / Table 語意清楚分工</td>
          <td>多 API 共用同一資料語意、相容層行為差異開始影響 production</td>
          <td><a href="/blog/backend/01-database/vendors/mongodb/" data-link-title="MongoDB" data-link-desc="Document database 代表、Atlas managed、跨雲可用、許多大規模平台從 MongoDB 起家">MongoDB vendor</a>、<a href="/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">Database</a></td>
      </tr>
      <tr>
          <td>Session consistency</td>
          <td>user session 內讀寫一致已滿足產品需求</td>
          <td>金融 / 庫存 / 票務需要更強順序承諾</td>
          <td><a href="/blog/backend/knowledge-cards/consistency-level/" data-link-title="Consistency Level" data-link-desc="資料系統對讀寫一致性語意的可選擇層級">Consistency Level</a>、<a href="/blog/backend/knowledge-cards/linearizability/" data-link-title="Linearizability" data-link-desc="每次操作看起來都在單一全域順序中即時生效的一致性語意">Linearizability</a></td>
      </tr>
      <tr>
          <td>Provisioned RU/s</td>
          <td>流量可預測、partition key 均勻</td>
          <td>Black Friday、遊戲上線、全球事件帶來突發尖峰</td>
          <td><a href="/blog/backend/knowledge-cards/hot-partition/" data-link-title="Hot Partition" data-link-desc="說明分散式 KV / OLTP 中、單一 partition 流量遠超其他的容量問題">Hot Partition</a>、<a href="/blog/backend/knowledge-cards/peak-forecast/" data-link-title="Peak Forecast" data-link-desc="說明預期峰值流量的預測方法 — 容量規劃的第一個輸入">Peak Forecast</a></td>
      </tr>
      <tr>
          <td>Multi-region write</td>
          <td>single-region write + global read 已足夠</td>
          <td>regional write latency、region residency、active-active 是產品需求</td>
          <td><a href="/blog/backend/knowledge-cards/rpo/" data-link-title="RPO" data-link-desc="說明恢復點目標如何定義可接受資料損失範圍">RPO</a>、<a href="/blog/backend/knowledge-cards/rto/" data-link-title="RTO" data-link-desc="說明恢復時間目標如何約束事故回復策略">RTO</a>、<a href="/blog/backend/knowledge-cards/stale-read/" data-link-title="Stale Read" data-link-desc="讀取到落後於最新寫入版本的舊資料">Stale Read</a></td>
      </tr>
      <tr>
          <td>MongoDB Atlas</td>
          <td>Azure global distribution 是主訴求</td>
          <td>跨雲、原生 MongoDB 行為、Atlas ecosystem 是主訴求</td>
          <td><a href="/blog/backend/01-database/vendors/mongodb/" data-link-title="MongoDB" data-link-desc="Document database 代表、Atlas managed、跨雲可用、許多大規模平台從 MongoDB 起家">MongoDB vendor</a></td>
      </tr>
      <tr>
          <td>Spanner / CockroachDB</td>
          <td>session / eventual consistency 可接受</td>
          <td>global SQL、strong transaction、cross-partition ACID 是核心需求</td>
          <td><a href="/blog/backend/01-database/vendors/spanner/" data-link-title="Google Cloud Spanner" data-link-desc="全球分散式 strong-consistency OLTP、TrueTime API、線性擴展到 10 億 req/sec">Spanner vendor</a>、<a href="/blog/backend/01-database/vendors/cockroachdb/" data-link-title="CockroachDB" data-link-desc="分散式 SQL、PostgreSQL 相容、跨區強一致、Spanner 的開源 / 跨雲替代">CockroachDB vendor</a></td>
      </tr>
      <tr>
          <td>Azure SQL Hyperscale</td>
          <td>document / NoSQL 是主要資料形狀</td>
          <td>JOIN-heavy、transaction-heavy、SQL Server 生態是主需求</td>
          <td><a href="/blog/backend/01-database/vendors/aurora/" data-link-title="AWS Aurora" data-link-desc="AWS managed PostgreSQL / MySQL、storage / compute 分離、&#43;75% 效能改善的 production 證據">Aurora vendor</a></td>
      </tr>
  </tbody>
</table>
<p>Cosmos DB 的簡單路徑是先固定 API model 與 consistency level。每個 API 的相容範圍、index 行為與 query cost 都不同；單純因為「同一服務支援多模型」而混用 API，後續 migration、debug 與容量估算會變複雜。</p>
<p>RU/s 的升級路徑要把 partition key 與 query shape 放在同一張圖。單純提高 RU/s 只能提高名義容量；logical partition 熱點、跨 partition query、index policy 與 payload size 仍會決定真實成本。</p>
<h2 id="已知-limitation-與後續路由">已知 limitation 與後續路由</h2>
<p>Cosmos DB overview 目前完成 Azure global NoSQL 判斷。下一輪 deep article / playbook 應補 consistency level 選擇、RU/s cost model、partition key design、multi-region conflict、Change Feed、MongoDB API migration、Cassandra API migration 與 Synapse Link。</p>
<h2 id="案例對照">案例對照</h2>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>規模</th>
          <th>教學重點</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/cases/minecraft-earth-cosmos-db-global/" data-link-title="9.C11 Minecraft Earth：Azure Cosmos DB 上的全球分散式 AR 遊戲" data-link-desc="Minecraft Earth 用 Cosmos DB 跨地區分散、測試到 100 萬 RU/s 仍維持承諾延遲">9.C11 Minecraft Earth</a></td>
          <td>1M RU/s 測試、turnkey global distribution</td>
          <td>AR 遊戲全球分散</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/cases/asos-cosmos-db-black-friday/" data-link-title="9.C21 ASOS：Cosmos DB 在 Black Friday 撐 1.67 億請求" data-link-desc="ASOS 在 2016 Black Friday 用 Azure Cosmos DB 撐 24 小時 1.67 億請求、3500 req/sec、48ms 平均延遲">9.C21 ASOS</a></td>
          <td>1.67 億 req / 24h、48ms p99</td>
          <td>全球零售 Black Friday</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/cases/microsoft-365-cosmos-db-analytics/" data-link-title="9.C30 Microsoft 365：從 MongoDB 遷移到 Cosmos DB 的分析平台" data-link-desc="Microsoft 365 把使用分析平台從 MongoDB 遷移到 Cosmos DB、planet-scale 全球分散式分析">9.C30 Microsoft 365</a></td>
          <td>planet-scale analytics</td>
          <td>MongoDB → Cosmos DB API-compatible 遷移、Microsoft 自家 dogfood</td>
      </tr>
  </tbody>
</table>
<p>Cosmos DB case 的讀法是分開看三種壓力：Minecraft Earth 提供 global partition 與 RU/s 訊號，ASOS 提供季節性零售尖峰訊號，Microsoft 365 提供 MongoDB API 相容遷移與 Azure dogfood 訊號。</p>
<h2 id="反向-sibling-路由">反向 sibling 路由</h2>
<p>Cosmos DB 的反向 sibling 路由用來把 Azure global NoSQL、DynamoDB 與 document migration 分開。若讀者從 DynamoDB 過來，先比較 RU/s、partition key、multi-region conflict 與 API model；若讀者從 MongoDB 過來，先把 API compatibility 當 migration hypothesis，再用 aggregation、index、change stream / Change Feed 行為驗證；若需求其實是 SQL strong consistency，轉到 <a href="/blog/backend/01-database/vendors/spanner/" data-link-title="Google Cloud Spanner" data-link-desc="全球分散式 strong-consistency OLTP、TrueTime API、線性擴展到 10 億 req/sec">Spanner vendor</a> 或 <a href="/blog/backend/01-database/vendors/cockroachdb/" data-link-title="CockroachDB" data-link-desc="分散式 SQL、PostgreSQL 相容、跨區強一致、Spanner 的開源 / 跨雲替代">CockroachDB vendor</a>。</p>
<p>這條路由的判準是 API model 是否已固定。Cosmos DB 的 multi-model 是產品入口，不代表同一套資料可以在多個 API 之間自由切換；partition key、index policy、RU/s 與 consistency level 一旦進 production，就會成為 migration 與成本邊界。</p>
<h2 id="常見陷阱">常見陷阱</h2>
<ul>
<li><strong>Strong consistency 用太多</strong>：多數互動式業務用 session consistency 就能滿足讀寫體驗</li>
<li><strong>partition key 只用 user_id</strong>：某些業務 user 集中（VIP、bot）會 hot</li>
<li><strong>忽略 Change Feed</strong>：寫入後通知、投影與同步流程適合先評估 Change Feed</li>
<li><strong>MongoDB API behavior 假設</strong>：API compat 仍要驗證 aggregation pipeline / index 行為</li>
<li><strong>忽略 multi-region 成本乘數</strong>：開 3 region active-active = 3 倍 RU 成本</li>
</ul>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>完整 T1 對照：<a href="/blog/backend/01-database/vendors/" data-link-title="資料庫 Vendor 清單" data-link-desc="規劃 SQL、managed SQL、document、KV 與 distributed SQL 的服務頁撰寫順序與教學大綱">01-database vendors index</a></li>
<li>平行：<a href="/blog/backend/01-database/vendors/dynamodb/" data-link-title="DynamoDB" data-link-desc="AWS managed key-value、partition-based scaling、9000 萬 RPS sustained 實戰證據">DynamoDB vendor</a>、<a href="/blog/backend/01-database/vendors/spanner/" data-link-title="Google Cloud Spanner" data-link-desc="全球分散式 strong-consistency OLTP、TrueTime API、線性擴展到 10 億 req/sec">Spanner vendor</a>、<a href="/blog/backend/01-database/vendors/mongodb/" data-link-title="MongoDB" data-link-desc="Document database 代表、Atlas managed、跨雲可用、許多大規模平台從 MongoDB 起家">MongoDB vendor</a></li>
<li>上游：<a href="/blog/backend/01-database/kv-document-capacity-planning/" data-link-title="1.10 KV / Document DB 容量規劃" data-link-desc="DynamoDB / Cosmos DB / Bigtable / MongoDB 等 KV / Document DB 的容量設計、partition key 取捨、capacity mode 選擇">1.10 KV / Document DB 容量規劃</a> / <a href="/blog/backend/01-database/global-distributed-oltp/" data-link-title="1.11 全球分散式 OLTP" data-link-desc="Spanner / Aurora DSQL / Cosmos DB multi-region write / CockroachDB / TiDB 的全球一致性取捨">1.11 全球分散式 OLTP</a></li>
<li>下游：<a href="/blog/backend/01-database/large-scale-db-migration/" data-link-title="1.12 大規模 DB 遷移實戰" data-link-desc="跨 DB 遷移的 dual-write、[shadow read](/backend/knowledge-cards/shadow-read/)、cutover、rollback 流程 — 從實戰案例提煉的工程做法">1.12 大規模 DB 遷移實戰</a>（MongoDB → Cosmos 範例）</li>
<li>跨模組：<a href="/blog/backend/09-performance-capacity/capacity-planning/" data-link-title="9.6 容量規劃模型" data-link-desc="peak forecast、headroom budget、growth curve、autoscaling sizing">9.6 容量規劃模型</a>、<a href="/blog/backend/09-performance-capacity/saturation-discovery/" data-link-title="9.4 Saturation Discovery" data-link-desc="找出 throughput plateau 與 latency knee 的方法">9.4 Saturation Discovery</a></li>
<li>Last reviewed：2026-05-22（API compatibility / consistency / RU model 屬時間敏感 claim）</li>
<li>官方：<a href="https://azure.microsoft.com/products/cosmos-db/">Azure Cosmos DB</a>、<a href="https://learn.microsoft.com/azure/cosmos-db/consistency-levels">Cosmos DB consistency levels</a></li>
</ul>
]]></content:encoded></item><item><title>Consul</title><link>https://tarrragon.github.io/blog/backend/05-deployment-platform/vendors/consul/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/05-deployment-platform/vendors/consul/</guid><description>&lt;p>Consul 是 HashiCorp 出品的 service networking 平台、承擔三個責任：service registry + discovery + health check（跨 VM / container / bare metal）、KV store + watch（dynamic config）、service mesh（Consul Connect、mTLS sidecar）。設計取捨偏向「跨平台統一 registry + multi-datacenter 一級公民 + DNS interface」、適合非 K8s-only 環境。BSL 授權變動同 Terraform。&lt;/p>
&lt;p>對「非 K8s 環境 service discovery、跨平台統一 registry、KV store + watch、跨 datacenter mesh」這條路徑、Consul 是首選。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>部署 Consul cluster（Server + Agent）&lt;/li>
&lt;li>註冊 service + 配置 health check&lt;/li>
&lt;li>用 KV store + watch 做 dynamic config&lt;/li>
&lt;li>部署 Consul Connect（mTLS service mesh）&lt;/li>
&lt;li>評估 BSL 授權影響跟 alternative（etcd / ZooKeeper）&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑5-分鐘把-consul-跑起來">最短路徑：5 分鐘把 Consul 跑起來&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 1. 啟動 dev mode&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">consul agent -dev -client&lt;span class="o">=&lt;/span>0.0.0.0
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="c1"># 2. 註冊 service（用 JSON 定義）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">cat &amp;gt; web.json &lt;span class="s">&amp;lt;&amp;lt;&amp;#39;SVC&amp;#39;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="s">{&amp;#34;service&amp;#34;: {&amp;#34;name&amp;#34;: &amp;#34;web&amp;#34;, &amp;#34;port&amp;#34;: 8080,
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="s"> &amp;#34;check&amp;#34;: {&amp;#34;http&amp;#34;: &amp;#34;http://localhost:8080/health&amp;#34;, &amp;#34;interval&amp;#34;: &amp;#34;10s&amp;#34;}}}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="s">SVC&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">consul services register web.json
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">&lt;span class="c1"># 3. 查詢（DNS + HTTP API）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">dig @127.0.0.1 -p &lt;span class="m">8600&lt;/span> web.service.consul SRV
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">curl -s http://localhost:8500/v1/catalog/service/web &lt;span class="p">|&lt;/span> jq .&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="日常操作與決策形狀">日常操作與決策形狀&lt;/h2>
&lt;h3 id="agent--server-拓樸">Agent / Server 拓樸&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>Server：Raft consensus、quorum（3 / 5 node）&lt;/li>
&lt;li>Agent：每 host 一個、forward 到 server&lt;/li>
&lt;li>Client mode（不參 Raft、純 forward）&lt;/li>
&lt;li>對應 K8s 內 sidecar mode&lt;/li>
&lt;/ul>
&lt;h3 id="service-registration">Service registration&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>API / CLI / config file 註冊&lt;/li>
&lt;li>Health check：HTTP / TCP / Script / TTL&lt;/li>
&lt;li>Tags / metadata&lt;/li>
&lt;li>對應指令：&lt;code>consul services register&lt;/code>、&lt;code>consul catalog services&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="kv-store--watch">KV store + watch&lt;/h3>
&lt;p>子議題：&lt;/p></description><content:encoded><![CDATA[<p>Consul 是 HashiCorp 出品的 service networking 平台、承擔三個責任：service registry + discovery + health check（跨 VM / container / bare metal）、KV store + watch（dynamic config）、service mesh（Consul Connect、mTLS sidecar）。設計取捨偏向「跨平台統一 registry + multi-datacenter 一級公民 + DNS interface」、適合非 K8s-only 環境。BSL 授權變動同 Terraform。</p>
<p>對「非 K8s 環境 service discovery、跨平台統一 registry、KV store + watch、跨 datacenter mesh」這條路徑、Consul 是首選。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>部署 Consul cluster（Server + Agent）</li>
<li>註冊 service + 配置 health check</li>
<li>用 KV store + watch 做 dynamic config</li>
<li>部署 Consul Connect（mTLS service mesh）</li>
<li>評估 BSL 授權影響跟 alternative（etcd / ZooKeeper）</li>
</ol>
<h2 id="最短路徑5-分鐘把-consul-跑起來">最短路徑：5 分鐘把 Consul 跑起來</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># 1. 啟動 dev mode</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">consul agent -dev -client<span class="o">=</span>0.0.0.0
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c1"># 2. 註冊 service（用 JSON 定義）</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">cat &gt; web.json <span class="s">&lt;&lt;&#39;SVC&#39;
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="s">{&#34;service&#34;: {&#34;name&#34;: &#34;web&#34;, &#34;port&#34;: 8080,
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="s">  &#34;check&#34;: {&#34;http&#34;: &#34;http://localhost:8080/health&#34;, &#34;interval&#34;: &#34;10s&#34;}}}
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="s">SVC</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">consul services register web.json
</span></span><span class="line"><span class="ln">10</span><span class="cl">
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="c1"># 3. 查詢（DNS + HTTP API）</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">dig @127.0.0.1 -p <span class="m">8600</span> web.service.consul SRV
</span></span><span class="line"><span class="ln">13</span><span class="cl">curl -s http://localhost:8500/v1/catalog/service/web <span class="p">|</span> jq .</span></span></code></pre></div><h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="agent--server-拓樸">Agent / Server 拓樸</h3>
<p>子議題：</p>
<ul>
<li>Server：Raft consensus、quorum（3 / 5 node）</li>
<li>Agent：每 host 一個、forward 到 server</li>
<li>Client mode（不參 Raft、純 forward）</li>
<li>對應 K8s 內 sidecar mode</li>
</ul>
<h3 id="service-registration">Service registration</h3>
<p>子議題：</p>
<ul>
<li>API / CLI / config file 註冊</li>
<li>Health check：HTTP / TCP / Script / TTL</li>
<li>Tags / metadata</li>
<li>對應指令：<code>consul services register</code>、<code>consul catalog services</code></li>
</ul>
<h3 id="kv-store--watch">KV store + watch</h3>
<p>子議題：</p>
<ul>
<li>HTTP API：PUT / GET / DELETE</li>
<li>Watch：long polling / blocking query</li>
<li>適合：dynamic config / feature flag / leader election</li>
<li>對應 consul-template 用 KV 模板生 config</li>
</ul>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<h3 id="consul-connectmtls-service-mesh">Consul Connect（mTLS service mesh）</h3>
<p>子議題：</p>
<ul>
<li>Sidecar proxy（Envoy-based）</li>
<li>Service intentions（誰可訪誰）</li>
<li>mTLS 自動憑證</li>
<li>跟 Istio / Linkerd 對比</li>
</ul>
<h3 id="dns-interface">DNS interface</h3>
<p>子議題：</p>
<ul>
<li>Consul DNS port 8600（dig 可訪）</li>
<li>跟 system resolver 整合（unbound / dnsmasq forward to Consul）</li>
<li>SRV record / A record</li>
<li>對應 service discovery 替代 client-side library</li>
</ul>
<h3 id="multi-datacenter">Multi-datacenter</h3>
<p>子議題：</p>
<ul>
<li>Consul 一級公民跨 DC 設計</li>
<li>WAN federation</li>
<li>Network areas</li>
<li>跟 etcd（單 DC focused）對比</li>
</ul>
<h3 id="acl-system">ACL system</h3>
<p>子議題：</p>
<ul>
<li>Token-based ACL</li>
<li>Policy / Role</li>
<li>Bootstrap token / agent token / management token</li>
<li>對應 <a href="/blog/backend/07-security-data-protection/" data-link-title="模組七：資安與資料保護" data-link-desc="以問題驅動方式擴充資安知識網：先定義服務環節問題，再以案例作為觸發式參考">07 security</a> IAM</li>
</ul>
<h3 id="bsl-授權影響">BSL 授權影響</h3>
<p>子議題：</p>
<ul>
<li>2023 改 BSL（同 Terraform）</li>
<li>不能 host Consul-as-a-Service 對外</li>
<li>對 internal 用沒影響</li>
<li>Fork：HashFork / no major fork yet（vs OpenTofu 對 Terraform）</li>
</ul>
<h3 id="跟-etcd--zookeeper-對比">跟 etcd / ZooKeeper 對比</h3>
<p>子議題：</p>
<ul>
<li>etcd：K8s control plane 後端、API minimal</li>
<li>ZooKeeper：老牌、Java-heavy、Kafka 跟 HBase 用</li>
<li>Consul：service discovery first、DNS / health check 內建</li>
<li>選擇判讀：K8s 內 → etcd（就在那）；non-K8s 多 DC → Consul</li>
</ul>
<h3 id="consul--nomad--vault-integration">Consul + Nomad / Vault integration</h3>
<p>子議題：</p>
<ul>
<li>跟 HashiCorp Nomad（替代 K8s）整合</li>
<li>跟 Vault（secrets）整合</li>
<li>三件套：Consul + Nomad + Vault</li>
</ul>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<h3 id="service-不出現在-catalog">Service 不出現在 catalog</h3>
<p>操作原則：先確認 registration API 成功、再看 health check state。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">consul catalog services
</span></span><span class="line"><span class="ln">2</span><span class="cl">consul members
</span></span><span class="line"><span class="ln">3</span><span class="cl">consul catalog nodes -service<span class="o">=</span>web</span></span></code></pre></div><h3 id="health-check-flapping">Health check flapping</h3>
<p>操作原則：check interval / timeout 設定 + 應用本身不穩定。判讀：UI 看 check history。</p>
<h3 id="split-brainraft">Split brain（Raft）</h3>
<p>操作原則：Server 數量 &lt; quorum（&lt; 半數）會 split brain。修法：recover snapshot / 加 server。</p>
<h3 id="kv-race-condition">KV race condition</h3>
<p>操作原則：多 client 同時改、要用 CAS（compare-and-swap）。判讀：API ModifyIndex。</p>
<h3 id="consul-connect-sidecar-連不上">Consul Connect sidecar 連不上</h3>
<p>操作原則：proxy config 錯 / intention 沒設 / cert 過期。判讀：Envoy admin endpoint（sidecar 後面）。</p>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>K8s 內 service discovery</td>
          <td>K8s 內建 Service / DNS</td>
      </tr>
      <tr>
          <td>K8s service mesh</td>
          <td>Istio / Linkerd / Cilium</td>
      </tr>
      <tr>
          <td>純 K8s control plane backend</td>
          <td>etcd</td>
      </tr>
      <tr>
          <td>純 Java 生態</td>
          <td>ZooKeeper / Eureka</td>
      </tr>
      <tr>
          <td>BSL 敏感</td>
          <td>etcd（OSI）/ ZooKeeper（OSI）</td>
      </tr>
      <tr>
          <td>Cloud-native（AWS）</td>
          <td>Service Connect for ECS / Cloud Map</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Consul API 完整 reference</li>
<li>Vault / Nomad 細節（各自獨立工具）</li>
<li>Raft protocol 內部</li>
<li>BSL 法律細節</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<h3 id="跨-vendor-對照">跨 vendor 對照</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>對 Consul 的對應</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/05-deployment-platform/cases/tradeshift-self-managed-k8s-to-eks/" data-link-title="5.C1 Tradeshift：self-managed Kubernetes 遷移到 EKS" data-link-desc="零停機平台遷移的分段策略案例。">5.C1 Tradeshift self-managed → EKS</a></td>
          <td>Tradeshift 用 Linkerd 做切流、對照 Consul Connect 做跨叢集 mTLS 的取捨</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/05-deployment-platform/cases/airbnb-istio-upgrade-governance/" data-link-title="5.C7 Airbnb：Istio 升級治理" data-link-desc="service mesh 升級在大規模環境下如何保持高可用。">5.C7 Airbnb Istio</a></td>
          <td>大規模 mesh 升級節奏的對照、Consul Connect 在類似治理上要設計分批與回退窗口</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/05-deployment-platform/cases/contrast-platform-migration-by-scale/" data-link-title="5.C10 對照：規模差異下的平台遷移" data-link-desc="平台遷移策略在小中大型組織下的差異。">5.C10 規模對照</a></td>
          <td>非 K8s 多 DC 場景 Consul 首選、K8s-only 場景則退到 K8s 內建 service discovery</td>
      </tr>
  </tbody>
</table>
<p><strong>待補 Consul 案例</strong>：HashiCorp customer story、Bloomberg / Cloudflare / Stripe 等大規模 Consul 案例、Consul → K8s service mesh 遷移案例。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游概念：<a href="/blog/backend/05-deployment-platform/" data-link-title="模組五：部署平台與網路入口" data-link-desc="整理 Kubernetes、systemd、load balancer、container 與服務生命週期合約">5 deployment platform</a></li>
<li>平行 vendor：<a href="/blog/backend/05-deployment-platform/vendors/kubernetes/" data-link-title="Kubernetes" data-link-desc="Container orchestration 主流、GKE / EKS / AKS / 自管">Kubernetes</a>（K8s 內建 service discovery）</li>
<li>下游能力：<a href="/blog/backend/07-security-data-protection/" data-link-title="模組七：資安與資料保護" data-link-desc="以問題驅動方式擴充資安知識網：先定義服務環節問題，再以案例作為觸發式參考">07 security IAM</a>、<a href="/blog/backend/06-reliability/" data-link-title="模組六：可靠性驗證流程" data-link-desc="用 SRE 領域詞彙建問題節點、以服務級案例庫累積驗證脈絡，先建概念與案例庫再進實作交接">6 reliability</a></li>
</ul>
]]></content:encoded></item><item><title>Gremlin</title><link>https://tarrragon.github.io/blog/backend/06-reliability/vendors/gremlin/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/06-reliability/vendors/gremlin/</guid><description>&lt;p>Gremlin 是商業 chaos engineering SaaS、承擔三個責任：跨平台 chaos（VM / container / K8s / cloud 都有 agent）、GameDay 設計 + 報告功能、enterprise-grade audit + blast radius guardrail。設計取捨偏向「商業支援 + 跨平台 + 企業安全 + Halt button 緊急中止」、適合非純 K8s 環境 + 需要商業 SLA 的團隊。Founder 來自 Netflix Chaos team。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>部署 Gremlin agent 到 VM / container / K8s&lt;/li>
&lt;li>設計 attack（resource / state / network）+ blast radius&lt;/li>
&lt;li>跑 Scenario / GameDay + 報告交付&lt;/li>
&lt;li>用 Halt button 緊急中止&lt;/li>
&lt;li>評估 Gremlin vs Chaos Mesh / LitmusChaos 的選用&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑5-分鐘把-gremlin-跑起來">最短路徑：5 分鐘把 Gremlin 跑起來&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 1. 註冊 + 取得 team API key&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: gremlin install or container agent&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="c1"># 2. 第一個 attack&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: gremlin attack-container --target ... --type cpu&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">&lt;span class="c1"># 3. Dashboard 看 attack timeline&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: app.gremlin.com&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="日常操作與決策形狀">日常操作與決策形狀&lt;/h2>
&lt;h3 id="attack-types">Attack types&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>Resource：CPU / memory / disk / IO&lt;/li>
&lt;li>State：shutdown / process kill / time travel&lt;/li>
&lt;li>Network：blackhole / DNS / latency / packet loss&lt;/li>
&lt;li>Application：custom error inject&lt;/li>
&lt;/ul>
&lt;h3 id="blast-radius--magnitude">Blast radius + magnitude&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>Target selection（host / container / K8s pod）&lt;/li>
&lt;li>Magnitude（影響度、CPU %、latency ms）&lt;/li>
&lt;li>Duration（短到分鐘 / 長到小時）&lt;/li>
&lt;li>Halt button：emergency stop&lt;/li>
&lt;/ul>
&lt;h3 id="scenario--gameday-設計">Scenario / GameDay 設計&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>Multi-step attack scenario&lt;/li>
&lt;li>GameDay 跨 team 演練設計&lt;/li>
&lt;li>Report 自動產生&lt;/li>
&lt;/ul>
&lt;h2 id="進階主題按需閱讀">進階主題（按需閱讀）&lt;/h2>
&lt;h3 id="cross-platform-agent">Cross-platform agent&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>VM agent（Linux / Windows）&lt;/li>
&lt;li>Container agent（Docker / Kubernetes DaemonSet）&lt;/li>
&lt;li>Cloud agent（AWS / GCP / Azure）&lt;/li>
&lt;li>Agent-less mode（限制較多）&lt;/li>
&lt;/ul>
&lt;h3 id="enterprise-audit--rbac">Enterprise audit + RBAC&lt;/h3>
&lt;p>子議題：&lt;/p></description><content:encoded><![CDATA[<p>Gremlin 是商業 chaos engineering SaaS、承擔三個責任：跨平台 chaos（VM / container / K8s / cloud 都有 agent）、GameDay 設計 + 報告功能、enterprise-grade audit + blast radius guardrail。設計取捨偏向「商業支援 + 跨平台 + 企業安全 + Halt button 緊急中止」、適合非純 K8s 環境 + 需要商業 SLA 的團隊。Founder 來自 Netflix Chaos team。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>部署 Gremlin agent 到 VM / container / K8s</li>
<li>設計 attack（resource / state / network）+ blast radius</li>
<li>跑 Scenario / GameDay + 報告交付</li>
<li>用 Halt button 緊急中止</li>
<li>評估 Gremlin vs Chaos Mesh / LitmusChaos 的選用</li>
</ol>
<h2 id="最短路徑5-分鐘把-gremlin-跑起來">最短路徑：5 分鐘把 Gremlin 跑起來</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 1. 註冊 + 取得 team API key</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># TODO: gremlin install or container agent</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 2. 第一個 attack</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="c1"># TODO: gremlin attack-container --target ... --type cpu</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="c1"># 3. Dashboard 看 attack timeline</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="c1"># TODO: app.gremlin.com</span></span></span></code></pre></div><h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="attack-types">Attack types</h3>
<p>子議題：</p>
<ul>
<li>Resource：CPU / memory / disk / IO</li>
<li>State：shutdown / process kill / time travel</li>
<li>Network：blackhole / DNS / latency / packet loss</li>
<li>Application：custom error inject</li>
</ul>
<h3 id="blast-radius--magnitude">Blast radius + magnitude</h3>
<p>子議題：</p>
<ul>
<li>Target selection（host / container / K8s pod）</li>
<li>Magnitude（影響度、CPU %、latency ms）</li>
<li>Duration（短到分鐘 / 長到小時）</li>
<li>Halt button：emergency stop</li>
</ul>
<h3 id="scenario--gameday-設計">Scenario / GameDay 設計</h3>
<p>子議題：</p>
<ul>
<li>Multi-step attack scenario</li>
<li>GameDay 跨 team 演練設計</li>
<li>Report 自動產生</li>
</ul>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<h3 id="cross-platform-agent">Cross-platform agent</h3>
<p>子議題：</p>
<ul>
<li>VM agent（Linux / Windows）</li>
<li>Container agent（Docker / Kubernetes DaemonSet）</li>
<li>Cloud agent（AWS / GCP / Azure）</li>
<li>Agent-less mode（限制較多）</li>
</ul>
<h3 id="enterprise-audit--rbac">Enterprise audit + RBAC</h3>
<p>子議題：</p>
<ul>
<li>Team / Project / Role 設計</li>
<li>Attack approval workflow</li>
<li>Audit log</li>
<li>SSO / SAML</li>
</ul>
<h3 id="跟-oss-chaos-對比">跟 OSS chaos 對比</h3>
<p>子議題：</p>
<ul>
<li>Gremlin：商業 / 跨平台 / GameDay / 報告</li>
<li>OSS（Chaos Mesh / Litmus）：成本低 / K8s-only / 自管</li>
<li>選型判讀：企業合規 + 跨平台 → Gremlin；K8s-only + 預算敏感 → OSS</li>
</ul>
<h3 id="halt-button">Halt button</h3>
<p>子議題：</p>
<ul>
<li>緊急 stop 所有 active attack</li>
<li>對應 <a href="/blog/backend/06-reliability/experiment-safety-boundary/" data-link-title="6.20 Experiment Safety Boundary" data-link-desc="定義 chaos、load test、DR drill 的 [blast radius](/backend/knowledge-cards/blast-radius/)、停止條件與權限約束">6.20 Experiment Safety Boundary</a></li>
<li>跟 incident response 連動</li>
</ul>
<h3 id="application-level-fault">Application-level fault</h3>
<p>子議題：</p>
<ul>
<li>Gremlin ALFI（Application-Level Fault Injection）</li>
<li>SDK integration</li>
<li>Custom exception inject</li>
</ul>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<h3 id="agent-連不上-gremlin">Agent 連不上 Gremlin</h3>
<p>操作原則：API key / network 不通、proxy 配置錯。</p>
<h3 id="attack-沒生效">Attack 沒生效</h3>
<p>操作原則：target selection 沒匹配 / agent 沒安裝。</p>
<h3 id="halt-不及時">Halt 不及時</h3>
<p>操作原則：halt button 全 active attack 立即停、但已造成影響不會回滾。</p>
<h3 id="blast-radius-過大">Blast radius 過大</h3>
<p>操作原則：magnitude / duration 設過大、影響超預期。修法：staging 先測 / 分階段放大。</p>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>K8s OSS</td>
          <td><a href="/blog/backend/06-reliability/vendors/chaos-mesh/" data-link-title="Chaos Mesh" data-link-desc="Kubernetes-native chaos engineering（CNCF incubating）">Chaos Mesh</a> / <a href="/blog/backend/06-reliability/vendors/litmuschaos/" data-link-title="LitmusChaos" data-link-desc="Kubernetes chaos engineering 平台（CNCF graduated）">LitmusChaos</a></td>
      </tr>
      <tr>
          <td>Integration test 模擬</td>
          <td><a href="/blog/backend/06-reliability/vendors/toxiproxy/" data-link-title="Toxiproxy" data-link-desc="TCP-level fault injection proxy（Shopify 開源）">Toxiproxy</a></td>
      </tr>
      <tr>
          <td>AWS-only</td>
          <td>AWS Fault Injection Service</td>
      </tr>
      <tr>
          <td>Azure-only</td>
          <td>Azure Chaos Studio</td>
      </tr>
      <tr>
          <td>預算極敏感</td>
          <td>OSS chaos 工具</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Gremlin pricing</li>
<li>各 attack parameter detail</li>
<li>Agent internal</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<table>
  <thead>
      <tr>
          <th>案例方向</th>
          <th>對應主題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/06-reliability/cases/netflix/steady-state-chaos-and-fit/" data-link-title="Netflix：Steady State、Chaos 與 FIT 的驗證路徑" data-link-desc="把故障注入從工具操作升級成可驗證流程：先定義穩態，再設計注入與回復條件。">Netflix：Steady State、Chaos 與 FIT</a></td>
          <td>chaos 文化的對照組、商業 vs 自建工具的選擇</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/06-reliability/cases/netflix/chaos-monkey-business-hours-guardrails/" data-link-title="Netflix：Business-Hours Chaos 與 Guardrails" data-link-desc="Chaos Monkey 為何刻意在 business hours 執行：把即時應變能力納入驗證，並用 guardrails 限制實驗風險。">Netflix：Business-Hours Guardrails</a></td>
          <td>attack scope / halt 條件對應時段與 blast radius 控制</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/06-reliability/cases/stripe/idempotency-and-zero-downtime-migration/" data-link-title="Stripe：Idempotency 與零停機遷移的交易安全設計" data-link-desc="把 API 重試與資料遷移放在同一套安全模型，維持支付交易的一致結果。">Stripe：Idempotency 與零停機遷移</a></td>
          <td>Game Day 設計 + 商業 chaos SaaS 的演練節奏</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/06-reliability/cases/shopify/bfcm-capacity-and-game-day/" data-link-title="Shopify：BFCM 容量治理與 Game Day 驗證節奏" data-link-desc="把季節性流量峰值轉成年度可靠性流程，透過容量模型、演練與隔離策略提前吸收風險。">Shopify：BFCM 容量治理與 Game Day</a></td>
          <td>峰值前 Game Day 演練的攻擊類型清單</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/06-reliability/cases/spotify/platform-engineering-and-reliability-contracts/" data-link-title="Spotify：平台工程與可靠性契約" data-link-desc="用平台契約統一服務團隊的可靠性最低標準，降低跨團隊變更造成的隱性風險。">Spotify：平台工程與可靠性契約</a></td>
          <td>squad-based 採用 chaos 的商業工具落地</td>
      </tr>
  </tbody>
</table>
<p><strong>待補 Gremlin customer case</strong>：Stripe / Shopify / Slack 直接公開的 Gremlin GameDay engineering blog（目前以 cases/ 內的可靠性脈絡引用為主）。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游概念：<a href="/blog/backend/06-reliability/experiment-safety-boundary/" data-link-title="6.20 Experiment Safety Boundary" data-link-desc="定義 chaos、load test、DR drill 的 [blast radius](/backend/knowledge-cards/blast-radius/)、停止條件與權限約束">6.20 Experiment Safety Boundary</a></li>
<li>平行 vendor：<a href="/blog/backend/06-reliability/vendors/chaos-mesh/" data-link-title="Chaos Mesh" data-link-desc="Kubernetes-native chaos engineering（CNCF incubating）">Chaos Mesh</a>、<a href="/blog/backend/06-reliability/vendors/toxiproxy/" data-link-title="Toxiproxy" data-link-desc="TCP-level fault injection proxy（Shopify 開源）">Toxiproxy</a></li>
<li>下游能力：<a href="/blog/backend/08-incident-response/" data-link-title="模組八：事故處理與復盤" data-link-desc="用 IR 領域詞彙建問題節點、以服務級案例庫累積事故脈絡，先建概念與案例庫再進實作交接">8 incident response</a></li>
</ul>
]]></content:encoded></item><item><title>Jeli</title><link>https://tarrragon.github.io/blog/backend/08-incident-response/vendors/jeli/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/08-incident-response/vendors/jeli/</guid><description>&lt;p>Jeli 是 &lt;em>post-incident learning platform&lt;/em>、2023 &lt;a href="https://www.pagerduty.com/blog/welcome-jeli/">被 PagerDuty 收購整合&lt;/a>、定位跟 &lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/vendors/incident-io/" data-link-title="incident.io" data-link-desc="Slack-native IR 平台、整合 paging / response / retro">incident.io retro&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/vendors/firehydrant/" data-link-title="FireHydrant" data-link-desc="IR &amp;#43; retrospective 平台、Slack / Teams 整合、service catalog &amp;#43; runbook automation 為核心">FireHydrant retrospective&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/vendors/pagerduty/" data-link-title="PagerDuty" data-link-desc="On-call / alerting 主流 SaaS、IR 平台演化">PagerDuty 既有 Postmortem&lt;/a> 的差異在 &lt;em>human-in-the-loop interview workflow + narrative reconstruction + cross-incident pattern detection&lt;/em>、retro template 本身相近。源自 Etsy / Honeycomb 等 SRE-mature org 的 learning-from-incident 流派、創辦人 Nora Jones 推 Production Excellence 文化。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Jeli 的核心定位是 &lt;em>post-incident learning 的方法論工具&lt;/em>、不是 paging / orchestration / on-call。底層三個責任：&lt;em>incident import + 自動 narrative draft&lt;/em>（從 PagerDuty / Slack / Zoom transcript 拉資料、生 timeline + 故事框架）、&lt;em>structured interview workflow&lt;/em>（OPM-style 訪談 facilitator → operator → contributor、question template 走 context / decision / surprise / pattern 四軸）、&lt;em>cross-incident analysis&lt;/em>（多事故 longitudinal scan 找 systemic issue、非單事故 root cause）。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/vendors/incident-io/" data-link-title="incident.io" data-link-desc="Slack-native IR 平台、整合 paging / response / retro">incident.io retrospective&lt;/a> 比、incident.io 走 &lt;em>Slack-native + lightweight template&lt;/em>、Jeli 走 &lt;em>interview-heavy + narrative-first&lt;/em>；incident.io 適合 weekly retro 量大、Jeli 適合 sev1 / sev2 深度復盤。跟 &lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/vendors/firehydrant/" data-link-title="FireHydrant" data-link-desc="IR &amp;#43; retrospective 平台、Slack / Teams 整合、service catalog &amp;#43; runbook automation 為核心">FireHydrant retrospective&lt;/a> 比、FireHydrant 走 &lt;em>timeline + action item 結構化&lt;/em>、Jeli 走 &lt;em>contributing factors + surprising behavior 敘事化&lt;/em>。跟 &lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/vendors/pagerduty/" data-link-title="PagerDuty" data-link-desc="On-call / alerting 主流 SaaS、IR 平台演化">PagerDuty Postmortem&lt;/a>（收購前的舊模組）比、PagerDuty 走 &lt;em>report template 填空&lt;/em>、Jeli 走 &lt;em>interview transcript → analyst-drafted narrative&lt;/em>；收購後 Jeli 是 PD 推薦的 deep-retro layer。&lt;/p></description><content:encoded><![CDATA[<p>Jeli 是 <em>post-incident learning platform</em>、2023 <a href="https://www.pagerduty.com/blog/welcome-jeli/">被 PagerDuty 收購整合</a>、定位跟 <a href="/blog/backend/08-incident-response/vendors/incident-io/" data-link-title="incident.io" data-link-desc="Slack-native IR 平台、整合 paging / response / retro">incident.io retro</a> / <a href="/blog/backend/08-incident-response/vendors/firehydrant/" data-link-title="FireHydrant" data-link-desc="IR &#43; retrospective 平台、Slack / Teams 整合、service catalog &#43; runbook automation 為核心">FireHydrant retrospective</a> / <a href="/blog/backend/08-incident-response/vendors/pagerduty/" data-link-title="PagerDuty" data-link-desc="On-call / alerting 主流 SaaS、IR 平台演化">PagerDuty 既有 Postmortem</a> 的差異在 <em>human-in-the-loop interview workflow + narrative reconstruction + cross-incident pattern detection</em>、retro template 本身相近。源自 Etsy / Honeycomb 等 SRE-mature org 的 learning-from-incident 流派、創辦人 Nora Jones 推 Production Excellence 文化。</p>
<h2 id="服務定位">服務定位</h2>
<p>Jeli 的核心定位是 <em>post-incident learning 的方法論工具</em>、不是 paging / orchestration / on-call。底層三個責任：<em>incident import + 自動 narrative draft</em>（從 PagerDuty / Slack / Zoom transcript 拉資料、生 timeline + 故事框架）、<em>structured interview workflow</em>（OPM-style 訪談 facilitator → operator → contributor、question template 走 context / decision / surprise / pattern 四軸）、<em>cross-incident analysis</em>（多事故 longitudinal scan 找 systemic issue、非單事故 root cause）。</p>
<p>跟 <a href="/blog/backend/08-incident-response/vendors/incident-io/" data-link-title="incident.io" data-link-desc="Slack-native IR 平台、整合 paging / response / retro">incident.io retrospective</a> 比、incident.io 走 <em>Slack-native + lightweight template</em>、Jeli 走 <em>interview-heavy + narrative-first</em>；incident.io 適合 weekly retro 量大、Jeli 適合 sev1 / sev2 深度復盤。跟 <a href="/blog/backend/08-incident-response/vendors/firehydrant/" data-link-title="FireHydrant" data-link-desc="IR &#43; retrospective 平台、Slack / Teams 整合、service catalog &#43; runbook automation 為核心">FireHydrant retrospective</a> 比、FireHydrant 走 <em>timeline + action item 結構化</em>、Jeli 走 <em>contributing factors + surprising behavior 敘事化</em>。跟 <a href="/blog/backend/08-incident-response/vendors/pagerduty/" data-link-title="PagerDuty" data-link-desc="On-call / alerting 主流 SaaS、IR 平台演化">PagerDuty Postmortem</a>（收購前的舊模組）比、PagerDuty 走 <em>report template 填空</em>、Jeli 走 <em>interview transcript → analyst-drafted narrative</em>；收購後 Jeli 是 PD 推薦的 deep-retro layer。</p>
<p>關鍵張力：<em>interview workflow 的人力成本</em> ↔ <em>narrative 品質</em>。Jeli 不能取代 facilitator、它放大有經驗的 incident analyst — 沒人投入 interview / coding / pattern review、narrative 流於 timeline 重寫、cross-incident analysis 空轉。組織要看清自己 <em>願意投入多少 incident analyst 時間換多深的 systemic learning</em>。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>Jeli 在 IR stack 中承擔哪一段（post-incident learning、不是 paging / orchestration）、為何要外接 <a href="/blog/backend/08-incident-response/vendors/pagerduty/" data-link-title="PagerDuty" data-link-desc="On-call / alerting 主流 SaaS、IR 平台演化">PagerDuty</a> on-call + <a href="/blog/backend/08-incident-response/incident-communication/" data-link-title="8.4 事故通訊與狀態更新" data-link-desc="建立內外部通報節奏與狀態更新格式">Slack / Zoom</a> 為 transcript source</li>
<li>Interview workflow 的 ownership 設計（誰當 facilitator、誰 code transcript、誰寫 narrative draft、誰 sign-off）</li>
<li>Cross-incident pattern detection 的最小條件（多少事故樣本、tag 怎麼一致、theme 怎麼歸納）</li>
<li>何時用 Jeli、何時走 incident.io / FireHydrant / PagerDuty Postmortem 的取捨</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Jeli deployment 是否真的在學習、最少看四件事：</p>
<ul>
<li><strong>Incident import workflow</strong>：從 PagerDuty incident / Slack channel / Zoom transcript 自動 import 是否設好、新事故進來幾分鐘內是否有 draft、source coverage 是否包含主 IR 通訊管道</li>
<li><strong>Interview prep</strong>：sev1 / sev2 是否預設排 interview、facilitator 是否非當事人、question template 是否走 context / decision / surprise / pattern 四軸而非自由 freestyle</li>
<li><strong>Narrative draft 品質</strong>：draft 是否寫成 <em>story</em>（contributing factors / latent conditions / surprising behavior）、不是 timeline 重寫；analyst sign-off 前是否走過 transcript citation 驗證</li>
<li><strong>Cross-incident pattern</strong>：多事故 tag taxonomy 是否一致、是否有人定期跑 6-12 個月 pattern scan、output 是否回到 <a href="/blog/backend/08-incident-response/incident-pattern-library/" data-link-title="8.9 事故型態庫入口" data-link-desc="把跨服務的共通事故型態抽成型態卡，作為新事故的判讀錨點">Incident Pattern Library</a> 或 process / tooling 改善</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/08-incident-response/post-incident-review/" data-link-title="8.5 復盤與改進追蹤" data-link-desc="把 RCA 與 action items 轉成可驗證閉環">post-incident review</a> 邊界的待補項目。</p>
<h2 id="最短路徑">最短路徑</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 1. PagerDuty 用戶 enable Jeli module（2024+ 整合）</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># 2. 從 PagerDuty incident / Slack channel / Zoom transcript 自動 import</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="c1"># 3. analyst 驗 timeline citation、補 contributing factors + latent conditions</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 4. Schedule interview（facilitator 非當事人）、走 context / decision / surprise / pattern 四軸</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="c1"># 5. Sign-off narrative、tag 進固定 taxonomy、進 cross-incident 池</span></span></span></code></pre></div><h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>Incident import + 自動 draft</strong>：Jeli 從 PagerDuty incident metadata、Slack incident channel transcript、Zoom recording transcript 三路 import、自動產 timeline + 參與人列表 + 初步 narrative skeleton。意義是 <em>把人力從「翻聊天紀錄拼 timeline」釋放出來、聚焦在 narrative + interview</em>。但 auto-draft 是骨架不是結論、analyst 必須驗每筆 citation 是否準。</p>
<p><strong>Interview workflow（OPM-style）</strong>：Jeli 推的 <em>Operating Procedures Manual</em> style 訪談 — facilitator 不是 incident commander、不是當事人；question template 走 <em>context</em>（這個系統平常怎麼運作）→ <em>decision</em>（事故當下你想到什麼選項、為何選這個）→ <em>surprise</em>（什麼跟你預期不一樣）→ <em>pattern</em>（你是否在別的事故看過類似形狀）。錄音 + transcription + structured coding（標 contributing factor / latent condition / how-near-miss）是這層的工程化。</p>
<p><strong>Narrative reconstruction</strong>：narrative 不是 chronological event list、是 <em>story</em>。三個必寫元素：<em>contributing factors</em>（多重原因疊加、不是 root cause）、<em>latent conditions</em>（事故前已存在但沒人 trip 的條件、像系統 default config / 文檔誤導）、<em>surprising / unexpected behavior</em>（responder 當下覺得「這不對」的點）。對照 <a href="/blog/backend/08-incident-response/post-incident-review/" data-link-title="8.5 復盤與改進追蹤" data-link-desc="把 RCA 與 action items 轉成可驗證閉環">post-incident review</a> 的章節原則。</p>
<p><strong>Cross-incident pattern detection</strong>：跨 6-12 個月事故跑 longitudinal analysis、找 <em>recurring component</em>（同一個服務反覆 trip）、<em>recurring handoff</em>（某 team 之間 incident 傳遞失敗）、<em>recurring process gap</em>（同類 runbook 缺漏）。Output 是 org-level intervention 建議（process / tooling / training）、不是個案 action item。需要 tag taxonomy 跨事故一致、否則 pattern detection 抓不出 signal。</p>
<p><strong>PagerDuty 整合（2023+）</strong>：收購後 Jeli 從 PD incident 自動 import、整合進 PD Process Automation 的 post-incident workflow、roadmap 朝 PD 主產品 deep integration。對已是 PagerDuty 客戶的 org 是 ecosystem 一致性增加；對非 PD 環境（用 <a href="/blog/backend/08-incident-response/vendors/opsgenie/" data-link-title="Opsgenie" data-link-desc="Atlassian on-call、跟 Jira / Statuspage 套件整合、JSM Premium migration 議題">Opsgenie</a> / <a href="/blog/backend/08-incident-response/vendors/grafana-oncall/" data-link-title="Grafana OnCall" data-link-desc="OSS-friendly on-call 平台、Grafana Labs 維護、Apache 2.0、Grafana IRM bundle 把 OnCall &#43; Incident 收進一個 alert-to-resolve 流程">Grafana OnCall</a> / <a href="/blog/backend/08-incident-response/vendors/incident-io/" data-link-title="incident.io" data-link-desc="Slack-native IR 平台、整合 paging / response / retro">incident.io</a>）整合曲線變陡、長期可能要遷 paging stack。</p>
<p><strong>Causal Analysis based on System Theory (CAST)</strong>：Jeli methodology 受 Nancy Leveson 的 CAST / STAMP 影響、把事故看成 <em>control structure failure</em> 而非 <em>component failure</em>。意義是分析重心從「哪台機器壞」轉到「哪個 control loop（人 + tool + process）失效」。實作上反映在 interview question 的 <em>decision</em> 軸（你當下手上有什麼 control）。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Jeli (PagerDuty)</th>
          <th>PagerDuty Postmortem 舊模組</th>
          <th>incident.io retrospective</th>
          <th>FireHydrant retrospective</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>主要產出</td>
          <td>Narrative + contributing factors</td>
          <td>Report template 填空</td>
          <td>Slack-native retro doc</td>
          <td>Timeline + action item 結構</td>
      </tr>
      <tr>
          <td>訪談支援</td>
          <td>Interview workflow + transcript coding</td>
          <td>無</td>
          <td>無（手動）</td>
          <td>無（手動）</td>
      </tr>
      <tr>
          <td>跨事故 pattern</td>
          <td>Longitudinal analysis 內建</td>
          <td>無</td>
          <td>限於 tag filter</td>
          <td>限於 tag filter</td>
      </tr>
      <tr>
          <td>適用 incident sev</td>
          <td>sev1 / sev2 深度復盤</td>
          <td>一般事故報告</td>
          <td>weekly retro 量大</td>
          <td>weekly retro + action tracking</td>
      </tr>
      <tr>
          <td>人力成本</td>
          <td>高（需 incident analyst）</td>
          <td>低</td>
          <td>低</td>
          <td>低</td>
      </tr>
      <tr>
          <td>平台耦合</td>
          <td>PagerDuty ecosystem</td>
          <td>PagerDuty</td>
          <td>incident.io</td>
          <td>FireHydrant</td>
      </tr>
      <tr>
          <td>文化前提</td>
          <td>Production Excellence、blame-aware</td>
          <td>無前提</td>
          <td>Slack-first IR</td>
          <td>結構化 action tracking</td>
      </tr>
  </tbody>
</table>
<p>選 Jeli 的核心訴求：<em>SRE-mature org + 願投入 incident analyst 時間 + 已是 PagerDuty 生態 + 想做 systemic learning 而非單事故 root cause</em>。中等成熟度組織單事故 retro 量大、走 incident.io / FireHydrant 的輕量模板就夠。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Production Excellence 文化前提</strong>：Nora Jones / Charity Majors 推的 <em>blame-aware</em>（不是 blameless — blameless 太絕對、實務上人會自我審查；blame-aware 是承認情緒存在但不把責任貼個人）學習文化、跟 <a href="/blog/backend/04-observability/vendors/honeycomb/" data-link-title="Honeycomb" data-link-desc="High-cardinality observability 平台、events-based 模型">Honeycomb</a> Production Excellence 對齊。Jeli 工具只在這個文化前提下有用、強行 deploy 到 blame-heavy org 會被當成「找戰犯的另一個工具」。</p>
<p><strong>Interview methodology 深層原則</strong>：question template 不是 checklist、是 <em>讓 responder 重建當下心智模型</em> 的工具。常見反例是 facilitator 問「為什麼你沒看 dashboard」— 這是 <em>hindsight bias</em>；正確問法是「你當下看了哪些 signal、它們告訴你什麼」。facilitator 訓練是 Jeli 流程的隱性投資、不只是工具熟悉度。</p>
<p><strong>Cross-incident tag taxonomy</strong>：pattern detection 的前提是 tag 一致。常見治理失敗：每個 incident 用 free-form tag、半年後同類事故掛不同 tag、longitudinal scan 抓不到 signal。實務治理走 <em>固定 tag dictionary</em>（component / failure mode / contributing factor type）+ 季度 retag review、犧牲一些彈性換 pattern detection 可用性。</p>
<p><strong>Multi-incident analysis 的樣本門檻</strong>：跨事故 pattern 要可信、最少 20-30 個同類事故樣本、跨 6-12 個月時間窗。樣本不足時 <em>pattern</em> 可能只是巧合 — 解法是先把單事故 retro 做扎實、樣本累積到門檻再啟動 longitudinal scan、不要為了「跑 cross-incident」而提前下結論。Output 形狀是 <em>org-level intervention 建議書</em>（哪個 process / tooling / training 該改）、回寫 <a href="/blog/backend/08-incident-response/incident-pattern-library/" data-link-title="8.9 事故型態庫入口" data-link-desc="把跨服務的共通事故型態抽成型態卡，作為新事故的判讀錨點">Incident Pattern Library</a>。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Interview transcript 沒寫好</strong>：facilitator 用 leading question / hindsight bias 問法、responder 答案被引導 — 走 question template review、facilitator 訓練、不讓當事人當 facilitator</li>
<li><strong>Narrative drafting AI hallucination</strong>：auto-draft 把 timeline 缺漏處用 plausible 但無 citation 的描述補上、analyst sign-off 沒驗 citation — 強制每段 narrative claim 必須回指 transcript / Slack / metric 來源、AI draft 是骨架不是結論</li>
<li><strong>Narrative 流於表面 timeline 重寫</strong>：interview 沒問 <em>surprising / unexpected</em> 角度、只重述 chronology — 強化 question template 第三軸、analyst review 拒收沒 contributing factors 段落的 draft</li>
<li><strong>Pattern detection 太空 / 抓不到 signal</strong>：多事故 tag 不一致 / 樣本數不足（&lt; 20 incident）/ 沒人定期跑 scan — 補 tag taxonomy + 季度 pattern review 排程、不到樣本數先當單事故 retro</li>
<li><strong>Interview 排不出來</strong>：sev1 後 facilitator 沒指派 / 當事人 schedule 衝突拖 2 週 — sev1 / sev2 預設 IC handoff 時即指派 facilitator、interview 14 天內必排（記憶衰減 window）</li>
<li><strong>Action item 黑洞</strong>：retro 完成但 action item 沒人 own、3 個月後同類事故重發 — Jeli 不是 action tracking 工具、必須外接 Jira / Linear、retro 完成 == action item 有 owner + due date</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>輕量 weekly retro template</td>
          <td><a href="/blog/backend/08-incident-response/vendors/incident-io/" data-link-title="incident.io" data-link-desc="Slack-native IR 平台、整合 paging / response / retro">incident.io</a> / <a href="/blog/backend/08-incident-response/vendors/firehydrant/" data-link-title="FireHydrant" data-link-desc="IR &#43; retrospective 平台、Slack / Teams 整合、service catalog &#43; runbook automation 為核心">FireHydrant</a> retro 模組</td>
      </tr>
      <tr>
          <td>不在 PagerDuty 生態</td>
          <td>Blameless / Howie / 自建 Confluence template</td>
      </tr>
      <tr>
          <td>Action item tracking 為主</td>
          <td>Jira / Linear（Jeli 不擅長）</td>
      </tr>
      <tr>
          <td>沒 incident analyst 人力</td>
          <td>PagerDuty Postmortem 舊模組 / Confluence template + Jira action item</td>
      </tr>
      <tr>
          <td>Blame-heavy 文化未準備</td>
          <td>先補 Production Excellence 文化、再上 Jeli</td>
      </tr>
      <tr>
          <td>Pattern library 治理</td>
          <td><a href="/blog/backend/08-incident-response/incident-pattern-library/" data-link-title="8.9 事故型態庫入口" data-link-desc="把跨服務的共通事故型態抽成型態卡，作為新事故的判讀錨點">Incident Pattern Library</a>（章節層、不是工具）</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Production Excellence 完整理論（Nora Jones / Charity Majors 公開資料）</li>
<li>PagerDuty Process Automation 跟 Jeli 的整合細節 roadmap</li>
<li>CAST / STAMP 完整方法論（Nancy Leveson MIT 公開教材）</li>
<li>Interview facilitator 訓練課程</li>
<li>Tag taxonomy 設計細節（屬 <a href="/blog/backend/08-incident-response/incident-pattern-library/" data-link-title="8.9 事故型態庫入口" data-link-desc="把跨服務的共通事故型態抽成型態卡，作為新事故的判讀錨點">Incident Pattern Library</a>）</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>Jeli 流程本身的客戶多為 SRE-mature org（Slack / Honeycomb / Netflix 等公開 talk 引用）、本案例庫沒有直接揭露 Jeli 流程的事故、但所有跨事故 systemic learning 的 case 都是 Jeli 方法論的對照閱讀：</p>
<table>
  <thead>
      <tr>
          <th>案例方向</th>
          <th>跟 Jeli 的關係（對照啟示）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/08-incident-response/cases/slack/" data-link-title="Slack" data-link-desc="Slack 通訊服務事故與外部狀態頁設計">Slack cases</a></td>
          <td>Slack 內部事故 retro 結構（外部視角）、Production Excellence 文化內生的 learning 流程</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/08-incident-response/cases/cloudflare/" data-link-title="Cloudflare" data-link-desc="Cloudflare 全球 edge 事故時間線與架構脈絡">Cloudflare cases</a></td>
          <td>多次 control plane / data plane 事故的跨事故 pattern、systemic learning 的具體形狀</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/08-incident-response/cases/github/" data-link-title="GitHub" data-link-desc="GitHub 重大事故時間線與架構脈絡">GitHub cases</a></td>
          <td>大型平台連續事故的 contributing factor 累積、cross-incident pattern detection 的典型 input</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/08-incident-response/cases/datadog/" data-link-title="Datadog" data-link-desc="Datadog 監控服務事故、客戶觀測落差">Datadog cases</a></td>
          <td>觀測平台事故的 surprising / unexpected behavior 紀錄、interview workflow 該抓的 narrative 軸</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/08-incident-response/incident-pattern-library/" data-link-title="8.9 事故型態庫入口" data-link-desc="把跨服務的共通事故型態抽成型態卡，作為新事故的判讀錨點">Incident Pattern Library (section)</a></td>
          <td>Jeli cross-incident analysis output 該回寫的 collection、tag taxonomy 治理的章節層原則</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/08-incident-response/post-incident-review/" data-link-title="8.5 復盤與改進追蹤" data-link-desc="把 RCA 與 action items 轉成可驗證閉環">Post-Incident Review (section)</a></td>
          <td>Narrative reconstruction + contributing factors + interview workflow 的章節層原則、Jeli 是其工具實作</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/08-incident-response/incident-evidence-write-back/" data-link-title="8.22 Incident Evidence Write-back" data-link-desc="把事故證據、決策與復盤結論回寫到 observability、reliability 與 runbook">8.22 Incident Evidence Write-back</a>、<a href="/blog/backend/08-incident-response/post-incident-review/" data-link-title="8.5 復盤與改進追蹤" data-link-desc="把 RCA 與 action items 轉成可驗證閉環">Post-Incident Review</a></li>
<li>平行：<a href="/blog/backend/08-incident-response/vendors/pagerduty/" data-link-title="PagerDuty" data-link-desc="On-call / alerting 主流 SaaS、IR 平台演化">PagerDuty</a>（已整合 paging 來源）、<a href="/blog/backend/08-incident-response/vendors/incident-io/" data-link-title="incident.io" data-link-desc="Slack-native IR 平台、整合 paging / response / retro">incident.io</a>、<a href="/blog/backend/08-incident-response/vendors/firehydrant/" data-link-title="FireHydrant" data-link-desc="IR &#43; retrospective 平台、Slack / Teams 整合、service catalog &#43; runbook automation 為核心">FireHydrant</a>（輕量 retro 對照）</li>
<li>下游：<a href="/blog/backend/08-incident-response/incident-pattern-library/" data-link-title="8.9 事故型態庫入口" data-link-desc="把跨服務的共通事故型態抽成型態卡，作為新事故的判讀錨點">Incident Pattern Library</a>（cross-incident output）、<a href="/blog/backend/04-observability/vendors/honeycomb/" data-link-title="Honeycomb" data-link-desc="High-cardinality observability 平台、events-based 模型">Honeycomb</a>（observability + Production Excellence 文化）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>、<a href="/blog/backend/04-observability/" data-link-title="模組四：可觀測性平台" data-link-desc="整理 log、metric、trace、dashboard 與 alert 的後端操作實務">4 observability</a>（事故當下 signal 來源 → Jeli narrative source）</li>
<li>官方：<a href="https://www.pagerduty.com/blog/welcome-jeli/">Welcome Jeli (PagerDuty blog, 2023)</a></li>
</ul>
]]></content:encoded></item><item><title>Sentry</title><link>https://tarrragon.github.io/blog/backend/04-observability/vendors/sentry/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/04-observability/vendors/sentry/</guid><description>&lt;p>Sentry 是 error tracking 的事實標準、承擔三個責任：跨 frontend / backend / mobile 的 unhandled exception 自動聚合（issue grouping）、release-aware error tracking（regressed errors / source map）、延伸功能（APM / Continuous Profiling / Session Replay / Cron Monitoring）。設計取捨偏向「錯誤生命週期管理 + UX 強 + OSS self-host 雙軌」、不追求 metrics / logs 全面平台。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>整合 Sentry SDK（auto-instrumentation）到 frontend / backend / mobile&lt;/li>
&lt;li>配置 release + source map、追蹤 regressed errors&lt;/li>
&lt;li>設計 issue grouping / fingerprint 避免 noise&lt;/li>
&lt;li>用 Sentry Performance / Session Replay / Cron Monitoring&lt;/li>
&lt;li>評估 self-hosted vs SaaS、跟 IR 平台整合&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑5-分鐘把-sentry-跑起來">最短路徑：5 分鐘把 Sentry 跑起來&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 1. 註冊 Sentry / self-host、拿 DSN&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: 從 Console 拿 project DSN&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="c1"># 2. 整合 SDK（範例：Python）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: import sentry_sdk; sentry_sdk.init(dsn=..., traces_sample_rate=1.0)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">&lt;span class="c1"># 3. 觸發 test exception 驗證&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: try: 1/0 / except: sentry_sdk.capture_exception()&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="日常操作與決策形狀">日常操作與決策形狀&lt;/h2>
&lt;h3 id="sdk-整合auto-instrumentation">SDK 整合（auto-instrumentation）&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>各語言 SDK：Python / Node / Java / Go / Ruby / PHP / .NET / iOS / Android&lt;/li>
&lt;li>自動 framework instrumentation（Django / FastAPI / Express / Rails 等）&lt;/li>
&lt;li>Manual capture：&lt;code>capture_exception&lt;/code> / &lt;code>capture_message&lt;/code>&lt;/li>
&lt;li>對應 OTel integration（Sentry 接受 OTel context）&lt;/li>
&lt;/ul>
&lt;h3 id="release--source-map">Release / source map&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>Release 標記每次部署（git SHA / version）&lt;/li>
&lt;li>Source map 上傳：minified frontend code → readable stack trace&lt;/li>
&lt;li>Regressed errors：之前 resolved 在新 release 又出現&lt;/li>
&lt;li>對應 release health metric&lt;/li>
&lt;/ul>
&lt;h3 id="issue-grouping--fingerprint">Issue grouping / fingerprint&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>Auto grouping：based on stack trace + exception type&lt;/li>
&lt;li>自訂 fingerprint：把不同 errors 聚成同 issue&lt;/li>
&lt;li>拆 issue：相同 stack 但需分開追蹤&lt;/li>
&lt;li>對應 noise 控制&lt;/li>
&lt;/ul>
&lt;h3 id="performance-monitoring">Performance monitoring&lt;/h3>
&lt;p>子議題：&lt;/p></description><content:encoded><![CDATA[<p>Sentry 是 error tracking 的事實標準、承擔三個責任：跨 frontend / backend / mobile 的 unhandled exception 自動聚合（issue grouping）、release-aware error tracking（regressed errors / source map）、延伸功能（APM / Continuous Profiling / Session Replay / Cron Monitoring）。設計取捨偏向「錯誤生命週期管理 + UX 強 + OSS self-host 雙軌」、不追求 metrics / logs 全面平台。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>整合 Sentry SDK（auto-instrumentation）到 frontend / backend / mobile</li>
<li>配置 release + source map、追蹤 regressed errors</li>
<li>設計 issue grouping / fingerprint 避免 noise</li>
<li>用 Sentry Performance / Session Replay / Cron Monitoring</li>
<li>評估 self-hosted vs SaaS、跟 IR 平台整合</li>
</ol>
<h2 id="最短路徑5-分鐘把-sentry-跑起來">最短路徑：5 分鐘把 Sentry 跑起來</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 1. 註冊 Sentry / self-host、拿 DSN</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># TODO: 從 Console 拿 project DSN</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 2. 整合 SDK（範例：Python）</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="c1"># TODO: import sentry_sdk; sentry_sdk.init(dsn=..., traces_sample_rate=1.0)</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="c1"># 3. 觸發 test exception 驗證</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="c1"># TODO: try: 1/0 / except: sentry_sdk.capture_exception()</span></span></span></code></pre></div><h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="sdk-整合auto-instrumentation">SDK 整合（auto-instrumentation）</h3>
<p>子議題：</p>
<ul>
<li>各語言 SDK：Python / Node / Java / Go / Ruby / PHP / .NET / iOS / Android</li>
<li>自動 framework instrumentation（Django / FastAPI / Express / Rails 等）</li>
<li>Manual capture：<code>capture_exception</code> / <code>capture_message</code></li>
<li>對應 OTel integration（Sentry 接受 OTel context）</li>
</ul>
<h3 id="release--source-map">Release / source map</h3>
<p>子議題：</p>
<ul>
<li>Release 標記每次部署（git SHA / version）</li>
<li>Source map 上傳：minified frontend code → readable stack trace</li>
<li>Regressed errors：之前 resolved 在新 release 又出現</li>
<li>對應 release health metric</li>
</ul>
<h3 id="issue-grouping--fingerprint">Issue grouping / fingerprint</h3>
<p>子議題：</p>
<ul>
<li>Auto grouping：based on stack trace + exception type</li>
<li>自訂 fingerprint：把不同 errors 聚成同 issue</li>
<li>拆 issue：相同 stack 但需分開追蹤</li>
<li>對應 noise 控制</li>
</ul>
<h3 id="performance-monitoring">Performance monitoring</h3>
<p>子議題：</p>
<ul>
<li>Traces sampling rate</li>
<li>Transaction / span 結構（類 APM）</li>
<li>Web Vitals（前端 LCP / FID / CLS）</li>
<li>跟 OTel trace 互操作</li>
</ul>
<h2 id="deep-article">Deep Article</h2>
<ul>
<li><a href="error-grouping-fingerprinting/">Error Grouping 與 Fingerprinting 策略</a>：預設 grouping 演算法、自訂 fingerprint rules、merge/unmerge、grouping 不準的判讀與大量 unique errors 的治理</li>
<li><a href="release-tracking-session-replay/">Release Tracking 與 Session Replay</a>：release health、deploy tracking、session replay 隱私設定、performance monitoring 與 OTel 整合、self-hosted vs SaaS</li>
</ul>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<h3 id="session-replay">Session Replay</h3>
<p>子議題：</p>
<ul>
<li>前端用戶體驗錄影（含 error 前後操作）</li>
<li>隱私設定：mask PII / block element</li>
<li>Sample rate 控制</li>
<li>跟 LogRocket / FullStory 對照</li>
</ul>
<h3 id="cron-monitoringsentry-crons">Cron Monitoring（Sentry Crons）</h3>
<p>子議題：</p>
<ul>
<li>監控 scheduled job 是否準時跑 + 是否成功</li>
<li>Schedule 配置（crontab / interval）</li>
<li>Heartbeat ping / 自動 alert</li>
<li>對應 <a href="/blog/backend/08-incident-response/" data-link-title="模組八：事故處理與復盤" data-link-desc="用 IR 領域詞彙建問題節點、以服務級案例庫累積事故脈絡，先建概念與案例庫再進實作交接">08 incident response</a></li>
</ul>
<h3 id="continuous-profiling">Continuous Profiling</h3>
<p>子議題：</p>
<ul>
<li>各語言 profiler（Python / Node / Go）</li>
<li>CPU / memory flame graph</li>
<li>跟 Pyroscope / Datadog Profiler 對照</li>
</ul>
<h3 id="self-hosted-vs-saas">Self-hosted vs SaaS</h3>
<p>子議題：</p>
<ul>
<li>Self-hosted：Sentry OSS（docker-compose + 數十 service）</li>
<li>SaaS：sentry.io、5 levels（developer / team / business / enterprise）</li>
<li>規模化通常用 SaaS（self-host 維運成本高）</li>
<li>Privacy / compliance 場景：self-host</li>
</ul>
<h3 id="跟-ir-平台整合">跟 IR 平台整合</h3>
<p>子議題：</p>
<ul>
<li>跟 PagerDuty / Opsgenie / incident.io 整合</li>
<li>Alert routing：嚴重 issue → on-call</li>
<li>Issue 跟 incident ticket 關聯</li>
<li>對應 <a href="/blog/backend/08-incident-response/" data-link-title="模組八：事故處理與復盤" data-link-desc="用 IR 領域詞彙建問題節點、以服務級案例庫累積事故脈絡，先建概念與案例庫再進實作交接">08 incident response 模組</a></li>
</ul>
<h3 id="otel-integration">OTel integration</h3>
<p>子議題：</p>
<ul>
<li>Sentry SDK 接受 OTel context（trace_id / span_id）</li>
<li>跟其他 OTel backend dual ship</li>
<li>Sentry 自家 SDK feature 較深（vs 純 OTel）</li>
</ul>
<h2 id="跟-monitoring-模組的分工">跟 Monitoring 模組的分工</h2>
<p>本頁從 server-side 觀測平台角度說明 Sentry — error grouping 的告警整合、performance monitoring 的 SLI 指標設計、self-hosted vs SaaS 成本、跟 OTel 的 context 整合。Client-side 的使用體驗（SDK 自動攔截設計、error grouping 的 client 端行為、session replay 的操作重播、跟自架 monitor 的比較）見 <a href="/blog/monitoring/06-commercial-comparison/sentry-deep-dive/" data-link-title="Sentry 深入" data-link-desc="Error tracking &#43; performance monitoring &#43; session replay 的架構 — Sentry 從 error-first 出發如何擴展到全面可觀測性">Monitoring 模組 Sentry 深入</a>。</p>
<p>兩者的交叉點是 error event 的格式和 trace context propagation — client SDK 捕獲的 error 帶 trace context，server-side 的 Sentry 用同一個 trace 串接完整路徑。</p>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<h3 id="issue-不出現">Issue 不出現</h3>
<p>操作原則：先確認 SDK 配置（DSN + initialization）、再看 sampling rate、最後看 ad blocker 等網路問題。</p>
<h3 id="issue-noise太多-issue">Issue noise（太多 issue）</h3>
<p>操作原則：用 fingerprint / inbound filter / rate limit 控制。判讀：Issue list 看哪些是噪音。</p>
<h3 id="release-沒對應">Release 沒對應</h3>
<p>操作原則：release tag 沒正確傳 SDK、或 source map 沒上傳。判讀：issue 沒有 release 資訊。</p>
<h3 id="performance-traces-缺失">Performance traces 缺失</h3>
<p>操作原則：sampling rate 過低或 SDK 沒啟用 performance。</p>
<h3 id="session-replay-不出現">Session Replay 不出現</h3>
<p>操作原則：sample rate 設定 + 隱私 setting 是否 block 過頭。</p>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>完整 metrics / logs 平台</td>
          <td><a href="/blog/backend/04-observability/vendors/datadog/" data-link-title="Datadog" data-link-desc="All-in-one SaaS 觀測平台、APM / Logs / Metrics / RUM / Security">Datadog</a> / <a href="/blog/backend/04-observability/vendors/grafana-stack/" data-link-title="Grafana Stack" data-link-desc="Grafana / Loki / Tempo / Mimir / Pyroscope 全棧">Grafana Stack</a> / ELK</td>
      </tr>
      <tr>
          <td>High-cardinality 分析</td>
          <td><a href="/blog/backend/04-observability/vendors/honeycomb/" data-link-title="Honeycomb" data-link-desc="High-cardinality observability 平台、events-based 模型">Honeycomb</a></td>
      </tr>
      <tr>
          <td>純 backend 已有 APM</td>
          <td>跟 <a href="/blog/backend/04-observability/vendors/datadog/" data-link-title="Datadog" data-link-desc="All-in-one SaaS 觀測平台、APM / Logs / Metrics / RUM / Security">Datadog</a> APM 重疊、選一即可</td>
      </tr>
      <tr>
          <td>替代 error tracking</td>
          <td>Bugsnag / Rollbar / Raygun（T2 候選）</td>
      </tr>
      <tr>
          <td>Pure logs / metrics</td>
          <td><a href="/blog/backend/04-observability/vendors/prometheus/" data-link-title="Prometheus" data-link-desc="Pull-based metrics 主流 OSS、PromQL 與 alerting">Prometheus</a> / <a href="/blog/backend/04-observability/vendors/elastic-stack/" data-link-title="Elastic Stack" data-link-desc="ELK：Elasticsearch / Logstash / Kibana &#43; Beats / APM">Elastic</a> / Cloud-native</td>
      </tr>
      <tr>
          <td>OTel-only 標準</td>
          <td><a href="/blog/backend/04-observability/vendors/opentelemetry/" data-link-title="OpenTelemetry" data-link-desc="可觀測性開放標準、SDK 與 Collector">OTel</a> + 任一 backend</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>各語言 Sentry SDK 完整 API</li>
<li>Sentry self-host 部署細節</li>
<li>各 framework integration 細節</li>
<li>Sentry pricing 詳細</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<h3 id="直接相關案例待補-frontend-sentry-case">直接相關案例（待補 frontend Sentry case）</h3>
<p>Sentry 是 04 observability 模組第二大 SaaS（次 Datadog）、但 04 cases 庫主要聚焦 OTel / Prometheus / Grafana / ELK 等後端 telemetry pipeline 場景、Sentry 直接案例（frontend error / release health）待補。</p>
<h3 id="跨-vendor-對照">跨 vendor 對照</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>對 Sentry 的對應</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/fintech-audit-evidence-observability/" data-link-title="FinTech：審計證據鏈的可觀測性設計" data-link-desc="把交易與存取事件轉成可回查證據，降低合規審核與事故判讀落差。">4.C1 Fintech audit</a></td>
          <td>Issue 跟 audit evidence 串聯、release 對應監管要求</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/gaming-peak-signal-freshness-and-cardinality/" data-link-title="Gaming：高峰流量下的訊號新鮮度與 Cardinality" data-link-desc="在高峰事件中控制訊號延遲與維度爆炸，維持告警與定位可信度。">4.C2 Gaming peak</a></td>
          <td>高峰下 issue noise / rate limit / inbound filter</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/failure-otel-migration-signal-drift/" data-link-title="4.C9 反例：OTel 遷移後訊號漂移" data-link-desc="雙軌採集未對齊導致告警與 SLO 判讀失真。">4.C9 OTel migration signal drift</a></td>
          <td>Sentry SDK ↔ OTel context propagation 雙軌驗證</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/04-observability/cases/contrast-observability-rollout-by-scale/" data-link-title="4.C10 對照：規模差異下的觀測遷移" data-link-desc="觀測遷移在不同規模團隊下的流程與風險差異。">4.C10 規模對照</a></td>
          <td>Frontend / mobile-heavy team 通常選 Sentry</td>
      </tr>
  </tbody>
</table>
<p><strong>待補 frontend Sentry case</strong>：大規模前端團隊（Shopify / Slack / GitHub frontend）error tracking 案例、release health 落地、跟 incident.io / PagerDuty 整合案例。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游概念：<a href="/blog/backend/04-observability/telemetry-data-quality/" data-link-title="4.17 Telemetry Data Quality" data-link-desc="把 missing signal、schema drift、sampling bias 與 timestamp skew 變成資料品質問題">4.17 Telemetry Data Quality</a></li>
<li>平行 vendor：<a href="/blog/backend/04-observability/vendors/datadog/" data-link-title="Datadog" data-link-desc="All-in-one SaaS 觀測平台、APM / Logs / Metrics / RUM / Security">Datadog</a>、<a href="/blog/backend/04-observability/vendors/opentelemetry/" data-link-title="OpenTelemetry" data-link-desc="可觀測性開放標準、SDK 與 Collector">OpenTelemetry</a></li>
<li>下游能力：<a href="/blog/backend/08-incident-response/" data-link-title="模組八：事故處理與復盤" data-link-desc="用 IR 領域詞彙建問題節點、以服務級案例庫累積事故脈絡，先建概念與案例庫再進實作交接">08 incident response 模組</a></li>
</ul>
]]></content:encoded></item><item><title>Firestore</title><link>https://tarrragon.github.io/blog/backend/01-database/vendors/firestore/</link><pubDate>Tue, 16 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/01-database/vendors/firestore/</guid><description>&lt;p>Firestore 是 Google 的 serverless document database、承擔 mobile app 與 SPA 的正式狀態與多裝置即時同步責任。它的資料形狀是 collection 下的 document、存取模型是 client 端用 SDK 直連、授權靠 Security Rules，而不是經過自己寫的後端服務。Firestore 同時是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/baas/" data-link-title="BaaS（Backend as a Service）" data-link-desc="說明把認證、資料庫、檔案儲存、推播打包成現成模組、由前端 SDK 直連的後端交付形態">Firebase&lt;/a> bundle 的資料層、也能在 Google Cloud 上單獨使用；本頁從&lt;strong>資料層 vendor 視角&lt;/strong>說明它承擔什麼狀態責任、為哪種查詢付成本、何時撞牆該遷往自建。要不要採用 BaaS 這種交付形態本身、是更上層的決策，見 &lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/delivery-mode-selection/" data-link-title="0.21 交付形態選型：從全託管到自建的光譜與邊界" data-link-desc="在進入資料庫、快取與部署選型之前、先判斷服務該用託管平台（Wix / Shopify / Google Sites）、辦公生態自動化（Apps Script）、BaaS（Firebase）、半託管 CMS（WordPress）還是自建、並為日後遷往自建保留可遷出路徑">0.21 交付形態選型&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/capability-buy-vs-build/" data-link-title="0.22 能力級買 vs 建：feature-as-a-service 與 BaaS bundle 選型" data-link-desc="在交付形態決定整個系統要不要自建之後、逐能力判斷該外包還是自建：辨識 managed 基礎設施、feature SaaS 與 BaaS bundle 三種外包深度、no-code 到 dev-tool 的服務光譜、買 vs 建判準與權重浮動、整合接縫與遷出代價">0.22 能力級買 vs 建&lt;/a>。&lt;/p>
&lt;p>官方文件路由：&lt;a href="https://firebase.google.com/docs/firestore">Firestore documentation&lt;/a>、&lt;a href="https://firebase.google.com/docs/firestore/data-model">Firestore data model&lt;/a>、&lt;a href="https://firebase.google.com/docs/firestore/pricing">Firestore pricing&lt;/a>；本頁時間敏感的計費與限制 claim 以官方為準、最後檢查日 2026-06-16。&lt;/p>
&lt;h2 id="教學路線client-直連的-document-正式狀態">教學路線：client 直連的 document 正式狀態&lt;/h2>
&lt;p>Firestore 服務頁的教學目標是把「前端直接讀寫資料庫」這個存取模型的責任說清楚。讀者讀完後要能判斷 Firestore 何時是合適的正式狀態，何時因為查詢形狀、成本曲線或授權複雜度該轉向自建後端配 &lt;a href="https://tarrragon.github.io/blog/backend/01-database/vendors/postgresql/" data-link-title="PostgreSQL" data-link-desc="多用途 OLTP 主流關聯式資料庫、MVCC、豐富 SQL 特性、是 Aurora / Cosmos DB / Spanner / CockroachDB / Aurora DSQL 的相容目標">PostgreSQL&lt;/a> 或留在 document model 換 &lt;a href="https://tarrragon.github.io/blog/backend/01-database/vendors/mongodb/" data-link-title="MongoDB" data-link-desc="Document database 代表、Atlas managed、跨雲可用、許多大規模平台從 MongoDB 起家">MongoDB&lt;/a>。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>學習段&lt;/th>
 &lt;th>核心問題&lt;/th>
 &lt;th>對應段落&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Client-direct state&lt;/td>
 &lt;td>前端用 SDK 直連、授權下沉到 Security Rules 後責任邊界在哪&lt;/td>
 &lt;td>定位、存取模型&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Document shape&lt;/td>
 &lt;td>collection / document / subcollection 如何決定查詢能力&lt;/td>
 &lt;td>資料形狀、適用場景&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Query boundary&lt;/td>
 &lt;td>為什麼跨 collection 報表查不出來、index 與查詢限制如何約束建模&lt;/td>
 &lt;td>不適用場景、常見陷阱&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Realtime / offline&lt;/td>
 &lt;td>snapshot listener 與 offline persistence 解哪類多裝置同步問題&lt;/td>
 &lt;td>適用場景、跟其他 vendor 的取捨&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>替代路由&lt;/td>
 &lt;td>撞到報表、成本或授權牆時、遷往自建 relational 或換 document vendor&lt;/td>
 &lt;td>下一步路由、遷移 playbook&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="定位serverless-document-store--baas-資料層">定位：serverless document store + BaaS 資料層&lt;/h2>
&lt;p>Firestore 跟 &lt;a href="https://tarrragon.github.io/blog/backend/01-database/vendors/mongodb/" data-link-title="MongoDB" data-link-desc="Document database 代表、Atlas managed、跨雲可用、許多大規模平台從 MongoDB 起家">MongoDB&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/01-database/vendors/dynamodb/" data-link-title="DynamoDB" data-link-desc="AWS managed key-value、partition-based scaling、9000 萬 RPS sustained 實戰證據">DynamoDB&lt;/a> 同屬 NoSQL document / KV 家族，但承擔的責任層級不同：&lt;/p>
&lt;ul>
&lt;li>資料組織成 collection 下的 document，document 可巢狀 subcollection，單 document 上限 1 MiB&lt;/li>
&lt;li>沒有 server 端 JOIN，跨 collection 的關聯要靠 application 多次查詢自己組、或在寫入時反正規化&lt;/li>
&lt;li>存取模型以 client SDK 直連為主，授權寫在 Security Rules（一套規則 DSL），而不是後端 API 的權限中介層&lt;/li>
&lt;li>兩種營運模式：Firestore Native mode（行動 / web、含 realtime 與 offline）與 Datastore mode（server 端、相容舊 Datastore）&lt;/li>
&lt;/ul>
&lt;p>傳統定位：Firebase 行動 app 與 SPA 的後端資料層、MVP 快速驗證期、多裝置即時同步的產品。&lt;/p></description><content:encoded><![CDATA[<p>Firestore 是 Google 的 serverless document database、承擔 mobile app 與 SPA 的正式狀態與多裝置即時同步責任。它的資料形狀是 collection 下的 document、存取模型是 client 端用 SDK 直連、授權靠 Security Rules，而不是經過自己寫的後端服務。Firestore 同時是 <a href="/blog/backend/knowledge-cards/baas/" data-link-title="BaaS（Backend as a Service）" data-link-desc="說明把認證、資料庫、檔案儲存、推播打包成現成模組、由前端 SDK 直連的後端交付形態">Firebase</a> bundle 的資料層、也能在 Google Cloud 上單獨使用；本頁從<strong>資料層 vendor 視角</strong>說明它承擔什麼狀態責任、為哪種查詢付成本、何時撞牆該遷往自建。要不要採用 BaaS 這種交付形態本身、是更上層的決策，見 <a href="/blog/backend/00-service-selection/delivery-mode-selection/" data-link-title="0.21 交付形態選型：從全託管到自建的光譜與邊界" data-link-desc="在進入資料庫、快取與部署選型之前、先判斷服務該用託管平台（Wix / Shopify / Google Sites）、辦公生態自動化（Apps Script）、BaaS（Firebase）、半託管 CMS（WordPress）還是自建、並為日後遷往自建保留可遷出路徑">0.21 交付形態選型</a> 與 <a href="/blog/backend/00-service-selection/capability-buy-vs-build/" data-link-title="0.22 能力級買 vs 建：feature-as-a-service 與 BaaS bundle 選型" data-link-desc="在交付形態決定整個系統要不要自建之後、逐能力判斷該外包還是自建：辨識 managed 基礎設施、feature SaaS 與 BaaS bundle 三種外包深度、no-code 到 dev-tool 的服務光譜、買 vs 建判準與權重浮動、整合接縫與遷出代價">0.22 能力級買 vs 建</a>。</p>
<p>官方文件路由：<a href="https://firebase.google.com/docs/firestore">Firestore documentation</a>、<a href="https://firebase.google.com/docs/firestore/data-model">Firestore data model</a>、<a href="https://firebase.google.com/docs/firestore/pricing">Firestore pricing</a>；本頁時間敏感的計費與限制 claim 以官方為準、最後檢查日 2026-06-16。</p>
<h2 id="教學路線client-直連的-document-正式狀態">教學路線：client 直連的 document 正式狀態</h2>
<p>Firestore 服務頁的教學目標是把「前端直接讀寫資料庫」這個存取模型的責任說清楚。讀者讀完後要能判斷 Firestore 何時是合適的正式狀態，何時因為查詢形狀、成本曲線或授權複雜度該轉向自建後端配 <a href="/blog/backend/01-database/vendors/postgresql/" data-link-title="PostgreSQL" data-link-desc="多用途 OLTP 主流關聯式資料庫、MVCC、豐富 SQL 特性、是 Aurora / Cosmos DB / Spanner / CockroachDB / Aurora DSQL 的相容目標">PostgreSQL</a> 或留在 document model 換 <a href="/blog/backend/01-database/vendors/mongodb/" data-link-title="MongoDB" data-link-desc="Document database 代表、Atlas managed、跨雲可用、許多大規模平台從 MongoDB 起家">MongoDB</a>。</p>
<table>
  <thead>
      <tr>
          <th>學習段</th>
          <th>核心問題</th>
          <th>對應段落</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Client-direct state</td>
          <td>前端用 SDK 直連、授權下沉到 Security Rules 後責任邊界在哪</td>
          <td>定位、存取模型</td>
      </tr>
      <tr>
          <td>Document shape</td>
          <td>collection / document / subcollection 如何決定查詢能力</td>
          <td>資料形狀、適用場景</td>
      </tr>
      <tr>
          <td>Query boundary</td>
          <td>為什麼跨 collection 報表查不出來、index 與查詢限制如何約束建模</td>
          <td>不適用場景、常見陷阱</td>
      </tr>
      <tr>
          <td>Realtime / offline</td>
          <td>snapshot listener 與 offline persistence 解哪類多裝置同步問題</td>
          <td>適用場景、跟其他 vendor 的取捨</td>
      </tr>
      <tr>
          <td>替代路由</td>
          <td>撞到報表、成本或授權牆時、遷往自建 relational 或換 document vendor</td>
          <td>下一步路由、遷移 playbook</td>
      </tr>
  </tbody>
</table>
<h2 id="定位serverless-document-store--baas-資料層">定位：serverless document store + BaaS 資料層</h2>
<p>Firestore 跟 <a href="/blog/backend/01-database/vendors/mongodb/" data-link-title="MongoDB" data-link-desc="Document database 代表、Atlas managed、跨雲可用、許多大規模平台從 MongoDB 起家">MongoDB</a>、<a href="/blog/backend/01-database/vendors/dynamodb/" data-link-title="DynamoDB" data-link-desc="AWS managed key-value、partition-based scaling、9000 萬 RPS sustained 實戰證據">DynamoDB</a> 同屬 NoSQL document / KV 家族，但承擔的責任層級不同：</p>
<ul>
<li>資料組織成 collection 下的 document，document 可巢狀 subcollection，單 document 上限 1 MiB</li>
<li>沒有 server 端 JOIN，跨 collection 的關聯要靠 application 多次查詢自己組、或在寫入時反正規化</li>
<li>存取模型以 client SDK 直連為主，授權寫在 Security Rules（一套規則 DSL），而不是後端 API 的權限中介層</li>
<li>兩種營運模式：Firestore Native mode（行動 / web、含 realtime 與 offline）與 Datastore mode（server 端、相容舊 Datastore）</li>
</ul>
<p>傳統定位：Firebase 行動 app 與 SPA 的後端資料層、MVP 快速驗證期、多裝置即時同步的產品。</p>
<p>資料層視角的定位：一塊 <em>managed serverless document store</em>，把 capacity、replication、failover、scaling 全部交給平台，代價是查詢能力與資料模型沿平台特性生長。</p>
<h2 id="資料形狀與查詢邊界">資料形狀與查詢邊界</h2>
<p>Firestore 為「已知路徑的 document 讀寫」付成本，不為「任意欄位的 ad-hoc 查詢」付成本。這個取向決定了它的甜蜜區與牆：</p>
<ul>
<li>單 document 與單 collection 內的 key-based / 條件查詢高效，且每筆查詢都要有對應 index（單欄 index 自動建立、複合查詢要建 composite index）</li>
<li>查詢結果集的計費與大小跟「讀了幾筆 document」成正比，不是跟「掃了多少」— 一次回 10,000 筆就計 10,000 次 read</li>
<li>缺少 server 端 aggregation pipeline 與 JOIN；跨集合報表（例如「本月各地區訂單金額」）在 Firestore 上要嘛預先把彙總寫成一份 document、要嘛把資料複製到分析系統</li>
<li>沒有原生全文搜尋，全文需求要接專門的 <a href="/blog/backend/knowledge-cards/search-index/" data-link-title="Search Index" data-link-desc="說明搜尋索引如何承擔全文檢索、排序與查詢體驗">search index</a>（Algolia、Elasticsearch / OpenSearch）</li>
</ul>
<p>這條查詢邊界是 Firestore 最容易被低估的設計約束。它不是「功能還沒做」，而是 client 直連 + serverless 計費模型的必然結果：把任意 ad-hoc 查詢開放給前端，等於把不可預測的成本與掃描壓力暴露在公網。建模時要先窮舉 access pattern、再決定 document 結構，跟 <a href="/blog/backend/01-database/vendors/dynamodb/single-table-design-pattern/" data-link-title="DynamoDB Single-Table Design：從適用度前置判讀到 access pattern 反推 PK/SK" data-link-desc="DynamoDB single-table 設計不是「資料表越少越好」，而是 access pattern 反推 PK/SK 跟 GSI；本文先做 DynamoDB 適用度 4 軸前置判讀（PK 天然均勻 / control plane vs data plane / consistency / access pattern 穩定），再展開設計流程、failure modes 與 durable queue 正向用例">DynamoDB single-table design</a> 的 access-pattern-first 思路同源。</p>
<h2 id="一致性realtime-與容量特性">一致性、realtime 與容量特性</h2>
<p><strong>一致性</strong>：</p>
<ul>
<li>單 document 讀寫與「查詢結果在同一 region 內」提供 strong consistency</li>
<li>多 region 部署靠平台複製、跨 region 讀取可能有延遲；一致性語意由平台決定、不可調到自管資料庫那種 isolation level 顆粒</li>
</ul>
<p><strong>Realtime 與 offline</strong>：</p>
<ul>
<li>snapshot listener 讓 client 訂閱 query 結果、資料變更即時推送，是多裝置同步的核心能力</li>
<li>行動 / web SDK 內建 offline persistence，斷線時讀寫本地快取、回線後同步，這是自建 REST API 要額外工程才有的能力</li>
</ul>
<p><strong>容量與寫入熱點</strong>：</p>
<ul>
<li>serverless 自動擴縮，無 connection 概念，前端裝置數不直接轉成資料庫連線壓力</li>
<li>單一 document 的高頻寫入會撞到 contention（官方建議單 document 的持續寫入維持在每秒個位數量級、高頻計數器要用 distributed counter 分片）</li>
<li>寫入吞吐與索引維護成本綁在一起：每多一個 index、寫入就多一份維護成本</li>
</ul>
<p>容量特性的時間敏感數字（每秒寫入軟上限、單 document contention 門檻）以 <a href="https://firebase.google.com/docs/firestore/best-practices">官方 best practices</a> 為準，設計高頻寫入前先查當前限制。</p>
<h2 id="適用場景">適用場景</h2>
<p><strong>1. 行動 app / SPA 的 MVP 後端</strong>：</p>
<ul>
<li>認證接 Firebase Auth、資料存 Firestore、推播接 Cloud Messaging，整個 MVP 沒有自己的後端服務</li>
<li>對應 <a href="/blog/backend/00-service-selection/delivery-mode-selection/" data-link-title="0.21 交付形態選型：從全託管到自建的光譜與邊界" data-link-desc="在進入資料庫、快取與部署選型之前、先判斷服務該用託管平台（Wix / Shopify / Google Sites）、辦公生態自動化（Apps Script）、BaaS（Firebase）、半託管 CMS（WordPress）還是自建、並為日後遷往自建保留可遷出路徑">0.21</a> BaaS 段的「把後端工程師這個角色延後」</li>
</ul>
<p><strong>2. 多裝置即時同步</strong>：</p>
<ul>
<li>協作筆記、聊天、即時看板這類「一處改、多處即時更新」的產品</li>
<li>snapshot listener + offline persistence 是這類需求的天然形狀</li>
</ul>
<p><strong>3. access pattern 穩定的 document 工作負載</strong>：</p>
<ul>
<li>user profile、設定、feed item、活動紀錄這類讀多寫少、查詢路徑固定的資料</li>
<li>跟 <a href="/blog/backend/knowledge-cards/source-of-truth/" data-link-title="Source of Truth" data-link-desc="說明正式資料來源如何決定資料判斷、修復與一致性責任">source of truth</a> 對齊：Firestore 可以是這些資料的正式狀態</li>
</ul>
<h2 id="不適用場景">不適用場景</h2>
<p><strong>1. 跨實體報表與分析查詢</strong>：</p>
<ul>
<li>跨 collection JOIN、ad-hoc 篩選、彙總統計在 Firestore 上要靠資料複製工程</li>
<li>替代：自建 relational（<a href="/blog/backend/01-database/vendors/postgresql/" data-link-title="PostgreSQL" data-link-desc="多用途 OLTP 主流關聯式資料庫、MVCC、豐富 SQL 特性、是 Aurora / Cosmos DB / Spanner / CockroachDB / Aurora DSQL 的相容目標">PostgreSQL</a>）或把資料同步進分析系統</li>
</ul>
<p><strong>2. 成本對流量敏感的高讀取場景</strong>：</p>
<ul>
<li>計費隨 document read / write / delete 線性成長，高流量下可能超過自建</li>
<li>替代：自管資料庫 + 應用層 <a href="/blog/backend/02-cache-redis/" data-link-title="模組二：快取與 Redis" data-link-desc="整理快取策略、Redis 資料型別與分散式狀態輔助能力">cache</a>，把熱讀取的單位成本壓下來</li>
</ul>
<p><strong>3. 複雜授權需要可測試的控制面</strong>：</p>
<ul>
<li>client 直連模型把授權全塞進 Security Rules，規則長到難以 review / 測試時，控制面風險升高</li>
<li>替代：把授權拉回後端 API 中介層（自建後端 + 任意資料庫）</li>
</ul>
<p><strong>4. 強一致的多實體交易</strong>：</p>
<ul>
<li>Firestore 有 transaction 與 batch write，但跨大量 document 的複雜交易不是它的主場</li>
<li>替代：relational database 的多表交易</li>
</ul>
<h2 id="跟其他-vendor-的取捨">跟其他 vendor 的取捨</h2>
<p><strong>vs MongoDB（document 對 document）</strong>：</p>
<ul>
<li>Firestore：serverless、client 直連、realtime listener、GCP / Firebase 綁定、查詢能力受限</li>
<li>MongoDB：查詢與 aggregation 彈性高、跨雲、要自管或用 Atlas managed、走後端中介存取</li>
<li>選 Firestore：行動 / 即時同步 / 想省整層後端</li>
<li>選 MongoDB：document model 但要彈性查詢、aggregation、跨雲可攜，見 <a href="/blog/backend/01-database/vendors/db3-vendor-selection/" data-link-title="DB3 Vendor Selection：document / KV / multi-model 三方選型 &#43; workload shape 前置判讀" data-link-desc="MongoDB / DynamoDB / Cosmos DB 三家 NoSQL 選型 entry point：workload shape × access pattern × consistency 三軸前置判讀、migration path 三型、federated DB 視角、三 vendor 對比 10 軸">db3 vendor selection</a></li>
</ul>
<p><strong>vs DynamoDB（serverless NoSQL 對 serverless NoSQL）</strong>：</p>
<ul>
<li>Firestore：GCP / Firebase 生態、內建 realtime 與 offline、client 直連為主</li>
<li>DynamoDB：AWS 生態、access-pattern-first KV、通常走後端整合、streams 接事件驅動</li>
<li>兩者的 access-pattern-first 建模思路相近，差別在生態與 client 直連的有無</li>
</ul>
<p><strong>vs SQLite（行動端的反向選擇）</strong>：</p>
<ul>
<li>Firestore：雲端 store、自動多裝置 sync、realtime</li>
<li>SQLite：embedded、offline-first、無 sync（見 <a href="/blog/backend/01-database/vendors/sqlite/" data-link-title="SQLite" data-link-desc="embedded、單檔案、test / CLI / edge 場景的標準選擇、近年因 Cloudflare D1 / Turso 等服務復興">SQLite vendor</a>）</li>
<li>選 Firestore：需要跨裝置同步與即時更新</li>
<li>選 SQLite：純單機 / offline、不需要雲端同步</li>
</ul>
<p><strong>vs Supabase（BaaS bundle 的另一條路）</strong>：</p>
<ul>
<li>Firestore：document model、Google 的 BaaS bundle 資料層</li>
<li>Supabase：底層是 PostgreSQL（relational）、開源 BaaS bundle，遷出時資料是標準 SQL</li>
<li>兩者都是 client 直連 + 規則授權的 BaaS 形狀，差別在資料模型（document vs relational）與遷出時的資料可攜性；Supabase 的資料層判讀見 <a href="/blog/backend/01-database/vendors/postgresql/managed-pg-comparison/" data-link-title="Managed PostgreSQL Comparison" data-link-desc="RDS PostgreSQL、Aurora PostgreSQL、Cloud SQL、Azure Database for PostgreSQL、Neon、Supabase、Crunchy Bridge 的責任邊界比較">Managed PostgreSQL 比較</a>，選型層錨點見 <a href="/blog/backend/00-service-selection/capability-buy-vs-build/" data-link-title="0.22 能力級買 vs 建：feature-as-a-service 與 BaaS bundle 選型" data-link-desc="在交付形態決定整個系統要不要自建之後、逐能力判斷該外包還是自建：辨識 managed 基礎設施、feature SaaS 與 BaaS bundle 三種外包深度、no-code 到 dev-tool 的服務光譜、買 vs 建判準與權重浮動、整合接縫與遷出代價">0.22</a></li>
</ul>
<h2 id="容量規劃要點">容量規劃要點</h2>
<p><strong>1. access pattern 先於 document 結構</strong>：</p>
<ul>
<li>列出 application 對資料的所有讀寫路徑、再設計 collection / document 形狀</li>
<li>access pattern 沒想清楚就建模，後面報表查不出來要重做</li>
</ul>
<p><strong>2. 反正規化換查詢效率</strong>：</p>
<ul>
<li>為了避免跨 collection 多次查詢，常把關聯資料冗餘寫進同一 document</li>
<li>代價是寫入時要維護多份副本的一致性，對應 <a href="/blog/backend/01-database/reconciliation-data-repair/" data-link-title="1.9 Reconciliation 與 Data Repair" data-link-desc="資料不一致的分類、偵測模式、修復策略、audit trail、跟 backup / PITR 整合">1.9 Reconciliation</a></li>
</ul>
<p><strong>3. index 與寫入成本綁定</strong>：</p>
<ul>
<li>複合查詢要先建 composite index、否則查詢直接失敗</li>
<li>每個 index 增加寫入維護成本，移除用不到的 index 是容量優化的一環</li>
</ul>
<p><strong>4. 高頻寫入用 distributed counter</strong>：</p>
<ul>
<li>單一 document 撞到 contention 上限時，把計數拆成多個 shard document 再彙總</li>
</ul>
<p><strong>5. 成本以 document 數計，不以掃描量計</strong>：</p>
<ul>
<li>容量估算要算「每個畫面 / API 觸發幾次 read」、乘上日活與頻率</li>
<li>把熱讀取移到 <a href="/blog/backend/02-cache-redis/cache-aside/" data-link-title="2.2 cache aside 與失效策略" data-link-desc="整理 read-through 思路、cache miss 與 invalidation">應用層快取</a> 是壓低 read 計費的主要手段</li>
</ul>
<h2 id="常見陷阱">常見陷阱</h2>
<ul>
<li><strong>把 Firestore 當關聯式用</strong>：規劃了一堆需要 JOIN 的 collection、上線後跨集合查詢全靠 client 自己組、latency 與 read 成本爆炸</li>
<li><strong>報表需求到了才發現查不出來</strong>：老闆要月報、Firestore 沒有 aggregation pipeline、被迫臨時搭資料複製管線</li>
<li><strong>Security Rules 長到沒人敢改</strong>：授權全寫在規則 DSL、沒有版本控制與測試、變更時靠人工推敲</li>
<li><strong>單 document 當高頻計數器</strong>：直播按讚 / 即時計數寫爆單一 document 的 contention 上限</li>
<li><strong>忽略 read 計費規模</strong>：list 畫面一次回上千筆、每次重整都計上千次 read、帳單月底才浮現</li>
</ul>
<h2 id="deep-article-章節群">Deep article 章節群</h2>
<p>Firestore overview 負責第一輪服務判斷；vendor 特有機制的設定、踩坑與容量規劃拆成 deep article。下表是目前已建立的實作層教材，讀法是先讀 overview 判斷服務適配，再按撞到的壓力選 deep article。</p>
<table>
  <thead>
      <tr>
          <th>機制</th>
          <th>文件</th>
          <th>教學責任</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>授權控制面</td>
          <td><a href="/blog/backend/01-database/vendors/firestore/security-rules-authz-modeling/" data-link-title="Firestore Security Rules 授權建模與可測試化：把規則當程式碼治理" data-link-desc="Firestore client 直連模型把整個授權控制面壓在 Security Rules 這套 DSL 裡；本文展開規則的求值模型、把授權拆成可組合 function、用 emulator 寫單元測試、五個把規則寫成資安漏洞的 production 踩坑，以及規則複雜度撞牆時把授權拉回後端的邊界">Security Rules 授權建模與可測試化</a></td>
          <td>規則求值模型、可組合 function、emulator 單元測試、把規則當程式碼治理</td>
      </tr>
      <tr>
          <td>高頻寫入</td>
          <td><a href="/blog/backend/01-database/vendors/firestore/distributed-counter-high-frequency-write/" data-link-title="Firestore 高頻寫入與 distributed counter：單 document contention 邊界與分片計數" data-link-desc="Firestore 單一 document 有持續寫入的軟上限、高頻計數寫爆 contention 是常見事故；本文展開寫入 contention 的成因、distributed counter 分片計數的實作與讀取彙總、shard 數量與讀寫成本的取捨、五個高頻寫入踩坑，以及計數需求超過分片能處理時改走外部聚合的邊界">高頻寫入與 distributed counter</a></td>
          <td>單 document contention 邊界、分片計數、shard 數與讀寫成本取捨</td>
      </tr>
      <tr>
          <td>資料建模</td>
          <td><a href="/blog/backend/01-database/vendors/firestore/denormalization-fanout-consistency/" data-link-title="Firestore document 反正規化與一致性維護：fan-out write、副本同步與資料修復" data-link-desc="Firestore 沒有 JOIN，查詢能力逼著把關聯資料反正規化複製多份；本文展開反正規化的建模決策、fan-out write 維護副本一致、batch 與 transaction 的選擇、五個副本不一致的 production 踩坑，以及反正規化複雜到該回關聯式的邊界">document 反正規化與一致性維護</a></td>
          <td>反正規化決策、fan-out write、副本同步、不一致修復</td>
      </tr>
      <tr>
          <td>即時同步</td>
          <td><a href="/blog/backend/01-database/vendors/firestore/realtime-listener-fanout-cost/" data-link-title="Firestore realtime listener 扇出與成本：snapshot 訂閱、re-read 計費與連線規模" data-link-desc="Firestore 的 snapshot listener 提供即時同步、但訂閱的扇出、查詢結果變動的 re-read 計費與連線數會在規模下變成成本與效能瓶頸；本文展開 listener 的推送模型、訂閱範圍設計、五個 realtime 成本踩坑，以及即時需求超過 listener 該換推送架構的邊界">realtime listener 扇出與成本</a></td>
          <td>snapshot 推送模型、訂閱範圍設計、re-read 計費、連線規模</td>
      </tr>
  </tbody>
</table>
<p>讀法路由：撞到資料外洩 / 越權，讀 Security Rules；撞到熱門事件寫爆計數，讀 distributed counter；改一筆要連動改一千筆，讀反正規化；即時功能帳單失控，讀 realtime listener。撞到報表 / 成本 / 授權整體性的牆，走 <a href="/blog/backend/01-database/vendors/firestore/migrate-to-relational/" data-link-title="從 Firestore 遷往自建 relational：撞牆驅動的 Type E 重建模、存取模型反轉與並行期" data-link-desc="Firestore → 自建後端 &#43; relational 不是匯資料而是反轉存取模型：client 直連變 API 中介、Security Rules 授權變後端授權、document 反正規化變正規 schema、realtime listener 與 offline 同步要重建；本文走 Type E paradigm shift 結構、展開為何字面遷移不成立、哪些該遷哪些先留、dual-write &#43; shadow read 階段化與遷出代價判讀">遷往自建 relational</a>。</p>
<h2 id="hands-on-操作演練">Hands-on 操作演練</h2>
<p>deep article 講機制判讀，<a href="/blog/backend/01-database/vendors/firestore/hands-on/" data-link-title="Firestore Hands-on 操作路線" data-link-desc="用 Firebase Emulator Suite 在本地演練 Firestore：emulator quickstart、Security Rules 單元測試、distributed counter 分片計數，全程零雲端成本、可重跑、產出可驗證 artifact">Hands-on 操作路線</a> 把機制轉成可在本地 <a href="https://firebase.google.com/docs/emulator-suite">Firebase Emulator</a> 跑的演練——零雲端成本、可重跑、產出可驗證 artifact。三個 lab：<a href="/blog/backend/01-database/vendors/firestore/hands-on/local-emulator-quickstart/" data-link-title="Firestore Local Emulator Quickstart" data-link-desc="用 Firebase CLI 啟動 Firestore emulator、寫 firestore.rules、用 admin SDK seed 資料、跑 query baseline 與 cleanup，建立後續 Security Rules 與 distributed counter lab 共用的本地環境">emulator quickstart</a>（建立共用環境）、<a href="/blog/backend/01-database/vendors/firestore/hands-on/security-rules-test-lab/" data-link-title="Firestore Security Rules Test Lab" data-link-desc="用 @firebase/rules-unit-testing 在 emulator 上把 Security Rules 寫成自動化測試：放行 / 越權拒絕 / 未登入拒絕 / 欄位竄改拒絕四類斷言、firebase emulators:exec 在 CI 跑、把規則測試接進 release gate">Security Rules test lab</a>（規則自動化測試 + 接 release gate）、<a href="/blog/backend/01-database/vendors/firestore/hands-on/distributed-counter-lab/" data-link-title="Firestore Distributed Counter Lab" data-link-desc="在 emulator 上實作 distributed counter：建立 N 個 shard、隨機分片寫入、觀察 shard 分佈是否均勻、讀取彙總驗證總和正確，並說明 contention 本身是 emulator 不模擬的 production 特性">distributed counter lab</a>（分片計數機制驗證）。lab 全程標明 emulator 驗得了什麼（功能行為、規則求值）、驗不了什麼（計費、寫入軟上限要回雲端）。</p>
<h2 id="已知-limitation-與後續路由">已知 limitation 與後續路由</h2>
<p>Firestore overview 完成服務判斷、資料形狀、查詢邊界與替代路由；deep article 章節群覆蓋授權、高頻寫入、反正規化與即時同步四個機制；hands-on 章節群提供 emulator 演練。後續可補的方向：offline persistence 的衝突解決深入、realtime listener 在雲端的成本量測 lab（emulator 不計費、要在雲端 staging 跑）。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>完整 T1 對照：<a href="/blog/backend/01-database/vendors/" data-link-title="資料庫 Vendor 清單" data-link-desc="規劃 SQL、managed SQL、document、KV 與 distributed SQL 的服務頁撰寫順序與教學大綱">01-database vendors index</a></li>
<li>同類對比：<a href="/blog/backend/01-database/vendors/mongodb/" data-link-title="MongoDB" data-link-desc="Document database 代表、Atlas managed、跨雲可用、許多大規模平台從 MongoDB 起家">MongoDB vendor</a>（彈性查詢 document）/ <a href="/blog/backend/01-database/vendors/dynamodb/" data-link-title="DynamoDB" data-link-desc="AWS managed key-value、partition-based scaling、9000 萬 RPS sustained 實戰證據">DynamoDB vendor</a>（access-pattern-first KV）/ <a href="/blog/backend/01-database/vendors/db3-vendor-selection/" data-link-title="DB3 Vendor Selection：document / KV / multi-model 三方選型 &#43; workload shape 前置判讀" data-link-desc="MongoDB / DynamoDB / Cosmos DB 三家 NoSQL 選型 entry point：workload shape × access pattern × consistency 三軸前置判讀、migration path 三型、federated DB 視角、三 vendor 對比 10 軸">db3 vendor selection</a>（document / KV / multi-model 三方選型）</li>
<li>遷出方向：<a href="/blog/backend/01-database/vendors/firestore/migrate-to-relational/" data-link-title="從 Firestore 遷往自建 relational：撞牆驅動的 Type E 重建模、存取模型反轉與並行期" data-link-desc="Firestore → 自建後端 &#43; relational 不是匯資料而是反轉存取模型：client 直連變 API 中介、Security Rules 授權變後端授權、document 反正規化變正規 schema、realtime listener 與 offline 同步要重建；本文走 Type E paradigm shift 結構、展開為何字面遷移不成立、哪些該遷哪些先留、dual-write &#43; shadow read 階段化與遷出代價判讀">Firestore → 自建 relational</a>（撞到報表 / 成本 / 授權牆後的 Type E 重建模 playbook）</li>
<li>操作演練：<a href="/blog/backend/01-database/vendors/firestore/hands-on/" data-link-title="Firestore Hands-on 操作路線" data-link-desc="用 Firebase Emulator Suite 在本地演練 Firestore：emulator quickstart、Security Rules 單元測試、distributed counter 分片計數，全程零雲端成本、可重跑、產出可驗證 artifact">Firestore Hands-on</a>（emulator quickstart、Security Rules 測試、distributed counter lab）</li>
<li>容量背景：<a href="/blog/backend/01-database/kv-document-capacity-planning/" data-link-title="1.10 KV / Document DB 容量規劃" data-link-desc="DynamoDB / Cosmos DB / Bigtable / MongoDB 等 KV / Document DB 的容量設計、partition key 取捨、capacity mode 選擇">1.10 KV / Document DB 容量規劃</a></li>
<li>選型上層：<a href="/blog/backend/00-service-selection/delivery-mode-selection/" data-link-title="0.21 交付形態選型：從全託管到自建的光譜與邊界" data-link-desc="在進入資料庫、快取與部署選型之前、先判斷服務該用託管平台（Wix / Shopify / Google Sites）、辦公生態自動化（Apps Script）、BaaS（Firebase）、半託管 CMS（WordPress）還是自建、並為日後遷往自建保留可遷出路徑">0.21 交付形態選型</a> / <a href="/blog/backend/00-service-selection/capability-buy-vs-build/" data-link-title="0.22 能力級買 vs 建：feature-as-a-service 與 BaaS bundle 選型" data-link-desc="在交付形態決定整個系統要不要自建之後、逐能力判斷該外包還是自建：辨識 managed 基礎設施、feature SaaS 與 BaaS bundle 三種外包深度、no-code 到 dev-tool 的服務光譜、買 vs 建判準與權重浮動、整合接縫與遷出代價">0.22 能力級買 vs 建</a> / <a href="/blog/backend/knowledge-cards/baas/" data-link-title="BaaS（Backend as a Service）" data-link-desc="說明把認證、資料庫、檔案儲存、推播打包成現成模組、由前端 SDK 直連的後端交付形態">BaaS 知識卡</a></li>
<li>從託管平台遷出的資產線盤點：<a href="/blog/backend/10-system-evolution/managed-platform-exit/" data-link-title="10.3 託管形態遷出：資產線盤點與並行期執行" data-link-desc="0.21 升級自建 tripwire 觸發後的執行劇本 — 把遷出拆成資料、身分、流量、整合各自的可攜性與斷點、設計舊平台與新系統的並行期與回切窗口、用部分遷出作為中繼形態">10.3 託管形態遷出</a></li>
<li>官方：<a href="https://firebase.google.com/docs/firestore">Firestore documentation</a>、<a href="https://firebase.google.com/docs/firestore/best-practices">Firestore best practices</a>、<a href="https://firebase.google.com/docs/firestore/pricing">Firestore pricing</a></li>
</ul>
]]></content:encoded></item><item><title>Let's Encrypt</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/letsencrypt/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/letsencrypt/</guid><description>&lt;p>Let&amp;rsquo;s Encrypt 是免費 + 自動化的公共 ACME CA（Certificate Authority）、由 Internet Security Research Group (ISRG) 營運、簽發 DV（Domain Validation）等級的 public TLS cert。它的核心設計選擇是 &lt;em>只發 90 天 TTL 的 cert + 完全自動化的 ACME protocol&lt;/em>、把人工管理選項從工程實務中拿掉、強迫 cert lifecycle 走機器化路線。今天大多數 public-facing web service 的 TLS cert 都直接或間接從 Let&amp;rsquo;s Encrypt 來、是現代 Web 的事實基礎設施之一。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Let&amp;rsquo;s Encrypt 的角色是 &lt;em>跨雲、跨平台、跨組織規模&lt;/em> 的公共 DV cert 來源。對於需要 public TLS cert 又不被特定雲廠綁定的場景（on-prem、edge node、跨雲 service、自架 CDN origin、開源專案）、Let&amp;rsquo;s Encrypt 是預設選項。它解決的問題不是「能不能拿到 cert」、而是「能不能 &lt;em>無人值守&lt;/em> 持續拿到 cert」— ACME protocol 把申請、驗證、issue、renew、revoke 全部標準化、ACME client（&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/cert-manager/" data-link-title="cert-manager" data-link-desc="K8s 原生 certificate lifecycle automation、支援 Let&amp;#39;s Encrypt / Vault PKI / Venafi 等多 issuer、auto-renewal &amp;#43; Challenge solver">cert-manager&lt;/a> / certbot / acme.sh / Caddy / Traefik）負責 client 端執行。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-acm/" data-link-title="AWS ACM" data-link-desc="AWS-managed certificate provisioning、DNS validation &amp;#43; auto-renewal、整合 ELB / CloudFront / API Gateway、Private CA 後端">AWS ACM&lt;/a> 比、Let&amp;rsquo;s Encrypt 跨雲跨平台、ACM 限 AWS-managed service（ALB / CloudFront / API Gateway）內使用、export 出去要另談；ACM Private CA 又是另一個產品。跟商業 CA（DigiCert / Sectigo / Entrust）比、商業 CA 提供 OV（Organization Validation）/ EV（Extended Validation）cert、cert 內含經過驗證的組織資訊、金融網站或法遵需求會用；Let&amp;rsquo;s Encrypt 只發 DV cert、不驗證組織身份。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault PKI&lt;/a> 比、Vault PKI 是 &lt;em>internal CA&lt;/em>（不被公共瀏覽器信任、適合 internal mTLS / workload identity）、Let&amp;rsquo;s Encrypt 是 &lt;em>public CA&lt;/em>（瀏覽器信任、適合 public-facing service）— 兩個是互補關係、不是替代。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本頁、讀者能判斷：&lt;/p>
&lt;ol>
&lt;li>哪些 cert 需求適合 Let&amp;rsquo;s Encrypt（public-facing、DV、跨平台）、哪些該走 ACM / 商業 CA / Vault PKI&lt;/li>
&lt;li>ACME protocol 的四個 first-class concept（Account / Order / Authorization / Challenge）跟自己選的 ACME client 怎麼對應&lt;/li>
&lt;li>Rate limit 是 &lt;em>硬限制&lt;/em>、SaaS 多 tenant 場景如何規劃（wildcard / SAN / rate limit exemption）&lt;/li>
&lt;li>90 天 TTL + CT log 公開 + revocation 弱化 在 production 設計上的影響&lt;/li>
&lt;/ol>
&lt;h2 id="最短判讀路徑">最短判讀路徑&lt;/h2>
&lt;p>判斷 Let&amp;rsquo;s Encrypt 使用是否健康、最少看四件事：&lt;/p></description><content:encoded><![CDATA[<p>Let&rsquo;s Encrypt 是免費 + 自動化的公共 ACME CA（Certificate Authority）、由 Internet Security Research Group (ISRG) 營運、簽發 DV（Domain Validation）等級的 public TLS cert。它的核心設計選擇是 <em>只發 90 天 TTL 的 cert + 完全自動化的 ACME protocol</em>、把人工管理選項從工程實務中拿掉、強迫 cert lifecycle 走機器化路線。今天大多數 public-facing web service 的 TLS cert 都直接或間接從 Let&rsquo;s Encrypt 來、是現代 Web 的事實基礎設施之一。</p>
<h2 id="服務定位">服務定位</h2>
<p>Let&rsquo;s Encrypt 的角色是 <em>跨雲、跨平台、跨組織規模</em> 的公共 DV cert 來源。對於需要 public TLS cert 又不被特定雲廠綁定的場景（on-prem、edge node、跨雲 service、自架 CDN origin、開源專案）、Let&rsquo;s Encrypt 是預設選項。它解決的問題不是「能不能拿到 cert」、而是「能不能 <em>無人值守</em> 持續拿到 cert」— ACME protocol 把申請、驗證、issue、renew、revoke 全部標準化、ACME client（<a href="/blog/backend/07-security-data-protection/vendors/cert-manager/" data-link-title="cert-manager" data-link-desc="K8s 原生 certificate lifecycle automation、支援 Let&#39;s Encrypt / Vault PKI / Venafi 等多 issuer、auto-renewal &#43; Challenge solver">cert-manager</a> / certbot / acme.sh / Caddy / Traefik）負責 client 端執行。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/aws-acm/" data-link-title="AWS ACM" data-link-desc="AWS-managed certificate provisioning、DNS validation &#43; auto-renewal、整合 ELB / CloudFront / API Gateway、Private CA 後端">AWS ACM</a> 比、Let&rsquo;s Encrypt 跨雲跨平台、ACM 限 AWS-managed service（ALB / CloudFront / API Gateway）內使用、export 出去要另談；ACM Private CA 又是另一個產品。跟商業 CA（DigiCert / Sectigo / Entrust）比、商業 CA 提供 OV（Organization Validation）/ EV（Extended Validation）cert、cert 內含經過驗證的組織資訊、金融網站或法遵需求會用；Let&rsquo;s Encrypt 只發 DV cert、不驗證組織身份。跟 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault PKI</a> 比、Vault PKI 是 <em>internal CA</em>（不被公共瀏覽器信任、適合 internal mTLS / workload identity）、Let&rsquo;s Encrypt 是 <em>public CA</em>（瀏覽器信任、適合 public-facing service）— 兩個是互補關係、不是替代。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>哪些 cert 需求適合 Let&rsquo;s Encrypt（public-facing、DV、跨平台）、哪些該走 ACM / 商業 CA / Vault PKI</li>
<li>ACME protocol 的四個 first-class concept（Account / Order / Authorization / Challenge）跟自己選的 ACME client 怎麼對應</li>
<li>Rate limit 是 <em>硬限制</em>、SaaS 多 tenant 場景如何規劃（wildcard / SAN / rate limit exemption）</li>
<li>90 天 TTL + CT log 公開 + revocation 弱化 在 production 設計上的影響</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Let&rsquo;s Encrypt 使用是否健康、最少看四件事：</p>
<ul>
<li><strong>Account 管理</strong>：ACME account 是 <em>cross-domain</em> 的身份、同一個 account 可以申請組織所有 domain 的 cert — account key 外洩等於 attacker 可以對所有 domain 發 cert；account key 是否離線備份、是否跟 ACME client 用獨立 key（不重用 server key）</li>
<li><strong>Challenge 選擇</strong>：HTTP-01 需要 port 80 reachable、適合單機 + 直接 internet 暴露；DNS-01 需要 DNS API access、適合 wildcard + 私有環境；TLS-ALPN-01 走 443、適合 port 80 不可用的場景 — Challenge 選錯會卡在 validation 階段</li>
<li><strong>Rate limit 規劃</strong>：50 cert/week per registered domain、5 duplicate cert/week — 大型 SaaS 服務多 customer subdomain 容易撞牆、要先估 cert 量、再決定 wildcard / SAN / rate limit 申請</li>
<li><strong>Revocation 流程</strong>：cert 被洩漏怎麼辦 — revoke 不是 fleet-wide invalidation、real-world 失效靠 <em>rotate + 短 TTL</em>；revocation 程序是否寫入 runbook、舊 cert 是否在所有 endpoint 確實 retire</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/07-security-data-protection/transport-trust-and-certificate-lifecycle/" data-link-title="7.5 傳輸信任與憑證生命週期" data-link-desc="以問題驅動方式整理傳輸信任鏈、會話完整性與憑證節奏">Transport Trust and Certificate Lifecycle</a> 跟 <a href="/blog/backend/07-security-data-protection/credential-rotation-scoped-evidence/" data-link-title="7.27 Credential Rotation with Scoped Evidence 實作示範" data-link-desc="以 webhook/API credential 輪替示範 scope map、證據欄位與回退窗口如何一起設計。">Credential Rotation Scoped Evidence</a> 邊界的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>ACME client 選擇</strong>：<a href="/blog/backend/07-security-data-protection/vendors/cert-manager/" data-link-title="cert-manager" data-link-desc="K8s 原生 certificate lifecycle automation、支援 Let&#39;s Encrypt / Vault PKI / Venafi 等多 issuer、auto-renewal &#43; Challenge solver">cert-manager</a> 適合 K8s 環境、Ingress / Gateway / Certificate CRD 自動化；certbot 適合單機 / VM、官方參考實作；acme.sh 是 pure shell、嵌入既有 deployment script 容易；Caddy / Traefik 把 ACME 內建進 reverse proxy、零設定拿 cert。client 端的選擇決定 <em>cert 怎麼存、怎麼 deploy 到 termination point</em>、Let&rsquo;s Encrypt 自己不管這層。</p>
<p><strong>ACME Account（cross-domain identity）</strong>：Account 是 ACME server 認可的身份、用一把 account key（不同於 cert private key）簽 ACME request。同一個 account 可以申請 <em>組織所有 domain</em> 的 cert — 安全意義是 account key 外洩 = attacker 對所有 domain 都能 issue cert。Production 場景把 account key 視為跟 root signing key 同等級的 secret、離線備份、跟日常 ACME client 用獨立 key。</p>
<p><strong>Challenge 選擇 — HTTP-01 / DNS-01 / TLS-ALPN-01</strong>：HTTP-01 在 <code>/.well-known/acme-challenge/&lt;token&gt;</code> 放 response、Let&rsquo;s Encrypt 從 port 80 拉、適合單機 + 直接 internet 暴露；DNS-01 在 <code>_acme-challenge.&lt;domain&gt;</code> 放 TXT record、適合 wildcard cert（<code>*.example.com</code> 必須 DNS-01、HTTP-01 不行）跟私有環境（不需要 port 80 開放）；TLS-ALPN-01 走 port 443、用 special ALPN extension 回 challenge、適合 port 80 被擋的場景。Wildcard cert 強制 DNS-01 是 Let&rsquo;s Encrypt 政策、不能用 HTTP-01 繞過。</p>
<p><strong>Rate limit 是硬限制</strong>：50 cert/week per registered domain（包含 SAN 在內）、5 duplicate cert/week（同樣 SAN 組合）、300 new orders/3 hours per account、5 failed validation/hour。大型 SaaS 對 N 個 customer subdomain 發 cert 容易撞牆 — 解法有三：用 wildcard cert 把多 subdomain 合一張（單張 cert 服務無限 subdomain）、用 SAN cert 把多個 subdomain 寫進同一張 cert、申請 rate limit 上限提高（<a href="https://isrg.formstack.com/forms/rate_limit_adjustment_request">官方表單</a>）。撞 rate limit 後該 domain 整個 week 不能發新 cert、是 production outage 等級。</p>
<p><strong>Staging environment 必用於測試</strong>：<code>acme-staging-v02.api.letsencrypt.org</code> 是 Let&rsquo;s Encrypt 的測試 endpoint、cert 不被瀏覽器信任、但 <em>rate limit 寬鬆很多</em>（30000 cert/week / 60 duplicate cert/week）。debug ACME client 設定、新 deploy pipeline、CI 跑 cert renewal test 都應該先指 staging、確認 OK 再切 production endpoint。直接在 production 試錯撞 rate limit 是常見事故。</p>
<p><strong>90 天 TTL + 60 天 renew cadence</strong>：Let&rsquo;s Encrypt cert 固定 90 天 TTL、ACME client convention 是 <em>過 60 天就開始 renew</em>、留 30 天 buffer 給 retry。90 天是 <em>設計選擇</em>、不是技術限制 — 短 TTL 強迫自動化、把「過期前手動處理」這個失敗模式從設計中拿掉。如果你的 cert renewal 還需要人介入、表示 ACME client / deployment pipeline / monitoring 哪邊沒做好、要在 60 天 buffer 內修。</p>
<p><strong>CT log 公開可查</strong>：Let&rsquo;s Encrypt cert 都會進 Certificate Transparency log（CT log）、可以用 <a href="https://crt.sh">crt.sh</a> 查任何 domain 的歷史 cert。對 production 意義有兩面：blue team 可以監控自家 domain 的 unexpected cert（attacker 用相似 domain 釣魚會留痕）；red team 可以查 target 公司新出現的 internal hostname（cert 上的 SAN 等於公開的 service inventory）。對 <em>internal-only</em> hostname、不要用 Let&rsquo;s Encrypt cert、否則 SAN 變成 recon 資料源 — 內部服務走 Vault PKI / 私有 CA。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Let&rsquo;s Encrypt</th>
          <th>AWS ACM</th>
          <th>商業 CA（DigiCert / Sectigo）</th>
          <th>Vault PKI（internal CA）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>信任範圍</td>
          <td>Public（公共瀏覽器信任）</td>
          <td>Public（公共瀏覽器信任）</td>
          <td>Public（公共瀏覽器信任）</td>
          <td>Internal（需要客戶端裝 CA cert）</td>
      </tr>
      <tr>
          <td>部署範圍</td>
          <td>跨雲、跨平台、on-prem</td>
          <td>限 AWS-managed service（ALB / CF / APIGW）</td>
          <td>跨雲、跨平台</td>
          <td>自管、跨雲皆可</td>
      </tr>
      <tr>
          <td>Cert 等級</td>
          <td>DV（Domain Validation）</td>
          <td>DV（ACM）/ Private CA 任意</td>
          <td>DV / OV / EV</td>
          <td>自定義（內部信任）</td>
      </tr>
      <tr>
          <td>費用</td>
          <td>免費</td>
          <td>免費（ACM public）/ Private CA 收費</td>
          <td>收費（DV / OV / EV 各價位）</td>
          <td>自管成本</td>
      </tr>
      <tr>
          <td>自動化</td>
          <td>ACME protocol 標準化</td>
          <td>ACM 自動 renew（限 AWS-managed service）</td>
          <td>多數需手動 / API 申請、自動化弱</td>
          <td>自管 + ACME server 可選</td>
      </tr>
      <tr>
          <td>TTL</td>
          <td>90 天（硬性）</td>
          <td>13 個月（AWS rotate）</td>
          <td>1-2 年</td>
          <td>自訂</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>public-facing、跨雲、open source、SaaS</td>
          <td>AWS-only + ALB/CloudFront 內</td>
          <td>金融、政府、需要 EV 顯示組織</td>
          <td>internal mTLS、workload identity、企業內部 service</td>
      </tr>
      <tr>
          <td>不適合場景</td>
          <td>internal mTLS、EV cert、cert 內需含組織</td>
          <td>跨雲、export 出 AWS</td>
          <td>需要快速自動化、預算敏感</td>
          <td>public-facing、不能要求客戶端裝 CA</td>
      </tr>
  </tbody>
</table>
<p>選 Let&rsquo;s Encrypt 的核心訴求：<em>public-facing + DV 等級夠用 + 跨平台 + 需要自動化</em>。需要 EV cert 走商業 CA、需要 internal mTLS 走 Vault PKI、AWS-only + 留在 ALB / CloudFront 內走 ACM 更省事。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Rate limit 規劃跟 SaaS 多 tenant</strong>：N 個 customer subdomain 場景下、單 domain 50 cert/week 很容易撞牆。設計選項：(1) wildcard cert（<code>*.app.example.com</code>）一張覆蓋無限 subdomain、但 wildcard cert 不能保護 nested subdomain（<code>*.app.example.com</code> 不蓋 <code>foo.bar.app.example.com</code>）；(2) SAN cert 把多個 subdomain 寫進同一張 cert（單張最多 100 個 SAN）、適合 customer 數固定、新增不頻繁的場景；(3) 申請 rate limit 上限提高、production scale SaaS 走這條；(4) cert reuse — 同樣 SAN 組合在 5 duplicate cert/week 內可 reuse、不重發。</p>
<p><strong>跟 cert-manager + DNS-01 整合</strong>：production K8s 環境最常見組合是 cert-manager + Let&rsquo;s Encrypt + DNS-01、DNS provider 走 Route53 / Cloud DNS / Cloudflare。cert-manager 用 ClusterIssuer 設定 Let&rsquo;s Encrypt account + DNS solver、Certificate CRD 宣告需要的 cert、cert-manager 自動完成 ACME flow。優勢是 <em>wildcard cert 可用</em>（DNS-01 不受 HTTP-01 的 port 80 限制）、跨 cluster 可標準化、cert renewal 進 K8s event stream 容易監控。</p>
<p><strong>ACME profiles（client-specific behavior）</strong>：Let&rsquo;s Encrypt 2024 開始提供 ACME profile 機制、允許 client 選擇 cert 屬性（如 short-lived 6 天 cert vs standard 90 天）。short-lived cert 適合機器 workload、進一步壓縮 revocation 缺陷的影響窗口；普通 web service 用 standard profile 即可。Profile 是 opt-in、ACME client 要支援。</p>
<p><strong>跨 ACME CA fallback</strong>：Let&rsquo;s Encrypt 不是唯一 ACME CA — ZeroSSL、Buypass、Google Trust Services 都提供 ACME endpoint。production 建議 ACME client 設兩個 issuer（Let&rsquo;s Encrypt primary + ZeroSSL / Buypass secondary）、Let&rsquo;s Encrypt 出事（rate limit 撞牆、AWS outage 影響 challenge 驗證、ISRG 服務中斷）時可以 fallback、不會 cert 全停。cert-manager 用兩個 ClusterIssuer 即可、application 端零感知。</p>
<p><strong>Revocation 的弱化現實</strong>：cert 可以 revoke、但實際失效路徑薄弱 — CRL（Certificate Revocation List）跟 OCSP（Online Certificate Status Protocol）更新有延遲、且大多數 client（瀏覽器、API client）不會主動檢查 revocation 狀態（soft-fail：查不到就放行）。real-world 的 cert 失效機制其實是 <em>短 TTL + rotate</em>、不是 revocation API。設計時不要寄望 revoke 後 attacker 拿到的 cert 就無效 — rotate 出新 cert + 在所有 endpoint deploy 新 cert + 觀察舊 cert traffic 歸零、才算真正失效。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>ACME challenge 失敗</strong>：HTTP-01 拉不到 <code>/.well-known/acme-challenge/&lt;token&gt;</code>、檢查 port 80 reachability、firewall、CDN 是否擋；DNS-01 TXT record 沒生效、檢查 DNS provider API permission、TXT TTL 是否設太長</li>
<li><strong>撞 rate limit</strong>：50 cert/week per registered domain 撞牆、整個 week 不能發新 cert — production 必須先 <em>staging 測完</em> 再切 production、cert reuse 機制要開（同 SAN 組合不重發）、長期解走 wildcard / SAN consolidation / rate limit exemption</li>
<li><strong>Renewal 沒在 60 天前開始</strong>：cert 過期前才 renew、撞到 ACME server 暫時不可用會直接過期 — ACME client 設 60 天 renew threshold、cert expiry 30 天前 alert 給 oncall</li>
<li><strong>Account key 沒備份</strong>：account key 弄丟、可以重新註冊但 <em>舊 cert 的 revocation 權限沒了</em>（除非用 cert 私鑰 revoke）— account key 跟 root signing key 同等級保護、離線備份</li>
<li><strong>CT log 暴露 internal hostname</strong>：Let&rsquo;s Encrypt cert 進 CT log、internal-only hostname 的 SAN 變 recon 資料源 — internal service 不用 Let&rsquo;s Encrypt、改 Vault PKI / 私有 CA</li>
<li><strong>Wildcard cert 用 HTTP-01</strong>：<code>*.example.com</code> 申請失敗、Let&rsquo;s Encrypt 政策強制 wildcard 走 DNS-01 — 切到 DNS-01 solver、設定 DNS provider API access</li>
<li><strong>Cert 出事 revoke 後 attacker 還能用</strong>：revocation 不是 fleet-wide invalidation、CRL/OCSP 多數 client 不檢查 — 真正失效靠 rotate + 觀察舊 cert traffic 歸零、不是 revoke API</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>AWS-only + 留在 ALB / CloudFront 內</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/aws-acm/" data-link-title="AWS ACM" data-link-desc="AWS-managed certificate provisioning、DNS validation &#43; auto-renewal、整合 ELB / CloudFront / API Gateway、Private CA 後端">AWS ACM</a></td>
      </tr>
      <tr>
          <td>需要 OV / EV cert（cert 含組織資訊）</td>
          <td>商業 CA（DigiCert / Sectigo / Entrust）</td>
      </tr>
      <tr>
          <td>Internal mTLS / workload identity</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault PKI</a> / <a href="/blog/backend/07-security-data-protection/vendors/spire/" data-link-title="SPIRE" data-link-desc="SPIFFE Runtime Environment、attested workload identity、short-lived SVID &#43; Trust Bundle、跨組織 federation">SPIRE</a></td>
      </tr>
      <tr>
          <td>K8s workload cert 自動化（用 LE 當源）</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/cert-manager/" data-link-title="cert-manager" data-link-desc="K8s 原生 certificate lifecycle automation、支援 Let&#39;s Encrypt / Vault PKI / Venafi 等多 issuer、auto-renewal &#43; Challenge solver">cert-manager</a></td>
      </tr>
      <tr>
          <td>Cert lifecycle 治理（跨 vendor 通則）</td>
          <td><a href="/blog/backend/07-security-data-protection/transport-trust-and-certificate-lifecycle/" data-link-title="7.5 傳輸信任與憑證生命週期" data-link-desc="以問題驅動方式整理傳輸信任鏈、會話完整性與憑證節奏">7.4 Transport Trust and Certificate Lifecycle</a></td>
      </tr>
      <tr>
          <td>Cert rotation 證據鏈</td>
          <td><a href="/blog/backend/07-security-data-protection/credential-rotation-scoped-evidence/" data-link-title="7.27 Credential Rotation with Scoped Evidence 實作示範" data-link-desc="以 webhook/API credential 輪替示範 scope map、證據欄位與回退窗口如何一起設計。">7.5 Credential Rotation Scoped Evidence</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>ACME protocol RFC 8555 完整規格逐條解讀</li>
<li>每個 ACME client（certbot / cert-manager / acme.sh / Caddy / Traefik）的完整設定教學</li>
<li>Let&rsquo;s Encrypt 內部 CA infrastructure 跟 ISRG governance 細節</li>
<li>CT log 內部結構跟 SCT（Signed Certificate Timestamp）驗證流程</li>
<li>DNS provider 的 API 認證設定（Route53 IAM / Cloud DNS service account / Cloudflare API token）</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>Let&rsquo;s Encrypt 在 07 案例庫沒有直接 vendor-level 事件、以下案例採對照引用：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 Let&rsquo;s Encrypt 的關係（對照）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/transport-trust-and-certificate-lifecycle/" data-link-title="7.5 傳輸信任與憑證生命週期" data-link-desc="以問題驅動方式整理傳輸信任鏈、會話完整性與憑證節奏">Transport Trust and Certificate Lifecycle (section)</a></td>
          <td>Let&rsquo;s Encrypt 90 天 TTL + 強制 ACME 自動化、把人工依賴從 cert lifecycle 設計中拿掉、是 <em>forcing function 級別</em> 的治理選擇</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/credential-rotation-scoped-evidence/" data-link-title="7.27 Credential Rotation with Scoped Evidence 實作示範" data-link-desc="以 webhook/API credential 輪替示範 scope map、證據欄位與回退窗口如何一起設計。">Credential Rotation Scoped Evidence (section)</a></td>
          <td>Let&rsquo;s Encrypt 沒提供 fleet-wide revocation API、cert 出事後客戶側自己負責 fleet update + session invalidation、是 scope map 必要的典型情境</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/edge-exposure/citrix-bleed-2023-session-hijack/" data-link-title="7.R7.3.3 Citrix Bleed 2023：會話被劫持與重放風險" data-link-desc="邊界設備會話資料外洩後，如何演變成帳號與服務風險">Citrix Bleed 2023 Session Hijack</a></td>
          <td>對照啟示 — cert rotation 跟 session invalidation 是兩件事、Let&rsquo;s Encrypt cert renew 不會 invalidate 既有 TLS session 跟 application-layer session、要分別處理</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/cases/failure-credential-rotation-without-scope/" data-link-title="7.C9 反例：憑證輪替未分 Scope" data-link-desc="憑證輪替若未分域分批，容易造成跨系統連鎖中斷。">Failure: Credential Rotation Without Scope</a></td>
          <td>Let&rsquo;s Encrypt rate limit（50 cert/week per domain）是 scope-driven 設計的硬約束、單一 domain 不能無限 rotation、wildcard / SAN consolidation 必須納入 rotation 策略</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/transport-trust-and-certificate-lifecycle/" data-link-title="7.5 傳輸信任與憑證生命週期" data-link-desc="以問題驅動方式整理傳輸信任鏈、會話完整性與憑證節奏">7.4 Transport Trust and Certificate Lifecycle</a>、<a href="/blog/backend/07-security-data-protection/credential-rotation-scoped-evidence/" data-link-title="7.27 Credential Rotation with Scoped Evidence 實作示範" data-link-desc="以 webhook/API credential 輪替示範 scope map、證據欄位與回退窗口如何一起設計。">7.5 Credential Rotation Scoped Evidence</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/aws-acm/" data-link-title="AWS ACM" data-link-desc="AWS-managed certificate provisioning、DNS validation &#43; auto-renewal、整合 ELB / CloudFront / API Gateway、Private CA 後端">AWS ACM</a>、<a href="/blog/backend/07-security-data-protection/vendors/cert-manager/" data-link-title="cert-manager" data-link-desc="K8s 原生 certificate lifecycle automation、支援 Let&#39;s Encrypt / Vault PKI / Venafi 等多 issuer、auto-renewal &#43; Challenge solver">cert-manager</a>、<a href="/blog/backend/07-security-data-protection/vendors/spire/" data-link-title="SPIRE" data-link-desc="SPIFFE Runtime Environment、attested workload identity、short-lived SVID &#43; Trust Bundle、跨組織 federation">SPIRE</a></li>
<li>下游：<a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a>（Vault PKI 處理 internal CA、跟 Let&rsquo;s Encrypt public CA 互補）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（cert 出事 / private key 外洩如何 routing 進 IR 流程）</li>
<li>官方：<a href="https://letsencrypt.org/docs/">Let&rsquo;s Encrypt Documentation</a>、<a href="https://datatracker.ietf.org/doc/html/rfc8555">ACME RFC 8555</a>、<a href="https://crt.sh">crt.sh CT log search</a></li>
</ul>
]]></content:encoded></item><item><title>Toxiproxy</title><link>https://tarrragon.github.io/blog/backend/06-reliability/vendors/toxiproxy/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/06-reliability/vendors/toxiproxy/</guid><description>&lt;p>Toxiproxy 是 Shopify 開源的 TCP-level fault injection proxy、承擔三個責任：TCP 層 fault inject（latency / bandwidth / partition / slow_close）、integration test 中可程式化故障注入（reproducible）、client SDK 多語言（Go / Ruby / Python / JS）。設計取捨偏向「CI-friendly + reproducible + 細粒度 TCP control」、不適合 production chaos、適合 integration test 跟 dependency failure 模擬。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>跑起 Toxiproxy server + 設 listener / upstream proxy&lt;/li>
&lt;li>用 client SDK 注入 latency / partition / bandwidth toxic&lt;/li>
&lt;li>整合 Toxiproxy 到 integration test（before/after test hook）&lt;/li>
&lt;li>用 Docker Compose 整合&lt;/li>
&lt;li>評估 Toxiproxy vs Chaos Mesh NetworkChaos 的選用&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑5-分鐘把-toxiproxy-跑起來">最短路徑：5 分鐘把 Toxiproxy 跑起來&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 1. 啟動 server&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: docker run -d -p 8474:8474 -p 26379:26379 ghcr.io/shopify/toxiproxy&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="c1"># 2. 建 proxy（Redis 為例）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: curl -X POST localhost:8474/proxies -d &amp;#39;{&amp;#34;name&amp;#34;:&amp;#34;redis&amp;#34;,&amp;#34;listen&amp;#34;:&amp;#34;0.0.0.0:26379&amp;#34;,&amp;#34;upstream&amp;#34;:&amp;#34;redis:6379&amp;#34;}&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">&lt;span class="c1"># 3. 注入 toxic&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: curl -X POST localhost:8474/proxies/redis/toxics -d &amp;#39;{&amp;#34;type&amp;#34;:&amp;#34;latency&amp;#34;,&amp;#34;attributes&amp;#34;:{&amp;#34;latency&amp;#34;:1000}}&amp;#39;&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="日常操作與決策形狀">日常操作與決策形狀&lt;/h2>
&lt;h3 id="toxic-types">Toxic types&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>latency：增加延遲&lt;/li>
&lt;li>bandwidth：限制頻寬&lt;/li>
&lt;li>slow_close：connection close 慢&lt;/li>
&lt;li>timeout：connection timeout&lt;/li>
&lt;li>slicer：把 TCP packet 切片&lt;/li>
&lt;li>limit_data：limit 傳輸量&lt;/li>
&lt;/ul>
&lt;h3 id="api--client-sdk">API + Client SDK&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>HTTP API（8474 default）&lt;/li>
&lt;li>Client SDK：Go / Ruby / Python / JS&lt;/li>
&lt;li>Programmatic toxic enable/disable&lt;/li>
&lt;/ul>
&lt;h3 id="integration-test-pattern">Integration test pattern&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>before each test 設 toxic&lt;/li>
&lt;li>after each test cleanup&lt;/li>
&lt;li>Test isolation：每 test reset proxy state&lt;/li>
&lt;/ul>
&lt;h2 id="進階主題按需閱讀">進階主題（按需閱讀）&lt;/h2>
&lt;h3 id="docker-compose-整合">Docker Compose 整合&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>service depends_on toxiproxy&lt;/li>
&lt;li>應用透過 toxiproxy connect 真正 DB / cache&lt;/li>
&lt;li>environment variable 切換 toxiproxy vs direct&lt;/li>
&lt;/ul>
&lt;h3 id="reproducible-chaos">Reproducible chaos&lt;/h3>
&lt;p>子議題：&lt;/p></description><content:encoded><![CDATA[<p>Toxiproxy 是 Shopify 開源的 TCP-level fault injection proxy、承擔三個責任：TCP 層 fault inject（latency / bandwidth / partition / slow_close）、integration test 中可程式化故障注入（reproducible）、client SDK 多語言（Go / Ruby / Python / JS）。設計取捨偏向「CI-friendly + reproducible + 細粒度 TCP control」、不適合 production chaos、適合 integration test 跟 dependency failure 模擬。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>跑起 Toxiproxy server + 設 listener / upstream proxy</li>
<li>用 client SDK 注入 latency / partition / bandwidth toxic</li>
<li>整合 Toxiproxy 到 integration test（before/after test hook）</li>
<li>用 Docker Compose 整合</li>
<li>評估 Toxiproxy vs Chaos Mesh NetworkChaos 的選用</li>
</ol>
<h2 id="最短路徑5-分鐘把-toxiproxy-跑起來">最短路徑：5 分鐘把 Toxiproxy 跑起來</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 1. 啟動 server</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># TODO: docker run -d -p 8474:8474 -p 26379:26379 ghcr.io/shopify/toxiproxy</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 2. 建 proxy（Redis 為例）</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="c1"># TODO: curl -X POST localhost:8474/proxies -d &#39;{&#34;name&#34;:&#34;redis&#34;,&#34;listen&#34;:&#34;0.0.0.0:26379&#34;,&#34;upstream&#34;:&#34;redis:6379&#34;}&#39;</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="c1"># 3. 注入 toxic</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="c1"># TODO: curl -X POST localhost:8474/proxies/redis/toxics -d &#39;{&#34;type&#34;:&#34;latency&#34;,&#34;attributes&#34;:{&#34;latency&#34;:1000}}&#39;</span></span></span></code></pre></div><h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="toxic-types">Toxic types</h3>
<p>子議題：</p>
<ul>
<li>latency：增加延遲</li>
<li>bandwidth：限制頻寬</li>
<li>slow_close：connection close 慢</li>
<li>timeout：connection timeout</li>
<li>slicer：把 TCP packet 切片</li>
<li>limit_data：limit 傳輸量</li>
</ul>
<h3 id="api--client-sdk">API + Client SDK</h3>
<p>子議題：</p>
<ul>
<li>HTTP API（8474 default）</li>
<li>Client SDK：Go / Ruby / Python / JS</li>
<li>Programmatic toxic enable/disable</li>
</ul>
<h3 id="integration-test-pattern">Integration test pattern</h3>
<p>子議題：</p>
<ul>
<li>before each test 設 toxic</li>
<li>after each test cleanup</li>
<li>Test isolation：每 test reset proxy state</li>
</ul>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<h3 id="docker-compose-整合">Docker Compose 整合</h3>
<p>子議題：</p>
<ul>
<li>service depends_on toxiproxy</li>
<li>應用透過 toxiproxy connect 真正 DB / cache</li>
<li>environment variable 切換 toxiproxy vs direct</li>
</ul>
<h3 id="reproducible-chaos">Reproducible chaos</h3>
<p>子議題：</p>
<ul>
<li>Toxic seed（reproducible random）</li>
<li>Toxic stream（upstream / downstream）</li>
<li>對應 test reproducibility</li>
</ul>
<h3 id="跟-chaos-mesh-networkchaos-對比">跟 Chaos Mesh NetworkChaos 對比</h3>
<p>子議題：</p>
<ul>
<li>Toxiproxy：CI / integration test、TCP 層</li>
<li>Chaos Mesh：production、K8s pod 層</li>
<li>選擇判讀：testing CI → Toxiproxy；K8s staging chaos → Chaos Mesh</li>
</ul>
<h3 id="跟-client-retry--circuit-breaker-配合">跟 client retry / circuit breaker 配合</h3>
<p>子議題：</p>
<ul>
<li>驗證 client 對 dependency failure 的應對</li>
<li>Retry budget / backoff 測試</li>
<li>Circuit breaker trigger 測試</li>
<li>對應 <a href="/blog/backend/knowledge-cards/retry-budget/" data-link-title="Retry Budget" data-link-desc="說明重試次數如何受整體容量與錯誤預算限制">knowledge cards retry-budget</a></li>
</ul>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<h3 id="proxy-連不上">Proxy 連不上</h3>
<p>操作原則：先 <code>curl :8474/proxies</code> 看 proxy state、再看 network。</p>
<h3 id="toxic-沒生效">Toxic 沒生效</h3>
<p>操作原則：toxic enabled 但 attribute 設錯。判讀：API GET toxics 看當前狀態。</p>
<h3 id="test-state-pollute">Test state pollute</h3>
<p>操作原則：test 間沒 reset proxy、state 殘留。修法：每 test 開頭 reset。</p>
<h3 id="performance-overhead">Performance overhead</h3>
<p>操作原則：Toxiproxy 本身有 latency overhead（μs 級）、不適合 production sensitivity。</p>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>K8s production chaos</td>
          <td><a href="/blog/backend/06-reliability/vendors/chaos-mesh/" data-link-title="Chaos Mesh" data-link-desc="Kubernetes-native chaos engineering（CNCF incubating）">Chaos Mesh</a> NetworkChaos</td>
      </tr>
      <tr>
          <td>商業跨平台</td>
          <td><a href="/blog/backend/06-reliability/vendors/gremlin/" data-link-title="Gremlin" data-link-desc="商業 chaos engineering 平台、跨平台與 GameDay">Gremlin</a></td>
      </tr>
      <tr>
          <td>Application-level error</td>
          <td>Mock / stub library</td>
      </tr>
      <tr>
          <td>AWS-native</td>
          <td>AWS Fault Injection Service</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Toxic 內部實作</li>
<li>各語言 SDK 完整 API</li>
<li>TCP protocol 細節</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p><strong>Shopify 自家</strong>：Toxiproxy 是 Shopify 開源、Shopify reliability cases 多有引用。</p>
<table>
  <thead>
      <tr>
          <th>案例方向</th>
          <th>對應主題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/06-reliability/cases/shopify/bfcm-capacity-and-game-day/" data-link-title="Shopify：BFCM 容量治理與 Game Day 驗證節奏" data-link-desc="把季節性流量峰值轉成年度可靠性流程，透過容量模型、演練與隔離策略提前吸收風險。">Shopify：BFCM 容量治理與 Game Day</a></td>
          <td>resiliency matrix + TCP-level fault injection 的原生使用脈絡</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/06-reliability/cases/stripe/idempotency-and-zero-downtime-migration/" data-link-title="Stripe：Idempotency 與零停機遷移的交易安全設計" data-link-desc="把 API 重試與資料遷移放在同一套安全模型，維持支付交易的一致結果。">Stripe：Idempotency 與零停機遷移</a></td>
          <td>integration test 模擬 dependency 失敗、驗證 retry 與 idempotency</td>
      </tr>
  </tbody>
</table>
<p><strong>Case 庫稀薄</strong>：Toxiproxy 主要 case 集中在 Shopify 自家、其他 adopter 案例待補。</p>
<ul>
<li><strong>待補 Toxiproxy adopter case</strong>：其他公司用 Toxiproxy 做 dependency failure 測試</li>
<li><strong>候選 case</strong>：Pinterest（cache failure mode integration test）、Spotify（squad 自管 integration chaos）— 若未來收錄需先在 cases/ 補正文</li>
</ul>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游概念：<a href="/blog/backend/06-reliability/experiment-safety-boundary/" data-link-title="6.20 Experiment Safety Boundary" data-link-desc="定義 chaos、load test、DR drill 的 [blast radius](/backend/knowledge-cards/blast-radius/)、停止條件與權限約束">6.20 Experiment Safety Boundary</a></li>
<li>平行 vendor：<a href="/blog/backend/06-reliability/vendors/chaos-mesh/" data-link-title="Chaos Mesh" data-link-desc="Kubernetes-native chaos engineering（CNCF incubating）">Chaos Mesh</a>、<a href="/blog/backend/06-reliability/vendors/gremlin/" data-link-title="Gremlin" data-link-desc="商業 chaos engineering 平台、跨平台與 GameDay">Gremlin</a></li>
<li>下游能力：<a href="/blog/backend/knowledge-cards/retry-budget/" data-link-title="Retry Budget" data-link-desc="說明重試次數如何受整體容量與錯誤預算限制">knowledge cards retry-budget</a></li>
</ul>
]]></content:encoded></item><item><title>SPIRE</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/spire/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/spire/</guid><description>&lt;p>SPIRE（SPIFFE Runtime Environment）是 SPIFFE 規範的 reference 實作、CNCF graduated 專案、解決 &lt;em>workload identity attestation&lt;/em> 的核心問題：在 service mesh / 跨 cluster / 跨組織的環境裡、一個 workload 必須能 &lt;em>被驗證&lt;/em> 它是誰（是哪個 namespace 的哪個 service account、跑在哪台 attested host 上）、而不是依靠 IP / hostname / 共用 API key 這種可偽造的識別。SPIRE 發出的識別憑證叫 &lt;em>SVID&lt;/em>（SPIFFE Verifiable Identity Document）、識別格式是 URI 形式的 &lt;em>SPIFFE ID&lt;/em>（例如 &lt;code>spiffe://example.org/ns/prod/sa/api-gateway&lt;/code>）、TTL 是分鐘級短期、workload 透過本地 Unix socket（Workload API）持續拉新 SVID、不 mount file 一勞永逸。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>SPIRE 的核心定位是 &lt;em>attestation-first 的 workload identity 控制面&lt;/em>、解的問題是「這個 workload 在執行時是不是它聲稱的那個」— 識別語意是 &lt;em>attested SPIFFE ID&lt;/em>、不是 DNS name 也不是 cluster-internal ServiceAccount。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/cert-manager/" data-link-title="cert-manager" data-link-desc="K8s 原生 certificate lifecycle automation、支援 Let&amp;#39;s Encrypt / Vault PKI / Venafi 等多 issuer、auto-renewal &amp;#43; Challenge solver">cert-manager&lt;/a> 的 &lt;em>cert lifecycle&lt;/em>（DNS name 為主）、Kubernetes ServiceAccount 的 &lt;em>cluster-internal scope&lt;/em>、&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault&lt;/a> AppRole 的 &lt;em>pull-based secret&lt;/em>（workload 要先持有 secret_id）都解不同問題、不是替代關係。&lt;/p>
&lt;p>跟雲端 workload identity（&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM Roles Anywhere&lt;/a> / GCP Workload Identity Federation / Azure Federated Identity Credential）相比、SPIRE 多了 &lt;em>跨雲統一抽象&lt;/em> + &lt;em>跨組織 federation&lt;/em>（兩個 SPIRE deployment 互相信任只需要交換 trust bundle）。代價是 &lt;em>自管控制面&lt;/em>（SPIRE Server HA + Agent rollout + Registration Entry 維護）。詳細跟其他 vendor 的場景對比見「核心取捨表」與「何時改走其他服務」。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本頁、讀者能判斷：&lt;/p>
&lt;ol>
&lt;li>何時用 SPIRE（zero-trust mesh、跨 cluster / 跨組織 federation、需要 attestation）、何時用 cert-manager + Service Account / cloud-native workload identity 就夠&lt;/li>
&lt;li>SPIRE deployment 的最低安全骨架（Server / Agent 拓樸、Node Attestor、Workload Attestor、Registration Entry、SVID TTL）&lt;/li>
&lt;li>跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault&lt;/a> / Istio / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM&lt;/a> Roles Anywhere 的整合形狀&lt;/li>
&lt;li>失敗模式如何排錯（Attestor 設計太寬、SVID 過期、Trust Bundle 不同步）&lt;/li>
&lt;/ol>
&lt;h2 id="最短判讀路徑">最短判讀路徑&lt;/h2>
&lt;p>判斷 SPIRE deployment 是否健康、最少看四件事：&lt;/p></description><content:encoded><![CDATA[<p>SPIRE（SPIFFE Runtime Environment）是 SPIFFE 規範的 reference 實作、CNCF graduated 專案、解決 <em>workload identity attestation</em> 的核心問題：在 service mesh / 跨 cluster / 跨組織的環境裡、一個 workload 必須能 <em>被驗證</em> 它是誰（是哪個 namespace 的哪個 service account、跑在哪台 attested host 上）、而不是依靠 IP / hostname / 共用 API key 這種可偽造的識別。SPIRE 發出的識別憑證叫 <em>SVID</em>（SPIFFE Verifiable Identity Document）、識別格式是 URI 形式的 <em>SPIFFE ID</em>（例如 <code>spiffe://example.org/ns/prod/sa/api-gateway</code>）、TTL 是分鐘級短期、workload 透過本地 Unix socket（Workload API）持續拉新 SVID、不 mount file 一勞永逸。</p>
<h2 id="服務定位">服務定位</h2>
<p>SPIRE 的核心定位是 <em>attestation-first 的 workload identity 控制面</em>、解的問題是「這個 workload 在執行時是不是它聲稱的那個」— 識別語意是 <em>attested SPIFFE ID</em>、不是 DNS name 也不是 cluster-internal ServiceAccount。跟 <a href="/blog/backend/07-security-data-protection/vendors/cert-manager/" data-link-title="cert-manager" data-link-desc="K8s 原生 certificate lifecycle automation、支援 Let&#39;s Encrypt / Vault PKI / Venafi 等多 issuer、auto-renewal &#43; Challenge solver">cert-manager</a> 的 <em>cert lifecycle</em>（DNS name 為主）、Kubernetes ServiceAccount 的 <em>cluster-internal scope</em>、<a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a> AppRole 的 <em>pull-based secret</em>（workload 要先持有 secret_id）都解不同問題、不是替代關係。</p>
<p>跟雲端 workload identity（<a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM Roles Anywhere</a> / GCP Workload Identity Federation / Azure Federated Identity Credential）相比、SPIRE 多了 <em>跨雲統一抽象</em> + <em>跨組織 federation</em>（兩個 SPIRE deployment 互相信任只需要交換 trust bundle）。代價是 <em>自管控制面</em>（SPIRE Server HA + Agent rollout + Registration Entry 維護）。詳細跟其他 vendor 的場景對比見「核心取捨表」與「何時改走其他服務」。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>何時用 SPIRE（zero-trust mesh、跨 cluster / 跨組織 federation、需要 attestation）、何時用 cert-manager + Service Account / cloud-native workload identity 就夠</li>
<li>SPIRE deployment 的最低安全骨架（Server / Agent 拓樸、Node Attestor、Workload Attestor、Registration Entry、SVID TTL）</li>
<li>跟 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a> / Istio / <a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM</a> Roles Anywhere 的整合形狀</li>
<li>失敗模式如何排錯（Attestor 設計太寬、SVID 過期、Trust Bundle 不同步）</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 SPIRE deployment 是否健康、最少看四件事：</p>
<ul>
<li><strong>Server / Agent 拓樸</strong>：SPIRE Server 是 trust domain 的 root、發 SVID、簽 Trust Bundle；SPIRE Agent 跑在每個 host / node 上、向 Server 註冊、為本機 workload attest 身份。Server HA（多副本 + 共享 DB）跟 Agent rollout coverage 缺一就會出現 <em>節點上 workload 拿不到 SVID</em>。</li>
<li><strong>Attestor 設計</strong>：Node Attestor 驗 <em>這台 host 是真的</em>（K8s SAT / AWS IID / Azure MSI / GCP IIT / TPM 等）、Workload Attestor 驗 <em>這個 process 是誰</em>（K8s pod selector、unix UID/GID、systemd unit）。Selector 太寬等於整個 namespace 任何 pod 都拿同一個 SPIFFE ID、blast radius 失控。</li>
<li><strong>SVID lifetime</strong>：X.509-SVID 預設 TTL 1 小時、production 建議 5–15 分鐘；workload 必須走 Workload API（Unix socket）持續拉新 SVID、不能 mount 成 file。Workload 不支援 SDK 整合就被擋在 SPIRE 之外。</li>
<li><strong>Registration Entry</strong>：定義「哪個 SPIFFE ID 可以被哪個 attestation selector 取得」、是 SPIRE 的 <em>authorization 設計核心</em>。一個 entry 寫錯（selector 用了 <code>k8s:ns:default</code> 沒鎖 service account）就等於 default namespace 任何 pod 都拿 admin SPIFFE ID。</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/07-security-data-protection/workload-identity-and-federated-trust/" data-link-title="7.10 Workload Identity 與聯邦信任邊界" data-link-desc="定義非人類身份、跨平台信任與短時憑證治理問題">Workload Identity and Federated Trust</a> 邊界的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>Server / Agent 拓樸</strong>：SPIRE Server 是 trust domain 的 root CA + 註冊中心、必須 HA（至少兩副本 + 共享 PostgreSQL / MySQL）、production 通常每個 cluster 一個 Server cluster；SPIRE Agent 以 DaemonSet 跑在每個 K8s node、或以 systemd unit 跑在每台 VM、負責本機的 attestation 與 SVID 派發。Agent 跟 Server 之間用 mutual TLS、Agent 自己也走 Node Attestation 才能向 Server 註冊。</p>
<p><strong>Node Attestor</strong>：決定「這個 Agent 是不是真的跑在它聲稱的 host 上」。K8s SAT / PSAT（projected service account token）驗 Agent 的 ServiceAccount + Pod；AWS IID 驗 EC2 instance identity document；GCP IIT 驗 GCE metadata；Azure MSI 驗 Managed Identity；TPM attestor 驗硬體 TPM 簽章。選錯 attestor 等於 host 識別被偽造 — 例如 K8s SAT 沒鎖 audience、外部能用任何 K8s SA token 註冊 fake Agent。</p>
<p><strong>Workload Attestor</strong>：決定「這個 process 是哪個 workload」。Kubernetes attestor 用 pod label / annotation / namespace / service account；Unix attestor 用 UID / GID / parent process / binary hash；Docker attestor 用 container label / image。Workload 連到 Agent 的 Workload API Unix socket、Agent 透過 attestor 收集 selector、比對 Registration Entry、決定能發哪個 SPIFFE ID。Selector 設計是 <em>least privilege</em> 的 enforcement point — 寫得越精確、blast radius 越小。</p>
<p><strong>Registration Entry</strong>：定義 SPIFFE ID 到 selector 的 mapping、例如「<code>spiffe://example.org/ns/prod/sa/api-gateway</code> 對應 <code>k8s:ns:prod</code>、<code>k8s:sa:api-gateway</code>、<code>k8s:pod-label:app:api-gateway</code>」。Entry 透過 SPIRE Server API 或 GitOps 維護、變更走 PR review（policy-as-code）、避免單一 admin 偷加 entry 拿 admin SPIFFE ID。</p>
<p><strong>SVID 生命週期</strong>：X.509-SVID 是 mTLS 用的 cert（含 SPIFFE ID 作 URI SAN）、JWT-SVID 是給 non-mTLS 場景（HTTP header bearer token、跟 OIDC 整合）。workload 透過 Workload API stream 接 SVID、TTL 過半就 Agent 主動 push 新 SVID — workload 不需要自己排程 renew。Trust Bundle（trust domain 的 root cert）也透過 Workload API 同步、自動更新。</p>
<p><strong>Federation between trust domains</strong>：兩個獨立 SPIRE deployment（不同組織、不同 trust domain）要互信、交換 <em>trust bundle</em>（自簽 root cert）、走 SPIFFE Federation API。<code>example.org</code> 的 workload 可以驗證 <code>partner.com</code> 的 SVID、不需要共用 PKI、不需要在中間放 broker。對應 <a href="/blog/backend/07-security-data-protection/workload-identity-and-federated-trust/" data-link-title="7.10 Workload Identity 與聯邦信任邊界" data-link-desc="定義非人類身份、跨平台信任與短時憑證治理問題">Workload Identity and Federated Trust</a> 的 federation 章節。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>SPIRE</th>
          <th>cert-manager</th>
          <th>Kubernetes ServiceAccount</th>
          <th>Vault AppRole</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>識別語意</td>
          <td>Attested SPIFFE ID（who is this workload）</td>
          <td>DNS name（who owns this name）</td>
          <td>Cluster-internal SA name</td>
          <td>Pull-based role + secret_id</td>
      </tr>
      <tr>
          <td>信任邊界</td>
          <td>Trust domain、可跨 cluster / cloud / 組織</td>
          <td>Cluster 內、外部走 ACME / Vault PKI</td>
          <td>單一 cluster</td>
          <td>Vault 範圍內</td>
      </tr>
      <tr>
          <td>Attestation</td>
          <td>First-class — Node + Workload Attestor 雙層</td>
          <td>無 — 僅驗 DNS / cert request</td>
          <td>TokenReview API、cluster-scoped</td>
          <td>無 — secret_id 即是 proof</td>
      </tr>
      <tr>
          <td>Cert TTL</td>
          <td>分鐘級短期、Workload API 自動 rotate</td>
          <td>天 / 月級、cert-manager 排程 renew</td>
          <td>Token TTL（projected: 短）</td>
          <td>Token TTL（lease 治理）</td>
      </tr>
      <tr>
          <td>Workload 改動</td>
          <td>需走 SPIFFE Workload API SDK 或 sidecar</td>
          <td>Mount file 即可</td>
          <td>Mount file 即可</td>
          <td>拉 secret_id + 換 token</td>
      </tr>
      <tr>
          <td>跨組織 federation</td>
          <td>強 — 交換 trust bundle 即可</td>
          <td>弱 — 需共用 CA 或 ACME</td>
          <td>不支援</td>
          <td>弱 — 需共用 Vault 或 OIDC bridge</td>
      </tr>
      <tr>
          <td>運維成本</td>
          <td>高 — Server HA + Agent rollout + Entry 治理</td>
          <td>低 — Operator 模式</td>
          <td>內建</td>
          <td>中 — Vault 自管</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>Zero-trust mesh、跨 cluster / 跨組織、需要 attestation</td>
          <td>K8s app cert lifecycle、ACME / Vault issuer</td>
          <td>Cluster-internal 簡單 app</td>
          <td>不在雲 metadata 內的 workload</td>
      </tr>
  </tbody>
</table>
<p>選 SPIRE 的核心訴求：<em>需要 attested workload identity</em>（不只是「有 cert 就信」）+ <em>跨 cluster 或跨組織</em>（單 cluster 內 ServiceAccount 已夠）+ <em>workload 能整合 SPIFFE SDK 或 sidecar</em>。三個條件缺一就先用 cert-manager + ServiceAccount 組合、別硬上 SPIRE。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>跟 Istio / Linkerd / Envoy 整合</strong>：Istio 1.14+ 支援 SPIRE 作 identity provider（取代 Citadel）、Envoy SDS（Secret Discovery Service）走 SPIRE Workload API 拉 SVID、service mesh 內 mTLS 用 SPIFFE ID 做 peer 驗證 + authz policy（<code>source.principal == &quot;spiffe://example.org/ns/prod/sa/api-gateway&quot;</code>）。Linkerd 也有實驗性整合（policy controller 接受 SPIFFE ID）。</p>
<p><strong>跟 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a> 整合</strong>：Vault 可以用 SPIRE JWT-SVID 作 auth method、workload 拿 SVID 換 Vault token、不需要 AppRole secret_id — 等於把 Vault auth 的 <em>bootstrap secret 問題</em> 交給 SPIRE attestation 處理。workload 同時拿 SPIFFE 身份（mTLS）跟 Vault secret（DB credential、PKI cert）、兩條鏈共用同一個 attestation root。</p>
<p><strong>跟 <a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM</a> Roles Anywhere 整合</strong>：AWS IAM Roles Anywhere 接受 X.509 cert 換 IAM credential、SPIRE 發的 X.509-SVID 可以當這個 cert — non-AWS workload（on-prem、其他雲、CI runner）用 SPIFFE ID 拿 short-term AWS STS credential、不需要存 long-lived AWS access key。</p>
<p><strong>Nested SPIRE（多層 trust domain）</strong>：大型組織把 trust domain 切成 <em>parent + child</em>（例如 <code>example.org</code> 作 parent、每個 BU 各自 <code>bu1.example.org</code>、<code>bu2.example.org</code>）、child Server 向 parent Server 註冊作 downstream、child trust domain 的 workload 還是被 parent root 信任。適合需要 <em>部門自治 + 全公司互通</em> 的場景。</p>
<p><strong>JWT-SVID 給 non-mTLS workload</strong>：HTTP service 不一定能跑 mTLS（CDN 後面、legacy app）、SPIRE 發 JWT-SVID（標準 JWT、aud / sub claim、SPIFFE ID 在 sub）給這類 workload、走 HTTP <code>Authorization: Bearer</code> 傳遞、收方驗 SPIRE trust bundle 簽章。代價是失去 mTLS 的 mutual auth、需要 application-level 驗 JWT-SVID。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Workload Attestor selector 太寬</strong>：Entry 只鎖 <code>k8s:ns:prod</code> 沒鎖 <code>k8s:sa:*</code> — namespace 內任何 pod 都拿同一個 admin SPIFFE ID。修法：selector 必含 namespace + service account + （建議）pod label，policy review 走 GitOps PR。</li>
<li><strong>SVID 過期但 workload 沒接 Workload API</strong>：workload 把 SVID dump 成 file 後不再連 Workload API、TTL 過期之後 mTLS 失敗 — workload 必須用 SPIFFE SDK 或 sidecar（envoy / spiffe-helper）持續 stream SVID。</li>
<li><strong>Node Attestor audience 未鎖</strong>：K8s SAT attestor 沒設 <code>audience</code>、外部能用任何 K8s SA token 註冊 fake Agent — 改用 PSAT（projected SA token）+ 明確 audience 鎖到 SPIRE Server URL。</li>
<li><strong>Trust Bundle 不同步</strong>：federation 對端 rotate root cert、本端沒抓到新 bundle、跨 trust domain mTLS 失敗 — federation endpoint 必須走 HTTPS + 定期 refresh、SPIRE Server metric 監控 federation fetch 失敗。</li>
<li><strong>Registration Entry 漂移</strong>：手動加的 entry 沒進 GitOps、admin 離職後沒人知道為何某個 SPIFFE ID 存在 — entry 必須走 declarative source（YAML in Git）+ CI apply、禁止直接 <code>spire-server entry create</code>。</li>
<li><strong>Server DB 單點</strong>：SPIRE Server SQLite mode 跑在 production、節點掛了 = 整個 trust domain 不能發 SVID — production 必走 PostgreSQL / MySQL + HA Server 副本。</li>
<li><strong>Audit log gap</strong>：SPIRE Server audit log 沒接 SIEM、SVID 派發紀錄 7 天後輪轉掉、事故時無法回查誰拿過 admin SPIFFE ID — audit log 同步到外部 SIEM 是基本要求、對應 <a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">Audit Log</a> 卡。</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>單 cluster 簡單 K8s app + DNS-named cert</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/cert-manager/" data-link-title="cert-manager" data-link-desc="K8s 原生 certificate lifecycle automation、支援 Let&#39;s Encrypt / Vault PKI / Venafi 等多 issuer、auto-renewal &#43; Challenge solver">cert-manager</a> + Kubernetes ServiceAccount</td>
      </tr>
      <tr>
          <td>公開 serving cert（HTTPS endpoint）</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/aws-acm/" data-link-title="AWS ACM" data-link-desc="AWS-managed certificate provisioning、DNS validation &#43; auto-renewal、整合 ELB / CloudFront / API Gateway、Private CA 後端">AWS ACM</a> / <a href="/blog/backend/07-security-data-protection/vendors/letsencrypt/" data-link-title="Let&#39;s Encrypt" data-link-desc="免費 &#43; 自動化的公共 ACME CA、90 天 TTL 強制自動化、跨雲跨平台 public TLS cert 的事實基礎">Let&rsquo;s Encrypt</a></td>
      </tr>
      <tr>
          <td>Static secret + dynamic credential</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a></td>
      </tr>
      <tr>
          <td>AWS-only workload + IAM role</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM</a> IRSA / Roles Anywhere</td>
      </tr>
      <tr>
          <td>GCP-only workload</td>
          <td>GCP Workload Identity Federation</td>
      </tr>
      <tr>
          <td>純 human identity / SSO</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/keycloak/" data-link-title="Keycloak" data-link-desc="Open source self-hosted Identity Provider、Red Hat 主導、Realm-based multi-tenancy、適合資料主權與自訂 flow 需求">Keycloak</a> / <a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a></td>
      </tr>
      <tr>
          <td>跨組織 OIDC federation（human + machine）</td>
          <td><a href="/blog/backend/07-security-data-protection/workload-identity-and-federated-trust/" data-link-title="7.10 Workload Identity 與聯邦信任邊界" data-link-desc="定義非人類身份、跨平台信任與短時憑證治理問題">Workload Identity and Federated Trust</a>（章節層）</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>SPIFFE 規範完整逐條解讀（spec 各 section 細節）</li>
<li>SPIRE Server / Agent 完整 CLI 與 config reference</li>
<li>每個 Attestor plugin 的內部實作細節</li>
<li>Istio / Linkerd / Envoy 整合的完整步驟（屬 service mesh 章節）</li>
<li>SPIFFE Helper / spire-agent sidecar 各語言 SDK 用法</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>SPIRE 在 07 案例庫沒有直接 vendor-level 事件、以下為對照引用：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 SPIRE 的關係（對照）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/workload-identity-and-federated-trust/" data-link-title="7.10 Workload Identity 與聯邦信任邊界" data-link-desc="定義非人類身份、跨平台信任與短時憑證治理問題">Workload Identity and Federated Trust (section)</a></td>
          <td>SPIRE 是 federation 信任邊界的具體實作 — 跨 trust domain 交換 bundle 是 SPIFFE federation 的標準形狀</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/microsoft-storm-0558-2023-signing-key-chain/" data-link-title="7.R7.1.5 Microsoft Storm-0558 2023：簽章金鑰鏈與郵件存取" data-link-desc="從簽章金鑰保護失效到雲端郵件存取，拆解身分信任鏈的關鍵控制點">Microsoft Storm-0558 Signing Key Chain (red-team)</a></td>
          <td>對照啟示 — JWT-SVID 是 <em>short-lived + attested</em> 設計、跟 Storm-0558 的 long-lived signing key 是相反 mindset；attestation + 分鐘級 TTL 限制了 key 外洩後的 blast radius</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/github-oauth-2022-token-supply-chain/" data-link-title="7.R7.2.2 GitHub OAuth 2022：第三方 token 供應鏈風險" data-link-desc="第三方整合 token 被竊後，如何形成跨組織存取風險">GitHub OAuth 2022 Token Supply Chain (red-team)</a></td>
          <td>對照啟示 — 傳統 OAuth token 過寬 + 過長、SPIRE 設計是 short TTL + scope-narrow SPIFFE ID + Registration Entry 走 declarative authz、把 secret-leak 路徑收掉</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/workload-identity-and-federated-trust/" data-link-title="7.10 Workload Identity 與聯邦信任邊界" data-link-desc="定義非人類身份、跨平台信任與短時憑證治理問題">Workload Identity and Federated Trust</a>、<a href="/blog/backend/07-security-data-protection/identity-access-boundary/" data-link-title="7.2 身分與授權邊界" data-link-desc="以問題驅動方式整理身分、授權、會話與供應商身分鏈">Identity &amp; Access Boundary</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/cert-manager/" data-link-title="cert-manager" data-link-desc="K8s 原生 certificate lifecycle automation、支援 Let&#39;s Encrypt / Vault PKI / Venafi 等多 issuer、auto-renewal &#43; Challenge solver">cert-manager</a>（DNS-named cert lifecycle）、<a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a>（用 SPIRE JWT-SVID 作 Vault auth method）、<a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM</a>（Roles Anywhere 接 SPIRE 發的 X.509-SVID）</li>
<li>下游：service mesh（Istio / Linkerd / Envoy）整合層、<a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">Audit Log</a></li>
<li>官方：<a href="https://spiffe.io/docs/latest/spiffe-about/spiffe-overview/">SPIFFE Specification</a>、<a href="https://spiffe.io/docs/latest/spire-about/">SPIRE Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>Nobl9</title><link>https://tarrragon.github.io/blog/backend/06-reliability/vendors/nobl9/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/06-reliability/vendors/nobl9/</guid><description>&lt;p>Nobl9 是商業 SLO 平台、承擔三個責任：跨 data source SLO 統一治理（Datadog / Prometheus / New Relic / CloudWatch / Splunk 等）、error budget + burn rate alerting、organizational SLO governance（service catalog / project / role）。設計取捨偏向「multi-source + governance + OpenSLO standard」、創辦人來自 Google SRE、推動 OpenSLO 標準。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>在 Nobl9 定義 SLO（SLI / target / time window）&lt;/li>
&lt;li>配置 error budget + burn rate alert（multi-window）&lt;/li>
&lt;li>設計 composite SLO（跨服務組合）&lt;/li>
&lt;li>用 OpenSLO YAML 管 SLO as code&lt;/li>
&lt;li>評估 Nobl9 vs Sloth / Pyrra / vendor 內建 SLO&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑5-分鐘把-nobl9-跑起來">最短路徑：5 分鐘把 Nobl9 跑起來&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 1. 註冊 Nobl9 + connect data source&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: app.nobl9.com、connect Datadog / Prometheus&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="c1"># 2. 寫 SLO YAML（OpenSLO）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: SLO spec with service / indicator / objective&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">&lt;span class="c1"># 3. sloctl apply&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: sloctl apply -f slo.yaml&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="日常操作與決策形狀">日常操作與決策形狀&lt;/h2>
&lt;h3 id="slo-定義">SLO 定義&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>SLI（Service Level Indicator）：metric to measure&lt;/li>
&lt;li>Objective：target percentage&lt;/li>
&lt;li>Time window：rolling / calendar&lt;/li>
&lt;li>對應 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/burn-rate/" data-link-title="Burn Rate" data-link-desc="說明 error budget 消耗速度如何支援告警與事故分級">knowledge cards burn-rate&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="error-budget">Error budget&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>Budget = (1 - SLO target) × time window&lt;/li>
&lt;li>Consumed budget / remaining budget&lt;/li>
&lt;li>跟 release gate 對應（budget 用完 → freeze deploy）&lt;/li>
&lt;/ul>
&lt;h3 id="burn-rate-alert">Burn rate alert&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>Multi-window multi-burn-rate alert&lt;/li>
&lt;li>Fast burn alert（短期 high rate）+ slow burn alert（長期 low rate）&lt;/li>
&lt;li>對應 Google SRE burn rate alerting&lt;/li>
&lt;/ul>
&lt;h2 id="進階主題按需閱讀">進階主題（按需閱讀）&lt;/h2>
&lt;h3 id="composite-slo">Composite SLO&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>跨多 service 組合成單一 SLO&lt;/li>
&lt;li>適合：user journey SLO（不只單一 service）&lt;/li>
&lt;/ul>
&lt;h3 id="openslo-標準">OpenSLO 標準&lt;/h3>
&lt;p>子議題：&lt;/p></description><content:encoded><![CDATA[<p>Nobl9 是商業 SLO 平台、承擔三個責任：跨 data source SLO 統一治理（Datadog / Prometheus / New Relic / CloudWatch / Splunk 等）、error budget + burn rate alerting、organizational SLO governance（service catalog / project / role）。設計取捨偏向「multi-source + governance + OpenSLO standard」、創辦人來自 Google SRE、推動 OpenSLO 標準。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>在 Nobl9 定義 SLO（SLI / target / time window）</li>
<li>配置 error budget + burn rate alert（multi-window）</li>
<li>設計 composite SLO（跨服務組合）</li>
<li>用 OpenSLO YAML 管 SLO as code</li>
<li>評估 Nobl9 vs Sloth / Pyrra / vendor 內建 SLO</li>
</ol>
<h2 id="最短路徑5-分鐘把-nobl9-跑起來">最短路徑：5 分鐘把 Nobl9 跑起來</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 1. 註冊 Nobl9 + connect data source</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># TODO: app.nobl9.com、connect Datadog / Prometheus</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 2. 寫 SLO YAML（OpenSLO）</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="c1"># TODO: SLO spec with service / indicator / objective</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="c1"># 3. sloctl apply</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="c1"># TODO: sloctl apply -f slo.yaml</span></span></span></code></pre></div><h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="slo-定義">SLO 定義</h3>
<p>子議題：</p>
<ul>
<li>SLI（Service Level Indicator）：metric to measure</li>
<li>Objective：target percentage</li>
<li>Time window：rolling / calendar</li>
<li>對應 <a href="/blog/backend/knowledge-cards/burn-rate/" data-link-title="Burn Rate" data-link-desc="說明 error budget 消耗速度如何支援告警與事故分級">knowledge cards burn-rate</a></li>
</ul>
<h3 id="error-budget">Error budget</h3>
<p>子議題：</p>
<ul>
<li>Budget = (1 - SLO target) × time window</li>
<li>Consumed budget / remaining budget</li>
<li>跟 release gate 對應（budget 用完 → freeze deploy）</li>
</ul>
<h3 id="burn-rate-alert">Burn rate alert</h3>
<p>子議題：</p>
<ul>
<li>Multi-window multi-burn-rate alert</li>
<li>Fast burn alert（短期 high rate）+ slow burn alert（長期 low rate）</li>
<li>對應 Google SRE burn rate alerting</li>
</ul>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<h3 id="composite-slo">Composite SLO</h3>
<p>子議題：</p>
<ul>
<li>跨多 service 組合成單一 SLO</li>
<li>適合：user journey SLO（不只單一 service）</li>
</ul>
<h3 id="openslo-標準">OpenSLO 標準</h3>
<p>子議題：</p>
<ul>
<li>Vendor-neutral SLO spec</li>
<li>YAML 配置</li>
<li>跟 Nobl9 主導</li>
<li>對應 vendor lock-in 取捨</li>
</ul>
<h3 id="data-source-整合">Data source 整合</h3>
<p>子議題：</p>
<ul>
<li>Datadog / Prometheus / New Relic / CloudWatch / Splunk / AppDynamics / Honeycomb / Lightstep</li>
<li>多 source SLO 統一 view</li>
<li>對應 <a href="/blog/backend/04-observability/" data-link-title="模組四：可觀測性平台" data-link-desc="整理 log、metric、trace、dashboard 與 alert 的後端操作實務">04 observability</a> 模組</li>
</ul>
<h3 id="alert-routing">Alert routing</h3>
<p>子議題：</p>
<ul>
<li>跟 PagerDuty / Opsgenie / Slack 整合</li>
<li>跟 <a href="/blog/backend/08-incident-response/" data-link-title="模組八：事故處理與復盤" data-link-desc="用 IR 領域詞彙建問題節點、以服務級案例庫累積事故脈絡，先建概念與案例庫再進實作交接">08 incident response</a> 對應</li>
</ul>
<h3 id="service-catalog--governance">Service catalog + governance</h3>
<p>子議題：</p>
<ul>
<li>Project / Service / SLO 階層</li>
<li>Role-based access</li>
<li>Audit log</li>
</ul>
<h3 id="slo-as-code">SLO as code</h3>
<p>子議題：</p>
<ul>
<li>sloctl CLI</li>
<li>YAML version control</li>
<li>CI integration</li>
</ul>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<h3 id="slo-calculation-不準">SLO calculation 不準</h3>
<p>操作原則：SLI query 不對 / data source 延遲。判讀：raw metric vs SLO calculation 比對。</p>
<h3 id="alert-noise">Alert noise</h3>
<p>操作原則：burn rate window 設過短 / threshold 過嚴。</p>
<h3 id="data-source-disconnect">Data source disconnect</h3>
<p>操作原則：API key / network / quota。</p>
<h3 id="composite-slo-行為不符預期">Composite SLO 行為不符預期</h3>
<p>操作原則：composite 算法（AND / OR / custom）不對。</p>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>OSS / 預算敏感</td>
          <td><a href="/blog/backend/06-reliability/vendors/sloth/" data-link-title="Sloth" data-link-desc="OSS SLO generator for Prometheus">Sloth</a> / Pyrra</td>
      </tr>
      <tr>
          <td>單一 vendor 環境</td>
          <td>Datadog SLO / Honeycomb SLO / Grafana SLO</td>
      </tr>
      <tr>
          <td>K8s-native CRD</td>
          <td>Pyrra（K8s Operator）</td>
      </tr>
      <tr>
          <td>純 Prometheus</td>
          <td>Sloth（Prometheus generator）</td>
      </tr>
      <tr>
          <td>Enterprise + multi-cloud</td>
          <td>Nobl9（本頁）</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>OpenSLO 完整 spec</li>
<li>Nobl9 pricing</li>
<li>sloctl 完整 CLI reference</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<table>
  <thead>
      <tr>
          <th>案例方向</th>
          <th>對應主題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/06-reliability/cases/google/error-budget-policy-and-release-gating/" data-link-title="Google：Error Budget 政策如何決定發布節奏" data-link-desc="把 SLO 消耗量轉成 release gate，讓可靠性與交付速度共用同一套決策語言。">Google：Error Budget 與 Release Gating</a></td>
          <td>SLI / SLO / error budget 原典、多源聚合 SLO 平台的對齊對象</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/06-reliability/cases/honeycomb/burn-rate-driven-reliability-operations/" data-link-title="Honeycomb：以 Burn Rate 驅動的可靠性操作" data-link-desc="把 SLO burn rate 直接連到值班決策與改善優先序，降低高噪音告警造成的判讀失真。">Honeycomb：Burn Rate 驅動可靠性</a></td>
          <td>burn rate alert 對應 SLO 平台的 alert policy</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/06-reliability/cases/microsoft/change-management-and-reliability-governance/" data-link-title="Microsoft：變更治理與可靠性門檻" data-link-desc="透過分層變更管理與發布閘門，降低大型 SaaS 平台的系統性回歸風險。">Microsoft：變更治理與可靠性門檻</a></td>
          <td>企業合規 + SLO 治理的對應路徑</td>
      </tr>
  </tbody>
</table>
<p><strong>待補 Nobl9 customer case</strong>：企業 SLO 治理採用案例、OpenSLO adopter。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游概念：<a href="/blog/backend/knowledge-cards/burn-rate/" data-link-title="Burn Rate" data-link-desc="說明 error budget 消耗速度如何支援告警與事故分級">knowledge cards burn-rate</a></li>
<li>平行 vendor：<a href="/blog/backend/06-reliability/vendors/sloth/" data-link-title="Sloth" data-link-desc="OSS SLO generator for Prometheus">Sloth</a></li>
<li>下游能力：<a href="/blog/backend/04-observability/" data-link-title="模組四：可觀測性平台" data-link-desc="整理 log、metric、trace、dashboard 與 alert 的後端操作實務">04 observability</a>、<a href="/blog/backend/08-incident-response/" data-link-title="模組八：事故處理與復盤" data-link-desc="用 IR 領域詞彙建問題節點、以服務級案例庫累積事故脈絡，先建概念與案例庫再進實作交接">08 incident response</a></li>
</ul>
]]></content:encoded></item><item><title>Teleport</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/teleport/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/teleport/</guid><description>&lt;p>Teleport 是 &lt;em>Identity-Aware Proxy + PAM&lt;/em>（Privileged Access Management）、把 SSH / Database / Kubernetes / Windows Desktop / Cloud API / 內部 web app 的 &lt;em>privileged session&lt;/em> 統一收到一個 zero-trust 入口、所有 session 改走 &lt;em>short-lived cert + per-session MFA + 全程錄影&lt;/em>、取代傳統「long-lived SSH key + bastion + 手動 audit」。它跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta&lt;/a> 是兩層職責 — Okta 認證 &lt;em>人是誰&lt;/em>、Teleport 控制 &lt;em>拿到身份後 privileged session 怎麼進、留什麼證據&lt;/em>；典型部署是 &lt;em>Okta SSO into Teleport、Teleport proxies SSH/DB/K8s session&lt;/em>。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Teleport 的核心定位是 &lt;em>infrastructure access plane&lt;/em>、不是 IdP、不是 secret store、也不是 network mesh。它的責任是 &lt;em>把 admin / engineer 對 production 資源的 session 通通走可治理的入口&lt;/em>、每個 session 有 &lt;em>identity-bound short-lived cert&lt;/em>、有 &lt;em>audit log&lt;/em>、有 &lt;em>錄影&lt;/em>、有 &lt;em>MFA gate&lt;/em>。比較對象：&lt;/p>
&lt;ul>
&lt;li>跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta&lt;/a> / Azure AD 等 IdP 比、Teleport 不取代 SSO、而是 &lt;em>把 SSO identity 帶到 infrastructure layer&lt;/em> — Okta 給 user identity + group、Teleport 把這個 identity 翻譯成 SSH cert / DB cert / K8s cert&lt;/li>
&lt;li>跟傳統 bastion + SSH key 比、Teleport 把 &lt;em>long-lived SSH key&lt;/em> 換成 &lt;em>short-lived cert&lt;/em>（預設 TTL 數小時、過期自動失效）、把 &lt;em>看不到的 session&lt;/em> 換成 &lt;em>全程錄影 + searchable audit log&lt;/em>&lt;/li>
&lt;li>跟 HashiCorp Boundary 比、Teleport 走 &lt;em>protocol-aware proxy&lt;/em>（懂 SSH / PostgreSQL / Kubernetes API 協議、可以 decode keystroke 跟 query）、Boundary 走 &lt;em>generic TCP proxy&lt;/em>（協議無感、不能錄 keystroke 但部署更輕）&lt;/li>
&lt;li>跟 Tailscale SSH 比、Tailscale 是 &lt;em>network mesh 加 SSH&lt;/em>、適合小團隊 flat network；Teleport 是 &lt;em>PAM + 多協議 + 跨環境 audit&lt;/em>、適合需要 SOC handoff 的環境&lt;/li>
&lt;li>跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &amp;#43; DDoS &amp;#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare Access&lt;/a> 比、Cloudflare Access 是 &lt;em>application-layer ZTNA&lt;/em>（內部 web app / API 用）、Teleport 是 &lt;em>infrastructure-layer ZTNA&lt;/em>（SSH / DB / K8s 用）、兩者互補&lt;/li>
&lt;/ul>
&lt;p>關鍵張力：&lt;em>PAM 的覆蓋完整度&lt;/em> ↔ &lt;em>operator 摩擦&lt;/em>。Teleport 開越多（per-session MFA、Access Request 要 approval、Device Trust 強制企業裝置）、helpdesk SE 那種「拿到密碼直接進 prod」的 blast radius 越小、但 on-call engineer 在凌晨三點修事故時的摩擦也越大。要根據 &lt;em>資源敏感度分層&lt;/em> 設定、不是一刀切。&lt;/p></description><content:encoded><![CDATA[<p>Teleport 是 <em>Identity-Aware Proxy + PAM</em>（Privileged Access Management）、把 SSH / Database / Kubernetes / Windows Desktop / Cloud API / 內部 web app 的 <em>privileged session</em> 統一收到一個 zero-trust 入口、所有 session 改走 <em>short-lived cert + per-session MFA + 全程錄影</em>、取代傳統「long-lived SSH key + bastion + 手動 audit」。它跟 <a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a> 是兩層職責 — Okta 認證 <em>人是誰</em>、Teleport 控制 <em>拿到身份後 privileged session 怎麼進、留什麼證據</em>；典型部署是 <em>Okta SSO into Teleport、Teleport proxies SSH/DB/K8s session</em>。</p>
<h2 id="服務定位">服務定位</h2>
<p>Teleport 的核心定位是 <em>infrastructure access plane</em>、不是 IdP、不是 secret store、也不是 network mesh。它的責任是 <em>把 admin / engineer 對 production 資源的 session 通通走可治理的入口</em>、每個 session 有 <em>identity-bound short-lived cert</em>、有 <em>audit log</em>、有 <em>錄影</em>、有 <em>MFA gate</em>。比較對象：</p>
<ul>
<li>跟 <a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a> / Azure AD 等 IdP 比、Teleport 不取代 SSO、而是 <em>把 SSO identity 帶到 infrastructure layer</em> — Okta 給 user identity + group、Teleport 把這個 identity 翻譯成 SSH cert / DB cert / K8s cert</li>
<li>跟傳統 bastion + SSH key 比、Teleport 把 <em>long-lived SSH key</em> 換成 <em>short-lived cert</em>（預設 TTL 數小時、過期自動失效）、把 <em>看不到的 session</em> 換成 <em>全程錄影 + searchable audit log</em></li>
<li>跟 HashiCorp Boundary 比、Teleport 走 <em>protocol-aware proxy</em>（懂 SSH / PostgreSQL / Kubernetes API 協議、可以 decode keystroke 跟 query）、Boundary 走 <em>generic TCP proxy</em>（協議無感、不能錄 keystroke 但部署更輕）</li>
<li>跟 Tailscale SSH 比、Tailscale 是 <em>network mesh 加 SSH</em>、適合小團隊 flat network；Teleport 是 <em>PAM + 多協議 + 跨環境 audit</em>、適合需要 SOC handoff 的環境</li>
<li>跟 <a href="/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &#43; DDoS &#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare Access</a> 比、Cloudflare Access 是 <em>application-layer ZTNA</em>（內部 web app / API 用）、Teleport 是 <em>infrastructure-layer ZTNA</em>（SSH / DB / K8s 用）、兩者互補</li>
</ul>
<p>關鍵張力：<em>PAM 的覆蓋完整度</em> ↔ <em>operator 摩擦</em>。Teleport 開越多（per-session MFA、Access Request 要 approval、Device Trust 強制企業裝置）、helpdesk SE 那種「拿到密碼直接進 prod」的 blast radius 越小、但 on-call engineer 在凌晨三點修事故時的摩擦也越大。要根據 <em>資源敏感度分層</em> 設定、不是一刀切。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>Teleport 在 access stack 中承擔哪一段（infrastructure session）、哪些不屬於它（user identity 屬 Okta、long-lived service secret 屬 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a>、application access 可用 Cloudflare Access）</li>
<li>Cluster / Proxy / Auth Service / Node 拓樸的部署選擇（Cloud SaaS vs Self-hosted、Trusted Cluster 跨環境）</li>
<li>Roles + Access Requests + Per-session MFA + Session Recording 四件套的工程化設定（誰能 approve、TTL 多長、錄影存哪）</li>
<li>何時用 Teleport、何時走 Boundary / Tailscale SSH / Cloudflare Access 的取捨</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Teleport deployment 是否健康、最少看四件事：</p>
<ul>
<li><strong>是否還有 long-lived credential 旁路</strong>：production host 是否仍接受 <code>~/.ssh/authorized_keys</code> 的長期 key、DB 是否仍有 shared admin password、K8s kubeconfig 是否還在 engineer laptop 永存 — Teleport 收編失敗的最大訊號是 <em>存在 bypass Teleport 的捷徑</em></li>
<li><strong>Per-session MFA 是否對 sensitive resource 強制</strong>：prod SSH / prod DB / payment system 進 session 時是否每次都 re-MFA、不是「早上登入一次後 8 小時都通行」、role 設定有沒有 <code>require_session_mfa: true</code></li>
<li><strong>Access Request 的 standing privilege 是否收零</strong>：日常 role 是否只有 read-only、所有 write / admin operation 是否走 <em>Access Request</em> + approver gate + TTL、approver 是否 SOC / SRE on-call 而非任意 lead</li>
<li><strong>Session Recording 是否真的可回查</strong>：SSH / K8s / DB session 錄影是否落地 S3 / GCS、是否可在 audit log 透過 user / time / resource 三軸搜尋並回放、recording retention 是否符合合規（金融通常 7 年）</li>
</ul>
<p>四件事任一缺失、就回到 <a href="/blog/backend/07-security-data-protection/identity-access-boundary/" data-link-title="7.2 身分與授權邊界" data-link-desc="以問題驅動方式整理身分、授權、會話與供應商身分鏈">7.2 身分與授權邊界</a> 補設定。最容易踩的是第三點 — Teleport 裝了但日常 role 仍給 standing admin、Access Request 變裝飾、helpdesk SE 場景的 mitigation 等於沒上。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>Cluster + Proxy + Auth Service 拓樸</strong>：Teleport cluster 由三個 first-class component 組成 — <em>Auth Service</em>（CA、簽 cert、存 audit log、policy decision point）、<em>Proxy</em>（user 連線入口、做 protocol translation、把 SSH / DB / K8s request 轉到 Node）、<em>Node</em>（被保護的資源、裝 Teleport agent 或走 agentless 模式）。Cloud（SaaS）把 Auth + Proxy 託管、客戶只管 Node；Self-hosted 三層都自管、適合需要 data residency / FedRAMP 的環境。</p>
<p><strong>多協議 Resource Access</strong>：Teleport 是 <em>protocol-aware proxy</em>、不是 generic TCP tunnel — SSH Access 懂 OpenSSH、Database Access 懂 PostgreSQL / MySQL / MongoDB / Snowflake / Redis wire protocol、Kubernetes Access 懂 K8s API + RBAC impersonation、Desktop Access 懂 RDP、Application Access 懂 HTTP（包 AWS / GCP console 跟內部 web app）。協議感知的價值是 <em>可以錄 keystroke / query / 滑鼠移動</em>、可以做 <em>per-query approval</em>（DB Access 可設「DROP TABLE 要 approver」）、generic proxy 做不到。</p>
<p><strong>Roles + RBAC</strong>：Teleport role 是 YAML 定義的 RBAC policy、控制 <em>誰可以連哪些 resource、用什麼 OS user、執行什麼指令、session TTL 多長、要不要 per-session MFA</em>。Role 跟 Okta group 透過 SAML / OIDC attribute mapping 綁定 — Okta <code>group=sre-prod</code> 自動拿到 Teleport <code>role=prod-ssh-readonly</code>、不用 Teleport 端維護 user list。</p>
<p><strong>Access Requests（JIT approval）</strong>：standing privilege 收零的核心機制 — engineer 平常只有 read-only role、需要 write / admin 時透過 CLI / web UI 開 <em>Access Request</em>、指定 role + reason + TTL、approver 在 Slack / web 收到通知後 approve / deny、approve 後該 user 拿到該 role TTL（例如 4 小時）、過期自動 revoke。對應 <a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/mgm-2023-identity-lateral-impact/" data-link-title="7.R7.1.4 MGM 2023：身分流程被打穿後的營運中斷" data-link-desc="社交工程造成身分邊界失守後，如何演變成可用性與營運衝擊">MGM 2023</a> 的 mitigation — 即使 helpdesk SE 拿到 user 密碼、該 user 也沒有 standing admin 可用、要進 prod 必須額外開 Access Request + approver 看到 reason 異常會 deny。</p>
<p><strong>Per-session MFA</strong>：高敏 session 強制每次連線都 re-MFA、不是登入一次後 session TTL 內都通行。role 設 <code>require_session_mfa: true</code>、user <code>tsh ssh prod-db-01</code> 時會跳 Yubikey / WebAuthn 提示、過了才連得進去。對應 <a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/uber-2022-mfa-fatigue/" data-link-title="7.R7.1.1 Uber 2022：MFA 疲勞與內部工具擴散" data-link-desc="從社交工程到內部工具存取，拆解身分流程與權限邊界的失效點">Uber 2022 MFA Fatigue</a> 的 lesson — 即使 attacker 用 push fatigue 拿到 IdP session、要進 prod infrastructure 還會撞到第二道 MFA。</p>
<p><strong>Session Recording + Audit</strong>：所有 SSH / K8s / DB / Desktop session 全程錄影、SSH 錄 keystroke + output、DB 錄 SQL query、K8s 錄 API call、Desktop 錄畫面。錄影預設存 Auth Service local disk、production 應該設 <em>sync mode</em> 即時寫 S3 / GCS、不要等 session 結束才上傳（attacker 結束前 wipe）。Audit log 走結構化 JSON、可 export 到 <a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / Elastic、是 SOC 的 first-class signal。</p>
<p><strong>Trusted Cluster 跨環境 federation</strong>：dev / staging / prod 各自跑 Teleport cluster、用 <em>Trusted Cluster</em> 建立信任關係、user 從 root cluster 一次 login 就能 <code>tsh ssh --cluster=prod node-01</code>、不用每個環境各 login。設計重點是 <em>root cluster 是 SSO + 政策中心、leaf cluster 是各環境本地控制</em>、leaf 出事不會把 root identity 拖下水。</p>
<p><strong>跟 Okta / GitHub OIDC SSO 整合</strong>：Teleport 不做 user identity、authentication 全部委派給 IdP — Okta 設 SAML app、Teleport 設 SAML connector、user <code>tsh login</code> 跳 Okta 認證後拿 Teleport short-lived cert。GitHub Actions 也可以用 OIDC token 換 Teleport cert（給 CI 用、見下方 Machine ID）、不用埋 GitHub Actions secret。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Teleport</th>
          <th>HashiCorp Boundary</th>
          <th>Tailscale SSH</th>
          <th>Cloudflare Access</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>主要 surface</td>
          <td>Infrastructure（SSH / DB / K8s / Desktop）</td>
          <td>Infrastructure（generic TCP）</td>
          <td>Network mesh + SSH</td>
          <td>Application（web app / API）</td>
      </tr>
      <tr>
          <td>協議感知</td>
          <td>強 — 懂 SSH / DB / K8s / RDP / HTTP</td>
          <td>弱 — generic TCP proxy、不解協議</td>
          <td>弱 — SSH 為主、其他靠 network</td>
          <td>HTTP-only</td>
      </tr>
      <tr>
          <td>Short-lived cert</td>
          <td>強 — 各協議都有專屬 cert（SSH / DB / K8s）</td>
          <td>中 — 主要靠 Vault credential broker</td>
          <td>中 — SSH cert by Tailscale CA</td>
          <td>N/A（HTTP token）</td>
      </tr>
      <tr>
          <td>Session 錄影</td>
          <td>全程 keystroke / query / 畫面</td>
          <td>TCP-level 連線 metadata、不錄內容</td>
          <td>基本 SSH log、不錄 keystroke</td>
          <td>HTTP request log</td>
      </tr>
      <tr>
          <td>JIT access</td>
          <td>Access Request + approver + TTL</td>
          <td>Vault dynamic credential lease</td>
          <td>ACL tag、無 approver workflow</td>
          <td>Policy + identity gate</td>
      </tr>
      <tr>
          <td>Per-session MFA</td>
          <td>第一級支援、role 級別 toggle</td>
          <td>透過 Vault MFA、間接</td>
          <td>透過 Tailscale identity、間接</td>
          <td>App-level MFA（透過 Cloudflare）</td>
      </tr>
      <tr>
          <td>部署模型</td>
          <td>Cloud SaaS / Self-hosted（含 air-gapped）</td>
          <td>Self-hosted（OSS）+ HCP Boundary（SaaS）</td>
          <td>SaaS only</td>
          <td>SaaS only（Cloudflare 邊緣）</td>
      </tr>
      <tr>
          <td>計費</td>
          <td>Per protected resource + MAU、Cloud / Self</td>
          <td>跟 Vault Enterprise 綁定</td>
          <td>Per user / device</td>
          <td>Per user</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>需要 PAM + audit + JIT 的 admin session 治理</td>
          <td>已是 Vault 重度使用者、generic TCP 多</td>
          <td>小團隊 flat network、SSH 為主</td>
          <td>內部 web app / API 走 ZTNA、非 infra</td>
      </tr>
      <tr>
          <td>退場成本</td>
          <td>中 — role YAML / Trusted Cluster 設定多</td>
          <td>中 — Boundary target 設定</td>
          <td>低 — ACL 移植性高</td>
          <td>低 — policy 簡單</td>
      </tr>
  </tbody>
</table>
<p>選 Teleport 的核心訴求：<em>多協議 infrastructure session</em> + <em>session recording + JIT + per-session MFA 是 SOC 必要證據</em> + <em>跨環境 federation</em>（dev / staging / prod / partner）+ <em>願意承擔 cluster 維運成本（self-hosted）或 SaaS 訂閱</em>。純小團隊 flat network 走 Tailscale 更輕、純內部 web app 走 Cloudflare Access 更便宜、純 Vault-driven workflow 走 Boundary 整合更順。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Machine ID — service-to-service short-lived cert</strong>：CI / 內部 worker / cron job 也走 Teleport 拿 short-lived cert、不用埋長期 SSH key 或 DB password。Machine ID agent（<code>tbot</code>）跑在 CI runner、用 IAM role / GitHub OIDC token / Kubernetes service account 證明自己身份、Teleport 簽 short-lived SSH cert / DB cert（TTL 通常 1 小時）。對應 <a href="/blog/backend/07-security-data-protection/vendors/spire/" data-link-title="SPIRE" data-link-desc="SPIFFE Runtime Environment、attested workload identity、short-lived SVID &#43; Trust Bundle、跨組織 federation">SPIRE</a> 的 workload identity 概念、Teleport Machine ID 是 SPIRE 在 infrastructure access surface 的對等實作。</p>
<p><strong>Device Trust — 裝置驗證</strong>：除了 user identity + MFA、Teleport Enterprise 還可以強制 <em>只有企業 enrolled 裝置可以連 prod</em>。裝置透過 TPM / Secure Enclave 註冊 hardware-bound key、Teleport login 時驗證裝置 cert。對應 BYOD 風險 — 即使 attacker 拿到 user credential + MFA token、沒有企業裝置就連不進 prod。</p>
<p><strong>Moderated Session + Session Live View</strong>：高敏 session 設定 <em>需要第二人在線 moderate</em>、SOC analyst 即時看 keystroke、可以 <code>kill session</code>。對應金融 / 政府的「四眼原則」合規要求。Live View 也可以給 SOC 在 incident 進行中即時看 attacker 操作（如果 attacker 不知道被監聽）。</p>
<p><strong>FedRAMP / HIPAA / PCI compliance</strong>：Teleport Enterprise 有 FedRAMP Moderate authorization、Self-hosted 模式可部署 air-gapped 環境、audit log 滿足 HIPAA / PCI 的 access logging 要求。Cloud 版本走 SOC 2 Type II、FedRAMP 版本走 GovCloud 部署。</p>
<p><strong>跟 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a> / <a href="/blog/backend/07-security-data-protection/vendors/spire/" data-link-title="SPIRE" data-link-desc="SPIFFE Runtime Environment、attested workload identity、short-lived SVID &#43; Trust Bundle、跨組織 federation">SPIRE</a> 的職責切分</strong>：Vault 管 <em>service-to-service secret</em>（DB password、API key、PKI CA）、SPIRE 管 <em>workload identity</em>（SVID、跨服務 mTLS）、Teleport 管 <em>人類 admin session + service short-lived cert（透過 Machine ID）</em>。三者互補不重疊 — Vault 不該直接給 engineer 拿 SSH key、SPIRE 不該管 helpdesk admin 怎麼進 prod、Teleport 不該變成長期 API key 倉庫。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>裝了 Teleport 但 engineer 還在用直接 SSH key</strong>：production host 沒收掉 <code>authorized_keys</code>、long-lived key 旁路存在 — host onboarding 流程強制走 Teleport Node enrollment、CI 跑 <code>sshd_config</code> audit 抓 <code>AuthorizedKeysFile</code></li>
<li><strong>Access Request 變裝飾、approver 秒按</strong>：approver 是同團隊 lead 沒看 reason、TTL 設 24 小時等於 standing — approver 改 SOC on-call / cross-team、TTL 預設 1-4 小時、high-impact role 強制兩人 approve</li>
<li><strong>Per-session MFA 開了但 user 抱怨太煩</strong>：所有 role 一刀切要 MFA — 分層：dev / staging role 只要登入 MFA、prod role 才 per-session MFA、payment / PII DB 加 moderated session</li>
<li><strong>Session recording 沒存到 S3、attacker 結束前 wipe</strong>：用 default async mode、recording 留在 Auth Service local — 改 <em>sync mode</em> 即時寫 S3、S3 開 object lock 防刪除</li>
<li><strong>Trusted Cluster leaf 出事拖累 root</strong>：leaf cluster admin 也有 root cluster 權限 — leaf 用獨立 role mapping、leaf admin 不繼承 root identity、leaf 出事只影響該環境</li>
<li><strong>Cloud SaaS 跨區 latency 高</strong>：team 在亞太但 Teleport Cloud 在 us-east — 選 Teleport Cloud 地區 / 改 Self-hosted 部署在自家最近 region</li>
<li><strong>Machine ID cert TTL 短導致 CI 中途失效</strong>：long-running job &gt; cert TTL — 在 job 內定期 <code>tbot</code> renew、或拉長 TTL 但收緊 IAM role binding</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>純內部 web app / API access</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &#43; DDoS &#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare Access</a>（application-layer ZTNA）</td>
      </tr>
      <tr>
          <td>小團隊 flat network + SSH</td>
          <td>Tailscale SSH（network mesh + 輕量 SSH cert）</td>
      </tr>
      <tr>
          <td>已重度使用 Vault、generic TCP 為主</td>
          <td>HashiCorp Boundary（跟 Vault credential broker 整合）</td>
      </tr>
      <tr>
          <td>Service-to-service secret 跟 long-lived</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a> / <a href="/blog/backend/07-security-data-protection/vendors/aws-secrets-manager/" data-link-title="AWS Secrets Manager" data-link-desc="AWS 原生 secret store &#43; 內建 RDS / Redshift rotation Lambda、Resource Policy 跨帳號共享、KMS 加密">AWS Secrets Manager</a></td>
      </tr>
      <tr>
          <td>Workload identity / SVID</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/spire/" data-link-title="SPIRE" data-link-desc="SPIFFE Runtime Environment、attested workload identity、short-lived SVID &#43; Trust Bundle、跨組織 federation">SPIRE</a></td>
      </tr>
      <tr>
          <td>人類 SSO / IdP</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a> / <a href="/blog/backend/07-security-data-protection/vendors/keycloak/" data-link-title="Keycloak" data-link-desc="Open source self-hosted Identity Provider、Red Hat 主導、Realm-based multi-tenancy、適合資料主權與自訂 flow 需求">Keycloak</a></td>
      </tr>
      <tr>
          <td>Session audit log 進 SIEM</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / <a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Teleport role YAML 完整 reference、predicate language 進階用法</li>
<li>Teleport Cloud vs Self-hosted 的 SLA / pricing 細節</li>
<li>Teleport Connect（桌面 client app）的具體操作流程</li>
<li>Air-gapped 部署的 license server 跟 update workflow</li>
<li>各協議的 wire protocol 解析（PostgreSQL / MySQL session 怎麼被 decode）</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>Teleport 沒有 vendor-level 公開事故、但 07 案例庫的 identity / access 系列都是 PAM 設計的對照：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 Teleport 的關係（對照啟示）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/mgm-2023-identity-lateral-impact/" data-link-title="7.R7.1.4 MGM 2023：身分流程被打穿後的營運中斷" data-link-desc="社交工程造成身分邊界失守後，如何演變成可用性與營運衝擊">MGM 2023 Identity Lateral Impact</a></td>
          <td>helpdesk SE 拿到 reset 密碼後直接進 prod admin — Teleport JIT Access Request + per-session MFA 是 first-class mitigation、standing access 收零後 SE 拿到密碼也進不了 prod</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/uber-2022-mfa-fatigue/" data-link-title="7.R7.1.1 Uber 2022：MFA 疲勞與內部工具擴散" data-link-desc="從社交工程到內部工具存取，拆解身分流程與權限邊界的失效點">Uber 2022 MFA Fatigue</a></td>
          <td>push-based MFA fail 後 attacker 拿到 standing internal tool access — Teleport per-session MFA 是第二道 gate（即使 IdP session 被劫、進 prod infra 還要 re-MFA）+ session recording 給 SOC 事後重建</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/cases/okta-support-system-incident-2023/" data-link-title="7.C5 Okta：2023 Support System 事件" data-link-desc="支援系統憑證風險如何擴散到客戶租戶的案例。">Okta Support System 2023</a></td>
          <td>IdP 端 support tool compromise 後 attacker 拿到客戶 session token — 客戶側 Teleport audit log 仍能看到「異常 source IP / device 進 SSH session」、是 IdP 失守時的補位偵測層</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/identity-access-boundary/" data-link-title="7.2 身分與授權邊界" data-link-desc="以問題驅動方式整理身分、授權、會話與供應商身分鏈">7.2 身分與授權邊界</a>、<a href="/blog/backend/07-security-data-protection/secrets-and-machine-credential-governance/" data-link-title="7.6 秘密管理與機器憑證治理" data-link-desc="以問題驅動方式整理 secret、token、key 與機器身份治理">7.6 秘密管理與機器憑證治理</a></li>
<li>平行：HashiCorp Boundary / Tailscale SSH / <a href="/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &#43; DDoS &#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare Access</a></li>
<li>互補：<a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a>（IdP、user identity）、<a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a>（service secret）、<a href="/blog/backend/07-security-data-protection/vendors/spire/" data-link-title="SPIRE" data-link-desc="SPIFFE Runtime Environment、attested workload identity、short-lived SVID &#43; Trust Bundle、跨組織 federation">SPIRE</a>（workload identity）</li>
<li>偵測：<a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / <a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a>（session audit log 入 SIEM）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（compromise session 走 IR workflow）</li>
<li>官方：<a href="https://goteleport.com/docs/">Teleport Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>Sloth</title><link>https://tarrragon.github.io/blog/backend/06-reliability/vendors/sloth/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/06-reliability/vendors/sloth/</guid><description>&lt;p>Sloth 是 OSS Prometheus SLO generator、承擔三個責任：輸入簡單 YAML 定義 SLO、輸出 Prometheus recording rules + alerting rules（multi-window multi-burn-rate）、降低 SLO 維護成本。設計取捨偏向「Prometheus-only + OSS + GitOps-friendly」、適合 Prometheus-based 環境的純 OSS SLO 流程、跟 Nobl9 的 SaaS / multi-source 是不同定位。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>寫 Sloth SLO YAML&lt;/li>
&lt;li>產生 Prometheus recording / alerting rules&lt;/li>
&lt;li>設計 multi-window multi-burn-rate alert&lt;/li>
&lt;li>用 K8s Operator mode 自動同步&lt;/li>
&lt;li>評估從 Sloth 升級到 Nobl9 / OpenSLO 路徑&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑5-分鐘把-sloth-跑起來">最短路徑：5 分鐘把 Sloth 跑起來&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 1. 安裝&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: brew install slok/sloth/sloth / docker run&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="c1"># 2. 寫 SLO spec YAML&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: version: prometheus/v1, service, slos: [{name, objective, sli}]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">&lt;span class="c1"># 3. Generate rules&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: sloth generate -i slo.yaml &amp;gt; rules.yaml&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">9&lt;/span>&lt;span class="cl">&lt;span class="c1"># TODO: 把 rules.yaml 載入 Prometheus&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="日常操作與決策形狀">日常操作與決策形狀&lt;/h2>
&lt;h3 id="slo-yaml-結構">SLO YAML 結構&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>version + service&lt;/li>
&lt;li>slos[]：name / objective / SLI（events / raw）&lt;/li>
&lt;li>Alerting（page / ticket）&lt;/li>
&lt;/ul>
&lt;h3 id="multi-window-multi-burn-rate-alert">Multi-window multi-burn-rate alert&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>Sloth 預設產生 Google SRE recommended alert（4 windows）&lt;/li>
&lt;li>Fast burn / slow burn&lt;/li>
&lt;li>對應 page（urgent）vs ticket（non-urgent）&lt;/li>
&lt;/ul>
&lt;h3 id="generate-rules-workflow">Generate rules workflow&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>CLI generate&lt;/li>
&lt;li>Output: recording rules + alert rules&lt;/li>
&lt;li>放進 Prometheus rule_files 載入&lt;/li>
&lt;/ul>
&lt;h2 id="進階主題按需閱讀">進階主題（按需閱讀）&lt;/h2>
&lt;h3 id="kubernetes-operator-mode">Kubernetes Operator mode&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>Sloth K8s Operator&lt;/li>
&lt;li>PrometheusServiceLevel CRD&lt;/li>
&lt;li>自動 reconcile + 同步 Prometheus rules&lt;/li>
&lt;li>對應 &lt;a href="https://tarrragon.github.io/blog/backend/05-deployment-platform/vendors/kubernetes/" data-link-title="Kubernetes" data-link-desc="Container orchestration 主流、GKE / EKS / AKS / 自管">Kubernetes vendor 頁&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="slo-types">SLO types&lt;/h3>
&lt;p>子議題：&lt;/p>
&lt;ul>
&lt;li>Events-based SLI（好 events / 總 events）&lt;/li>
&lt;li>Raw query SLI（自訂 PromQL）&lt;/li>
&lt;li>對應 PromQL 撰寫&lt;/li>
&lt;/ul>
&lt;h3 id="ci--gitops">CI / GitOps&lt;/h3>
&lt;p>子議題：&lt;/p></description><content:encoded><![CDATA[<p>Sloth 是 OSS Prometheus SLO generator、承擔三個責任：輸入簡單 YAML 定義 SLO、輸出 Prometheus recording rules + alerting rules（multi-window multi-burn-rate）、降低 SLO 維護成本。設計取捨偏向「Prometheus-only + OSS + GitOps-friendly」、適合 Prometheus-based 環境的純 OSS SLO 流程、跟 Nobl9 的 SaaS / multi-source 是不同定位。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>寫 Sloth SLO YAML</li>
<li>產生 Prometheus recording / alerting rules</li>
<li>設計 multi-window multi-burn-rate alert</li>
<li>用 K8s Operator mode 自動同步</li>
<li>評估從 Sloth 升級到 Nobl9 / OpenSLO 路徑</li>
</ol>
<h2 id="最短路徑5-分鐘把-sloth-跑起來">最短路徑：5 分鐘把 Sloth 跑起來</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 1. 安裝</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># TODO: brew install slok/sloth/sloth / docker run</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 2. 寫 SLO spec YAML</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="c1"># TODO: version: prometheus/v1, service, slos: [{name, objective, sli}]</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="c1"># 3. Generate rules</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="c1"># TODO: sloth generate -i slo.yaml &gt; rules.yaml</span>
</span></span><span class="line"><span class="ln">9</span><span class="cl"><span class="c1"># TODO: 把 rules.yaml 載入 Prometheus</span></span></span></code></pre></div><h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<h3 id="slo-yaml-結構">SLO YAML 結構</h3>
<p>子議題：</p>
<ul>
<li>version + service</li>
<li>slos[]：name / objective / SLI（events / raw）</li>
<li>Alerting（page / ticket）</li>
</ul>
<h3 id="multi-window-multi-burn-rate-alert">Multi-window multi-burn-rate alert</h3>
<p>子議題：</p>
<ul>
<li>Sloth 預設產生 Google SRE recommended alert（4 windows）</li>
<li>Fast burn / slow burn</li>
<li>對應 page（urgent）vs ticket（non-urgent）</li>
</ul>
<h3 id="generate-rules-workflow">Generate rules workflow</h3>
<p>子議題：</p>
<ul>
<li>CLI generate</li>
<li>Output: recording rules + alert rules</li>
<li>放進 Prometheus rule_files 載入</li>
</ul>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<h3 id="kubernetes-operator-mode">Kubernetes Operator mode</h3>
<p>子議題：</p>
<ul>
<li>Sloth K8s Operator</li>
<li>PrometheusServiceLevel CRD</li>
<li>自動 reconcile + 同步 Prometheus rules</li>
<li>對應 <a href="/blog/backend/05-deployment-platform/vendors/kubernetes/" data-link-title="Kubernetes" data-link-desc="Container orchestration 主流、GKE / EKS / AKS / 自管">Kubernetes vendor 頁</a></li>
</ul>
<h3 id="slo-types">SLO types</h3>
<p>子議題：</p>
<ul>
<li>Events-based SLI（好 events / 總 events）</li>
<li>Raw query SLI（自訂 PromQL）</li>
<li>對應 PromQL 撰寫</li>
</ul>
<h3 id="ci--gitops">CI / GitOps</h3>
<p>子議題：</p>
<ul>
<li>Sloth 在 CI 跑 generate</li>
<li>Git commit rules.yaml</li>
<li>Prometheus pull rules.yaml</li>
</ul>
<h3 id="vs-pyrra">vs Pyrra</h3>
<p>子議題：</p>
<ul>
<li>Sloth：CLI + Operator、產生 rules</li>
<li>Pyrra：K8s-native CRD、UI 內建</li>
<li>選擇判讀：簡單 / CI-first → Sloth；K8s-native + UI → Pyrra</li>
</ul>
<h3 id="vs-nobl9">vs Nobl9</h3>
<p>子議題：</p>
<ul>
<li>Sloth：OSS / Prometheus-only / 無 SaaS</li>
<li>Nobl9：商業 SaaS / 多 source / governance</li>
<li>升級路徑：OpenSLO YAML 部分相容</li>
</ul>
<h3 id="alert-tuning">Alert tuning</h3>
<p>子議題：</p>
<ul>
<li>Burn rate threshold 調整（依 service criticality）</li>
<li>Inhibition（alert 之間互相壓制）</li>
<li>對應 Alertmanager routing</li>
</ul>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<h3 id="generate-fail">Generate fail</h3>
<p>操作原則：YAML 格式錯 / SLI query 語法錯。判讀：sloth validate。</p>
<h3 id="alert-noise">Alert noise</h3>
<p>操作原則：burn rate threshold 過嚴。</p>
<h3 id="recording-rule-太多">Recording rule 太多</h3>
<p>操作原則：每 SLO 產生 N recording rules、cardinality 累積快。判讀：Prometheus series count。</p>
<h3 id="operator-reconcile-失敗">Operator reconcile 失敗</h3>
<p>操作原則：CRD permission / Prometheus rule API 連不上。</p>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Multi-source</td>
          <td><a href="/blog/backend/06-reliability/vendors/nobl9/" data-link-title="Nobl9" data-link-desc="SLO platform、跨 data source、企業 SLO 治理">Nobl9</a></td>
      </tr>
      <tr>
          <td>K8s-native CRD + UI</td>
          <td>Pyrra</td>
      </tr>
      <tr>
          <td>Vendor 內建 SLO</td>
          <td>Datadog / Grafana / Honeycomb SLO</td>
      </tr>
      <tr>
          <td>純 SaaS</td>
          <td><a href="/blog/backend/06-reliability/vendors/nobl9/" data-link-title="Nobl9" data-link-desc="SLO platform、跨 data source、企業 SLO 治理">Nobl9</a></td>
      </tr>
      <tr>
          <td>完整 OpenSLO</td>
          <td>OpenSLO + 對應 generator</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>PromQL 語法基礎</li>
<li>Prometheus alerting rule 內部</li>
<li>Sloth 完整 CLI option</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<table>
  <thead>
      <tr>
          <th>案例方向</th>
          <th>對應主題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/06-reliability/cases/google/error-budget-policy-and-release-gating/" data-link-title="Google：Error Budget 政策如何決定發布節奏" data-link-desc="把 SLO 消耗量轉成 release gate，讓可靠性與交付速度共用同一套決策語言。">Google：Error Budget 與 Release Gating</a></td>
          <td>SLI / SLO 原典、用來生成 Prometheus rule 的對齊對象</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/06-reliability/cases/honeycomb/burn-rate-driven-reliability-operations/" data-link-title="Honeycomb：以 Burn Rate 驅動的可靠性操作" data-link-desc="把 SLO burn rate 直接連到值班決策與改善優先序，降低高噪音告警造成的判讀失真。">Honeycomb：Burn Rate 驅動可靠性</a></td>
          <td>multi-window multi-burn-rate alert 的 PromQL 落地語意</td>
      </tr>
  </tbody>
</table>
<p><strong>Case 庫稀薄</strong>：本 cases/ 目錄目前沒有以 Sloth 為主軸的案例。</p>
<ul>
<li><strong>待補 Sloth customer case</strong>：Prometheus 重度團隊採用、Kubernetes Operator 落地案例</li>
<li><strong>候選 case</strong>：Spotify（Backstage + Prometheus 結合 SLO metadata）、LinkedIn（self-service metrics + SLO rule generation）— 若未來收錄需先在 cases/ 補正文</li>
</ul>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游概念：<a href="/blog/backend/knowledge-cards/burn-rate/" data-link-title="Burn Rate" data-link-desc="說明 error budget 消耗速度如何支援告警與事故分級">knowledge cards burn-rate</a></li>
<li>平行 vendor：<a href="/blog/backend/06-reliability/vendors/nobl9/" data-link-title="Nobl9" data-link-desc="SLO platform、跨 data source、企業 SLO 治理">Nobl9</a>、<a href="/blog/backend/04-observability/vendors/prometheus/" data-link-title="Prometheus" data-link-desc="Pull-based metrics 主流 OSS、PromQL 與 alerting">Prometheus</a></li>
<li>下游能力：<a href="/blog/backend/04-observability/" data-link-title="模組四：可觀測性平台" data-link-desc="整理 log、metric、trace、dashboard 與 alert 的後端操作實務">04 observability</a>、<a href="/blog/backend/04-observability/vendors/prometheus/" data-link-title="Prometheus" data-link-desc="Pull-based metrics 主流 OSS、PromQL 與 alerting">Alertmanager</a></li>
</ul>
]]></content:encoded></item><item><title>HashiCorp Boundary</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/boundary/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/boundary/</guid><description>&lt;p>HashiCorp Boundary 是 &lt;em>identity-based access broker&lt;/em>、把「使用者要連到某個內部資源」這件事拆成 &lt;em>identity 驗證&lt;/em> + &lt;em>target 授權&lt;/em> + &lt;em>動態 credential 注入&lt;/em> 三段、由 Boundary 統一仲介。它跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault&lt;/a> 同生態、設計上預期兩者組合：&lt;em>Boundary 控制誰能連到哪個資源、Vault 提供連線當下的 short-lived credential&lt;/em>。單獨用 Boundary 而不接 Vault、會失去它最大的價值。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Boundary 的核心定位是 &lt;em>連線層級的存取仲介&lt;/em>、不是傳統的 bastion host、也不是 identity-aware proxy。它把 &lt;em>連線發起權&lt;/em> 收回控制面、user 不需要直接拿到 SSH key / DB password / cloud token、只需要對 Boundary 認證、由 Boundary 把 &lt;em>target 資源的網路位置&lt;/em> + &lt;em>Vault 動態簽發的 credential&lt;/em> 在 session 開始時注入連線。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/teleport/" data-link-title="Teleport" data-link-desc="Identity-Aware Proxy &amp;#43; PAM、SSH / DB / K8s / Desktop session 統一 short-lived cert &amp;#43; session recording &amp;#43; JIT、跟 Okta / Vault 互補">Teleport&lt;/a> 比、Boundary 走 &lt;em>network broker + dynamic credential injection&lt;/em>、Teleport 走 &lt;em>identity-aware proxy + session recording&lt;/em>。Teleport 是 &lt;em>看見每一個指令、可重播&lt;/em> 的 PAM；Boundary 是 &lt;em>不存 credential、不錄影、靠 Vault short-lived token 來控制 blast radius&lt;/em>。兩者解的是同一類問題（內部資源存取治理）、但工程取捨完全不同 — Boundary 把「攻擊者拿到 credential 也只有 minutes-level 有效期」當主要防線、Teleport 把「全部 session 留下不可否認證據」當主要防線。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/tailscale-ssh/" data-link-title="Tailscale SSH" data-link-desc="WireGuard-based zero-trust mesh &amp;#43; identity-bound SSH、ACL JSON policy、developer-friendly、跟 IdP integration 取代 SSH key">Tailscale SSH&lt;/a> 比、Tailscale 走 mesh network + SSH-only、無 credential 仲介、無 dynamic injection；Boundary 走 broker 模式、支援 SSH / RDP / DB / TCP / HTTP 等多協議、且 credential 從 Vault 拉。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/cloudflare-access/" data-link-title="Cloudflare Access" data-link-desc="Zero Trust Network Access (ZTNA)、取代 VPN 的 application-layer access、Argo Tunnel &amp;#43; Device Posture &amp;#43; IdP integration">Cloudflare Access&lt;/a> 比、Cloudflare 走 &lt;em>Zero Trust portal + identity-aware reverse proxy&lt;/em>、是 HTTP-first；Boundary 是 &lt;em>protocol-agnostic broker&lt;/em>、原生支援非 HTTP 協議（DB / SSH / RDP）。&lt;/p></description><content:encoded><![CDATA[<p>HashiCorp Boundary 是 <em>identity-based access broker</em>、把「使用者要連到某個內部資源」這件事拆成 <em>identity 驗證</em> + <em>target 授權</em> + <em>動態 credential 注入</em> 三段、由 Boundary 統一仲介。它跟 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a> 同生態、設計上預期兩者組合：<em>Boundary 控制誰能連到哪個資源、Vault 提供連線當下的 short-lived credential</em>。單獨用 Boundary 而不接 Vault、會失去它最大的價值。</p>
<h2 id="服務定位">服務定位</h2>
<p>Boundary 的核心定位是 <em>連線層級的存取仲介</em>、不是傳統的 bastion host、也不是 identity-aware proxy。它把 <em>連線發起權</em> 收回控制面、user 不需要直接拿到 SSH key / DB password / cloud token、只需要對 Boundary 認證、由 Boundary 把 <em>target 資源的網路位置</em> + <em>Vault 動態簽發的 credential</em> 在 session 開始時注入連線。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/teleport/" data-link-title="Teleport" data-link-desc="Identity-Aware Proxy &#43; PAM、SSH / DB / K8s / Desktop session 統一 short-lived cert &#43; session recording &#43; JIT、跟 Okta / Vault 互補">Teleport</a> 比、Boundary 走 <em>network broker + dynamic credential injection</em>、Teleport 走 <em>identity-aware proxy + session recording</em>。Teleport 是 <em>看見每一個指令、可重播</em> 的 PAM；Boundary 是 <em>不存 credential、不錄影、靠 Vault short-lived token 來控制 blast radius</em>。兩者解的是同一類問題（內部資源存取治理）、但工程取捨完全不同 — Boundary 把「攻擊者拿到 credential 也只有 minutes-level 有效期」當主要防線、Teleport 把「全部 session 留下不可否認證據」當主要防線。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/tailscale-ssh/" data-link-title="Tailscale SSH" data-link-desc="WireGuard-based zero-trust mesh &#43; identity-bound SSH、ACL JSON policy、developer-friendly、跟 IdP integration 取代 SSH key">Tailscale SSH</a> 比、Tailscale 走 mesh network + SSH-only、無 credential 仲介、無 dynamic injection；Boundary 走 broker 模式、支援 SSH / RDP / DB / TCP / HTTP 等多協議、且 credential 從 Vault 拉。跟 <a href="/blog/backend/07-security-data-protection/vendors/cloudflare-access/" data-link-title="Cloudflare Access" data-link-desc="Zero Trust Network Access (ZTNA)、取代 VPN 的 application-layer access、Argo Tunnel &#43; Device Posture &#43; IdP integration">Cloudflare Access</a> 比、Cloudflare 走 <em>Zero Trust portal + identity-aware reverse proxy</em>、是 HTTP-first；Boundary 是 <em>protocol-agnostic broker</em>、原生支援非 HTTP 協議（DB / SSH / RDP）。</p>
<p>關鍵張力：<em>Boundary + Vault 組合的工程複雜度</em> ↔ <em>不靠 session recording 的審計可信度</em>。已用 HashiCorp 生態（Terraform + Vault + Consul）的組織、Boundary 是 <em>最後一塊拼圖</em>；沒用 Vault 的組織用 Boundary 等於只剩一個 bastion 的弱化版、不如直接走 Teleport。合規強要求 keystroke audit 的場域、Boundary 預設不錄 session、要走 Enterprise add-on 才有、不如 Teleport first-class。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>Boundary 在 PAM stack 中承擔哪一段（broker / target / session）、哪些要外接（Vault 給 credential、IdP 給 auth、Enterprise add-on 給 session recording）</li>
<li>Controller + Worker + Multi-hop 拓樸怎麼對應實際網路分段（DMZ / internal / restricted subnet）</li>
<li>Vault Credential Library 怎麼設計、誰負責 host catalog、role / scope 怎麼劃</li>
<li>何時用 Boundary、何時改走 Teleport / Tailscale SSH / Cloudflare Access 的取捨</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Boundary deployment 是否健康、最少看四件事：</p>
<ul>
<li><strong>是否真的接 Vault</strong>：Credential Library 是否從 Vault 拉 dynamic credential（DB / SSH cert / cloud token）、session 結束是否自動 revoke、還是仍有 static credential 存在 Boundary 或人手裡</li>
<li><strong>Scope 結構是否反映組織邊界</strong>：Global → Org → Project 的三層 scope、Org 對應 BU / tenant、Project 對應應用或環境；role / grant 是否按 Project 切、還是全部塞 Global scope 變共享密碼</li>
<li><strong>Worker 拓樸是否反映網路分段</strong>：Controller 在 control plane、Worker 在每個網路 segment（DMZ / internal / restricted DB subnet）、Multi-hop 是否走 segment-aware routing、還是把所有 worker 塞同一個 VPC</li>
<li><strong>Auth Method 是不是 IdP-backed</strong>：OIDC（<a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a> / Azure AD / Google）/ LDAP / Password — production 應該走 OIDC、Password auth method 只該存在於 break-glass</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/07-security-data-protection/blue-team/" data-link-title="7.B 防守者視角（藍隊）與控制面驗證" data-link-desc="從防守者角度整理控制面、偵測路由、驗證策略與演練回寫">Privileged Access and Just-in-Time Authority</a> 邊界的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>Controller + Worker 拓樸</strong>：Controller 負責 control plane（auth、policy、session 管理、API endpoint）、Worker 負責 data plane（實際代理連線到 target）。Controller 通常 cluster 部署（3 個以上、HA）、Worker 按網路 segment 分散部署。Controller 從不直接連 target — user 跟 Controller 認證、Controller 告訴 user 走哪個 Worker、Worker 才實際代理連線。</p>
<p><strong>Target + Host Set + Host Catalog</strong>：Target 是 user 看到的「可連對象」抽象（例如 <code>prod-db-cluster</code>）、Host Set 是 Target 對應的實際 host 集合、Host Catalog 是 host 的來源（static list 或從 cloud auto-discover）。Dynamic Host Catalog 可以從 AWS / Azure / GCP 用 tag 自動 enroll host、不需要手動維護 host list — 例如 <code>tag:role=prod-db</code> 的 EC2 自動進 <code>prod-db-cluster</code> Target。</p>
<p><strong>Credential Library（Vault 整合）</strong>：Boundary 不存 credential、靠 Credential Library 從 Vault 拉。設計支援三種：<em>Vault Generic</em>（拉任意 Vault secret path）、<em>Vault SSH Certificate</em>（拉 Vault SSH CA 簽發的 short-lived cert）、<em>Vault Database</em>（拉 Vault Database Secret Engine 簽發的 DB user / password）。session 開始時 Boundary 拉 credential、注入連線、session 結束時 Vault 自動 revoke。這是 Boundary 的核心價值 — 沒接 Vault 等於丟掉 dynamic credential rotation 這個最大賣點。</p>
<p><strong>Auth Method</strong>：支援 OIDC（OAuth2 / OpenID Connect、給 <a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a> / Azure AD / Google）、LDAP（給 internal directory）、Password（給 break-glass）。Production 預設走 OIDC、跟 IdP 同源、user lifecycle 隨 IdP 變動（離職 IdP 鎖、Boundary 自動失效）。Password auth method 只該存在於 break-glass account、密碼進 Vault、單獨 audit。</p>
<p><strong>Role + Grant + Scope</strong>：Boundary 的權限模型是 <em>scope-bound role</em>、role 屬於某個 scope（Global / Org / Project）、grant 是 role 內的具體權限（例如 <code>target=&lt;id&gt;;actions=authorize-session</code>）。Scope 三層分別對應：<em>Global</em> — platform-level admin、<em>Org</em> — 某 BU 或 tenant、<em>Project</em> — 應用或環境（prod / staging / dev）。設計時把 role 按 Project 切、不要全部塞 Global scope 變共享密碼。</p>
<p><strong>Session 生命週期</strong>：user 對 Boundary 認證（OIDC）→ list authorized target → 對某 target 發起 <code>authorize-session</code>、Boundary 從 Credential Library 拉 credential → user 透過 Boundary CLI / Desktop / SDK 連線、實際走 Worker 代理 → session 有 <em>max duration</em>（預設 8 小時、可調短）、過期自動斷 + Vault credential revoke。session metadata（誰、何時、target、worker、duration）一律 audit log。</p>
<p><strong>Multi-hop Worker</strong>：跨網路 segment（例如 user 在 corp 網、target 在 DMZ → internal → restricted DB subnet）時、Boundary 支援 worker chain — corp Worker 連到 DMZ Worker、DMZ Worker 連到 internal Worker、internal Worker 連到 DB。每段 worker 只看得到下一段、不需要 VPN trunk 把整個網路打通。這是 Boundary 相對 Teleport / Tailscale 的網路工程優勢、特別適合金融 / 政府 / 製造業的多層網路分段。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>HashiCorp Boundary</th>
          <th>Teleport</th>
          <th>Tailscale SSH</th>
          <th>Cloudflare Access</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>核心模式</td>
          <td>Network broker + dynamic credential injection</td>
          <td>Identity-aware proxy + session recording</td>
          <td>Mesh VPN + SSH CA</td>
          <td>Zero Trust portal + identity-aware proxy</td>
      </tr>
      <tr>
          <td>Credential 處理</td>
          <td>從 Vault 拉 short-lived、不存</td>
          <td>Teleport CA 簽發 short-lived cert</td>
          <td>Tailscale SSH CA 簽發</td>
          <td>OAuth token、無 SSH credential 處理</td>
      </tr>
      <tr>
          <td>Session recording</td>
          <td>Enterprise add-on（2023+、非 first-class）</td>
          <td>First-class（SSH / kubectl / DB 都錄）</td>
          <td>無</td>
          <td>無</td>
      </tr>
      <tr>
          <td>協議支援</td>
          <td>SSH / RDP / DB（Postgres / MySQL）/ TCP / HTTP</td>
          <td>SSH / kubectl / DB / RDP / Web Apps</td>
          <td>SSH only（mesh 內任意 TCP）</td>
          <td>HTTP / SSH（透過 cloudflared）/ RDP</td>
      </tr>
      <tr>
          <td>部署模型</td>
          <td>Self-hosted (OSS / Enterprise) / HCP (HashiCorp)</td>
          <td>Self-hosted / Teleport Cloud</td>
          <td>SaaS only</td>
          <td>SaaS only</td>
      </tr>
      <tr>
          <td>網路拓樸</td>
          <td>Controller + Worker、Multi-hop 跨 segment 友善</td>
          <td>Proxy + Agent、單層 proxy</td>
          <td>Mesh、所有節點對等</td>
          <td>Cloudflare edge + cloudflared tunnel</td>
      </tr>
      <tr>
          <td>IdP 整合</td>
          <td>OIDC / LDAP / Password</td>
          <td>OIDC / SAML / GitHub</td>
          <td>OIDC（Okta / Google / Azure）</td>
          <td>OIDC / SAML / 內建 IdP</td>
      </tr>
      <tr>
          <td>跟其他 vendor 鎖</td>
          <td>預設假設用 Vault、單獨用價值有限</td>
          <td>獨立完整、不依賴特定 secret store</td>
          <td>獨立、Tailscale 生態</td>
          <td>獨立、Cloudflare 生態</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>已用 HashiCorp 生態 + 多協議 + 多層網路分段</td>
          <td>強合規 + session audit + kubectl-heavy</td>
          <td>小團隊 + SSH-only + 不要 PAM 複雜度</td>
          <td>Cloud-native + Zero Trust portal + HTTP-first</td>
      </tr>
      <tr>
          <td>退場成本</td>
          <td>中 — Vault 整合複雜、target / role / scope 量多</td>
          <td>中 — Teleport-specific config + recording</td>
          <td>低 — Tailscale 拆掉就回 plain SSH</td>
          <td>低 — Cloudflare 拆掉就回 origin</td>
      </tr>
  </tbody>
</table>
<p>選 Boundary 的核心訴求：<em>已用 HashiCorp 生態（特別是 Vault）</em> + <em>多協議內部資源（不只 SSH、還有 DB / RDP / TCP）</em> + <em>多層網路分段需要 Multi-hop</em>、可以接受 session recording 不是 first-class。沒用 Vault 的組織、Boundary 失去最大價值、應該直接走 Teleport。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Multi-hop Worker 跟網路分段</strong>：金融 / 政府常見三段網路（corp → DMZ → restricted）、傳統做法是打 VPN trunk 把整個網路扁平化、accept 大 blast radius。Boundary 用 worker chain 反向 — 每個 segment 部署一個 worker、worker 之間用 mTLS 認證、user 只進 corp worker、後面 hop 由 Boundary control plane 編排。每段 worker 不知道後一段的 target 細節、只知道下一段 worker 的位置。配對 <a href="/blog/backend/07-security-data-protection/blue-team/" data-link-title="7.B 防守者視角（藍隊）與控制面驗證" data-link-desc="從防守者角度整理控制面、偵測路由、驗證策略與演練回寫">Segmentation and Blast Radius Containment</a> 的章節原則。</p>
<p><strong>Dynamic Host Catalog</strong>：手動維護 host list 在 cloud-native 環境會壞 — auto-scaling group 起一台新 EC2、沒人去 Boundary 加 target。Dynamic Host Catalog 配 cloud provider plugin（AWS / Azure / GCP）、用 tag 自動 enroll：例如 <code>tag:env=prod tag:role=app</code> 的 EC2 自動進 <code>prod-app</code> Target、scale-down 也自動移除。這配 IaC（<a href="/blog/backend/05-deployment-platform/vendors/terraform/" data-link-title="Terraform / OpenTofu" data-link-desc="Infrastructure as Code 主流工具">Terraform</a> 管 tag）是 HashiCorp 生態一致性的核心賣點。</p>
<p><strong>Session Recording（Enterprise 才有）</strong>：2023+ Boundary Enterprise 引入 session recording、支援 SSH 跟 RDP 的 keystroke + screen recording、output 加密存到 S3 / Azure Blob、metadata 走 audit。OSS Community Edition 沒有、只記 session metadata（who / when / what target / how long）。組織要 session recording 但又要 Boundary、要評估 Enterprise license cost vs Teleport license cost — 通常 Teleport 在 session recording 場景成本效益更好。</p>
<p><strong>Vault credential brokering 設計</strong>：Boundary 連 Vault 的設計支援多種 secret engine — Database（Postgres / MySQL / Redis 等、簽 short-lived DB user）、SSH Certificate（簽 short-lived SSH cert）、AWS / Azure / GCP（簽 cloud STS token）、KV v2（拉靜態 secret、不推薦）。Production 預設用 dynamic engine、不要用 KV v2 — 靜態 secret 失去 Boundary 最大價值。Vault namespace / policy 設計要對齊 Boundary scope、否則 cross-scope credential 暴露變大問題。</p>
<p><strong>HCP Boundary（HashiCorp Cloud Platform）</strong>：HashiCorp 託管的 SaaS 版、Controller 由 HashiCorp 管、user 只部署 Worker 到自己網路。優點是省去 Controller HA / upgrade 維運；缺點是 control plane 在 HashiCorp 雲、合規敏感場域要評估 data residency。SMB / 中型團隊適合走 HCP、大型 enterprise 通常 Self-hosted。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Session 拿到 credential 但 target 連不上</strong>：Worker 跟 target 之間網路不通、或 Worker 沒部署到 target 所在 segment — 檢查 Worker tag 跟 Target worker_filter、用 <code>boundary workers list</code> 確認 Worker 健康</li>
<li><strong>OIDC login 失敗</strong>：IdP redirect URI 沒對齊、或 IdP signing key 過期 — 對照 <a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/microsoft-storm-0558-2023-signing-key-chain/" data-link-title="7.R7.1.5 Microsoft Storm-0558 2023：簽章金鑰鏈與郵件存取" data-link-desc="從簽章金鑰保護失效到雲端郵件存取，拆解身分信任鏈的關鍵控制點">Microsoft Storm-0558</a> 的啟示、Boundary OIDC auth method 依賴上游 IdP signing key、IdP 端 key rotation 不對 Boundary 通知會整批 session 認不過</li>
<li><strong>Vault credential 拉不到 / 過期太快</strong>：Boundary 服務帳戶在 Vault 的 policy 沒給 <code>creds/&lt;role&gt;</code> 權限、或 Vault 簽的 credential TTL 短於 session max duration — 對齊 TTL、加 Vault telemetry alert credential issuance 失敗</li>
<li><strong>Multi-hop 連線中斷</strong>：中間 hop 的 Worker 健康但 connection drop — 通常是中間 segment 的 firewall idle timeout 短於 session activity gap、調 firewall 或在 client 端開 keepalive</li>
<li><strong>Target 量爆炸 / role 管不動</strong>：所有 target 塞 Global scope、role 量線性漲 — 重構 scope 結構、按 Org / Project 切、role 從 Global 移到 Project 層</li>
<li><strong>Dynamic Host Catalog 漏 host</strong>：cloud tag 沒打 / IAM 沒給 Boundary 描述權限 — 檢查 cloud plugin 的 service account permission、加 catalog sync error 的 alert</li>
<li><strong>OSS Community 升 Enterprise 才發現缺 feature</strong>：選 OSS 之前沒確認需求 — session recording / SAML / 高級 RBAC / multi-region HA 都是 Enterprise 才有、評估時就要列清楚</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>強合規要 session recording / keystroke audit</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/teleport/" data-link-title="Teleport" data-link-desc="Identity-Aware Proxy &#43; PAM、SSH / DB / K8s / Desktop session 統一 short-lived cert &#43; session recording &#43; JIT、跟 Okta / Vault 互補">Teleport</a></td>
      </tr>
      <tr>
          <td>小團隊 + SSH-only + 不要 PAM 複雜度</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/tailscale-ssh/" data-link-title="Tailscale SSH" data-link-desc="WireGuard-based zero-trust mesh &#43; identity-bound SSH、ACL JSON policy、developer-friendly、跟 IdP integration 取代 SSH key">Tailscale SSH</a></td>
      </tr>
      <tr>
          <td>Cloud-native + Zero Trust portal</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/cloudflare-access/" data-link-title="Cloudflare Access" data-link-desc="Zero Trust Network Access (ZTNA)、取代 VPN 的 application-layer access、Argo Tunnel &#43; Device Posture &#43; IdP integration">Cloudflare Access</a></td>
      </tr>
      <tr>
          <td>Kubernetes kubectl-first PAM</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/teleport/" data-link-title="Teleport" data-link-desc="Identity-Aware Proxy &#43; PAM、SSH / DB / K8s / Desktop session 統一 short-lived cert &#43; session recording &#43; JIT、跟 Okta / Vault 互補">Teleport</a>（kubectl proxy first-class）</td>
      </tr>
      <tr>
          <td>Secret storage / rotation 核心</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a>（Boundary 的搭檔）</td>
      </tr>
      <tr>
          <td>IdP / SSO 治理</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a> / Azure AD</td>
      </tr>
      <tr>
          <td>Cloud IAM role assumption</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM</a> / 對應雲</td>
      </tr>
      <tr>
          <td>事故路由</td>
          <td><a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Boundary CLI / Desktop / Terraform provider 的完整指令 reference</li>
<li>HCP Boundary 跟 Self-hosted 的功能對照細節（HashiCorp 官方有 matrix）</li>
<li>Vault 內部的 secret engine 設計（在 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a> 頁）</li>
<li>OIDC / SAML 協議本身的攻擊面（<a href="/blog/backend/07-security-data-protection/identity-access-boundary/" data-link-title="7.2 身分與授權邊界" data-link-desc="以問題驅動方式整理身分、授權、會話與供應商身分鏈">2.3 SSO 攻擊面</a>）</li>
<li>Network segmentation 的整體設計（<a href="/blog/backend/07-security-data-protection/blue-team/" data-link-title="7.B 防守者視角（藍隊）與控制面驗證" data-link-desc="從防守者角度整理控制面、偵測路由、驗證策略與演練回寫">Segmentation and Blast Radius Containment</a>）</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>Boundary 在 07 案例庫沒有直接 vendor-level 事件、但 PAM / credential rotation / IdP 相關 case 都是它的設計取捨對照：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 Boundary 的關係（對照啟示）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/cases/failure-credential-rotation-without-scope/" data-link-title="7.C9 反例：憑證輪替未分 Scope" data-link-desc="憑證輪替若未分域分批，容易造成跨系統連鎖中斷。">Failure: Credential Rotation Without Scope</a></td>
          <td>Boundary + Vault Credential Library 直接解此 case 的 scope map 問題 — 每 session 拿 Vault 簽的 short-lived credential、session 結束自動 revoke、不需要 batch rotation、scope map 由 Vault policy + Boundary role 雙向約束</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/mgm-2023-identity-lateral-impact/" data-link-title="7.R7.1.4 MGM 2023：身分流程被打穿後的營運中斷" data-link-desc="社交工程造成身分邊界失守後，如何演變成可用性與營運衝擊">MGM 2023 Identity Lateral Impact</a></td>
          <td>helpdesk 走 SE 拿到 reset 後的密碼、但 Boundary 仍要求 session 開始時拿 Vault dynamic credential、attacker 在 Vault policy 端被擋；前提是 Boundary OIDC auth method 不依賴可被 SE 重置的 password、IdP 要走 phishing-resistant MFA</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/microsoft-storm-0558-2023-signing-key-chain/" data-link-title="7.R7.1.5 Microsoft Storm-0558 2023：簽章金鑰鏈與郵件存取" data-link-desc="從簽章金鑰保護失效到雲端郵件存取，拆解身分信任鏈的關鍵控制點">Microsoft Storm-0558 Signing Key Chain</a></td>
          <td>Boundary OIDC auth method 依賴上游 IdP signing key、IdP 出事時 Boundary access 也要 rotate；對應啟示是 <em>broker 的 trust chain 取決於上游 IdP</em>、不要把 OIDC 當無責任接口</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/data-exfiltration/snowflake-2024-credential-abuse/" data-link-title="7.R7.4.2 Snowflake 2024：憑證濫用與資料竊取" data-link-desc="外洩憑證與 MFA 缺口如何在資料平台形成高風險外送事件">Snowflake 2024 Credential Abuse</a></td>
          <td>static credential 在離職 / 外洩後仍可用是核心問題、Boundary + Vault Database Secret Engine 直接消除 static credential 存在、改成每 session 簽 short-lived DB user</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/blue-team/" data-link-title="7.B 防守者視角（藍隊）與控制面驗證" data-link-desc="從防守者角度整理控制面、偵測路由、驗證策略與演練回寫">Privileged Access and JIT Authority (section)</a></td>
          <td>Boundary 的 <em>authorize-session</em> 模型是 JIT authority 的具體實作、session 期限 + Vault TTL 雙重約束 blast radius</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/blue-team/" data-link-title="7.B 防守者視角（藍隊）與控制面驗證" data-link-desc="從防守者角度整理控制面、偵測路由、驗證策略與演練回寫">7.B Privileged Access and JIT Authority</a>、<a href="/blog/backend/07-security-data-protection/blue-team/" data-link-title="7.B 防守者視角（藍隊）與控制面驗證" data-link-desc="從防守者角度整理控制面、偵測路由、驗證策略與演練回寫">7.B Segmentation and Blast Radius Containment</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/teleport/" data-link-title="Teleport" data-link-desc="Identity-Aware Proxy &#43; PAM、SSH / DB / K8s / Desktop session 統一 short-lived cert &#43; session recording &#43; JIT、跟 Okta / Vault 互補">Teleport</a>、<a href="/blog/backend/07-security-data-protection/vendors/tailscale-ssh/" data-link-title="Tailscale SSH" data-link-desc="WireGuard-based zero-trust mesh &#43; identity-bound SSH、ACL JSON policy、developer-friendly、跟 IdP integration 取代 SSH key">Tailscale SSH</a>、<a href="/blog/backend/07-security-data-protection/vendors/cloudflare-access/" data-link-title="Cloudflare Access" data-link-desc="Zero Trust Network Access (ZTNA)、取代 VPN 的 application-layer access、Argo Tunnel &#43; Device Posture &#43; IdP integration">Cloudflare Access</a></li>
<li>搭檔：<a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a>（Credential Library 核心）、<a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a>（OIDC IdP）</li>
<li>跨類：<a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM</a>（cloud target 的 STS token 來源）、<a href="/blog/backend/05-deployment-platform/vendors/terraform/" data-link-title="Terraform / OpenTofu" data-link-desc="Infrastructure as Code 主流工具">Terraform</a>（target / scope / role 進 IaC）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（Boundary audit log → SIEM → IR routing）、<a href="/blog/backend/07-security-data-protection/identity-access-boundary/" data-link-title="7.2 身分與授權邊界" data-link-desc="以問題驅動方式整理身分、授權、會話與供應商身分鏈">2.3 SSO 攻擊面</a></li>
<li>官方：<a href="https://developer.hashicorp.com/boundary">Boundary Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>Tailscale SSH</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/tailscale-ssh/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/tailscale-ssh/</guid><description>&lt;p>Tailscale 是 WireGuard-based zero-trust mesh VPN、Tailscale SSH 是其上的 SSH on overlay network 模組。核心 mindset 是 &lt;em>不用 SSH key、不用 jump host&lt;/em>：所有 device 加入同一個 tailnet、ACL 控制誰能 SSH 到誰、user identity 從 Tailscale 的 IdP 整合（&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta&lt;/a> / Google / Microsoft / GitHub SSO）來。它跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/teleport/" data-link-title="Teleport" data-link-desc="Identity-Aware Proxy &amp;#43; PAM、SSH / DB / K8s / Desktop session 統一 short-lived cert &amp;#43; session recording &amp;#43; JIT、跟 Okta / Vault 互補">Teleport&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/boundary/" data-link-title="HashiCorp Boundary" data-link-desc="Identity-based access broker、跟 Vault 同生態組合（Boundary 控連線 / Vault 給 credential）、Multi-hop Worker 跨網路分段">Boundary&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/cloudflare-access/" data-link-title="Cloudflare Access" data-link-desc="Zero Trust Network Access (ZTNA)、取代 VPN 的 application-layer access、Argo Tunnel &amp;#43; Device Posture &amp;#43; IdP integration">Cloudflare Access&lt;/a> 的差異在 &lt;em>網路模型 + identity binding + audit 深度&lt;/em>、SSH 管理能力本身都具備 — Tailscale 走 overlay mesh + identity-bound SSH，Teleport 走 Identity-Aware Proxy + first-class session recording，Boundary 走 network broker + dynamic credential。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Tailscale 的核心定位是 &lt;em>WireGuard overlay mesh + identity-bound 連線&lt;/em>、Tailscale SSH 是其上 &lt;em>取代 sshd 的 SSH 模組&lt;/em>。底層是 Tailscale daemon（每台 device 跑、建立 WireGuard tunnel）+ Tailscale control plane（管 ACL、key exchange、IdP integration、node enrollment）。Tailscale SSH 不是把 OpenSSH 套上 VPN — 它是把 SSH server 換成 Tailscale daemon 內建版本、用 tailnet identity 取代 SSH key、ACL 跟 sshd 設定脫鉤。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/teleport/" data-link-title="Teleport" data-link-desc="Identity-Aware Proxy &amp;#43; PAM、SSH / DB / K8s / Desktop session 統一 short-lived cert &amp;#43; session recording &amp;#43; JIT、跟 Okta / Vault 互補">Teleport&lt;/a> 比、Tailscale 走 &lt;em>zero-config + developer-friendly&lt;/em>、Teleport 走 &lt;em>audit-first + compliance-friendly&lt;/em> — Teleport session recording / RBAC / approval workflow 是 first-class、Tailscale Enterprise 才補 session recording、approval workflow 偏簡單。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/boundary/" data-link-title="HashiCorp Boundary" data-link-desc="Identity-based access broker、跟 Vault 同生態組合（Boundary 控連線 / Vault 給 credential）、Multi-hop Worker 跨網路分段">Boundary&lt;/a> 比、Boundary 是 &lt;em>network broker&lt;/em>（client → broker → target、target 不在 client 網路上）、Tailscale 是 &lt;em>overlay network&lt;/em>（client / target 都在 tailnet 上、直接點對點）；Boundary 配 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault&lt;/a> 發 dynamic credential、Tailscale 直接 bypass credential。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/cloudflare-access/" data-link-title="Cloudflare Access" data-link-desc="Zero Trust Network Access (ZTNA)、取代 VPN 的 application-layer access、Argo Tunnel &amp;#43; Device Posture &amp;#43; IdP integration">Cloudflare Access&lt;/a> 比、Cloudflare Access 走 &lt;em>application-layer reverse proxy&lt;/em>、Tailscale 走 &lt;em>network-layer mesh&lt;/em>；application（HTTP / API）走 Cloudflare、機器存取（SSH / RDP / DB port）走 Tailscale。&lt;/p></description><content:encoded><![CDATA[<p>Tailscale 是 WireGuard-based zero-trust mesh VPN、Tailscale SSH 是其上的 SSH on overlay network 模組。核心 mindset 是 <em>不用 SSH key、不用 jump host</em>：所有 device 加入同一個 tailnet、ACL 控制誰能 SSH 到誰、user identity 從 Tailscale 的 IdP 整合（<a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a> / Google / Microsoft / GitHub SSO）來。它跟 <a href="/blog/backend/07-security-data-protection/vendors/teleport/" data-link-title="Teleport" data-link-desc="Identity-Aware Proxy &#43; PAM、SSH / DB / K8s / Desktop session 統一 short-lived cert &#43; session recording &#43; JIT、跟 Okta / Vault 互補">Teleport</a> / <a href="/blog/backend/07-security-data-protection/vendors/boundary/" data-link-title="HashiCorp Boundary" data-link-desc="Identity-based access broker、跟 Vault 同生態組合（Boundary 控連線 / Vault 給 credential）、Multi-hop Worker 跨網路分段">Boundary</a> / <a href="/blog/backend/07-security-data-protection/vendors/cloudflare-access/" data-link-title="Cloudflare Access" data-link-desc="Zero Trust Network Access (ZTNA)、取代 VPN 的 application-layer access、Argo Tunnel &#43; Device Posture &#43; IdP integration">Cloudflare Access</a> 的差異在 <em>網路模型 + identity binding + audit 深度</em>、SSH 管理能力本身都具備 — Tailscale 走 overlay mesh + identity-bound SSH，Teleport 走 Identity-Aware Proxy + first-class session recording，Boundary 走 network broker + dynamic credential。</p>
<h2 id="服務定位">服務定位</h2>
<p>Tailscale 的核心定位是 <em>WireGuard overlay mesh + identity-bound 連線</em>、Tailscale SSH 是其上 <em>取代 sshd 的 SSH 模組</em>。底層是 Tailscale daemon（每台 device 跑、建立 WireGuard tunnel）+ Tailscale control plane（管 ACL、key exchange、IdP integration、node enrollment）。Tailscale SSH 不是把 OpenSSH 套上 VPN — 它是把 SSH server 換成 Tailscale daemon 內建版本、用 tailnet identity 取代 SSH key、ACL 跟 sshd 設定脫鉤。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/teleport/" data-link-title="Teleport" data-link-desc="Identity-Aware Proxy &#43; PAM、SSH / DB / K8s / Desktop session 統一 short-lived cert &#43; session recording &#43; JIT、跟 Okta / Vault 互補">Teleport</a> 比、Tailscale 走 <em>zero-config + developer-friendly</em>、Teleport 走 <em>audit-first + compliance-friendly</em> — Teleport session recording / RBAC / approval workflow 是 first-class、Tailscale Enterprise 才補 session recording、approval workflow 偏簡單。跟 <a href="/blog/backend/07-security-data-protection/vendors/boundary/" data-link-title="HashiCorp Boundary" data-link-desc="Identity-based access broker、跟 Vault 同生態組合（Boundary 控連線 / Vault 給 credential）、Multi-hop Worker 跨網路分段">Boundary</a> 比、Boundary 是 <em>network broker</em>（client → broker → target、target 不在 client 網路上）、Tailscale 是 <em>overlay network</em>（client / target 都在 tailnet 上、直接點對點）；Boundary 配 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a> 發 dynamic credential、Tailscale 直接 bypass credential。跟 <a href="/blog/backend/07-security-data-protection/vendors/cloudflare-access/" data-link-title="Cloudflare Access" data-link-desc="Zero Trust Network Access (ZTNA)、取代 VPN 的 application-layer access、Argo Tunnel &#43; Device Posture &#43; IdP integration">Cloudflare Access</a> 比、Cloudflare Access 走 <em>application-layer reverse proxy</em>、Tailscale 走 <em>network-layer mesh</em>；application（HTTP / API）走 Cloudflare、機器存取（SSH / RDP / DB port）走 Tailscale。</p>
<p>關鍵張力：<em>developer 易用性</em> ↔ <em>audit / compliance 深度</em> 是 Tailscale 客戶的最大 trade-off。Tailscale 把 SSH 變成「裝完 Tailscale 客戶端、加入 tailnet、不用設 sshd」、developer onboarding 從幾天縮到幾分鐘；但 session recording、approval workflow、keystroke audit 在 Enterprise tier 才有、且深度仍不及 Teleport。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>Tailscale 在 access stack 承擔哪一段（mesh network / identity-bound SSH / Funnel external access）、哪些要外接（<a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a> IdP、<a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> audit log、Teleport 補 session recording）</li>
<li>ACL JSON policy 的 ownership 設計（src / dst / group / tag、誰寫、誰 review、tag 命名空間如何治理）</li>
<li>Tailscale SSH vs Teleport vs Boundary vs Cloudflare Access 的選型判讀</li>
<li>何時用 Tailscale、何時補上 Teleport（compliance）、何時補上 Boundary（dynamic credential）</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Tailscale SSH deployment 是否健康、最少看四件事：</p>
<ul>
<li><strong>ACL 是否走 tag 而非 IP</strong>：production node 是否標 <code>tag:prod-*</code>、ACL 用 tag / group 寫（<code>src: [&quot;group:sre&quot;]</code>、<code>dst: [&quot;tag:prod-db:22&quot;]</code>）而非寫 device hostname；ACL JSON 是否進版控（Git → Tailscale GitOps integration）、change 經 PR review</li>
<li><strong>Identity provider 是不是組織 IdP</strong>：tailnet 是否綁 <a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a> / Google Workspace / Microsoft Entra ID、user 從 IdP SCIM 同步、離職時 IdP deprovision 是否連動 tailnet（不是手動撤 tailnet user）</li>
<li><strong>Tailscale SSH 是否取代 sshd</strong>：production node 是否關掉 OpenSSH 的 port 22 listener、只允許 Tailscale SSH（避免 fallback 到 SSH key auth、繞過 tailnet ACL）</li>
<li><strong>Audit log 是否進 SIEM</strong>：Tailscale audit log（device add / ACL change / SSH session start）是否串到 <a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / <a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a>、跟 IdP log correlation；Enterprise tier 的 SSH session recording 是否啟用</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/07-security-data-protection/identity-access-boundary/" data-link-title="7.2 身分與授權邊界" data-link-desc="以問題驅動方式整理身分、授權、會話與供應商身分鏈">Identity Access Boundary</a> 的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>Tailnet 與 Node enrollment</strong>：Tailnet 是一個邏輯網路（一個組織通常一個）、Node 是加入 tailnet 的 device（laptop / server / container）。Enrollment 兩種路徑 — <em>interactive</em>（人類 device 跑 <code>tailscale up</code>、瀏覽器跳 IdP 登入）、<em>auth key</em>（ephemeral / reusable / preauthorized key、CI / IaC 用）。Production server 通常用 <em>auth key + tag</em> 加入、tag 在 enrollment 時就綁定、不能事後改。</p>
<p><strong>ACL JSON policy</strong>：Tailscale ACL 是 HuJSON（JSON with comments）文件、由 <code>acls</code> / <code>groups</code> / <code>tagOwners</code> / <code>ssh</code> 區塊組成。<code>acls</code> 寫 <code>action: accept</code> + <code>src</code> + <code>dst</code> + <code>proto</code> + <code>port</code>、<code>groups</code> 把 user 抽成角色（<code>group:sre</code>、<code>group:helpdesk</code>）、<code>tagOwners</code> 控制誰能 mint 某個 tag、<code>ssh</code> 區塊定義誰能用 Tailscale SSH 連到哪些 tag（額外於 <code>acls</code>）。ACL 寫得好不好直接決定 <em>lateral movement blast radius</em>。</p>
<p><strong>Tailscale SSH（取代 sshd）</strong>：Tailscale SSH 是 daemon 內建的 SSH server、user 連線時不出示 SSH key、Tailscale 用 <em>tailnet identity</em>（從 IdP 來）做 authn、用 ACL 的 <code>ssh</code> 區塊做 authz。SSH session 的 OS user 由 ACL 指定（<code>users: [&quot;root&quot;, &quot;ubuntu&quot;]</code>）、不是 user 自己挑。意義是 <em>SSH key rotation 從 lifecycle 移除</em>、user 離職 IdP deprovision 後立即失去所有 SSH access。</p>
<p><strong>Identity provider 整合</strong>：Tailscale 自身不存 password、user identity 完全外包給 IdP。Okta / Google Workspace 通常用 SCIM 同步 user + group、GitHub SSO 走 OAuth、Microsoft Entra ID 走 SAML。Group 從 IdP 同步進 tailnet 後、ACL 直接用 <code>group:sre</code>、<code>group:contractor</code>。IdP 的 MFA / Conditional Access policy 自動套用到 tailnet authn。</p>
<p><strong>Tag-based machine identity</strong>：Tag 是 Tailscale 的 <em>machine identity primitive</em>、語意接近 <a href="/blog/backend/07-security-data-protection/vendors/spire/" data-link-title="SPIRE" data-link-desc="SPIFFE Runtime Environment、attested workload identity、short-lived SVID &#43; Trust Bundle、跨組織 federation">SPIRE</a> workload identity（但 Tailscale-specific、不是 SPIFFE 標準）。Production 用 tag 把 node 分類（<code>tag:prod-db</code>、<code>tag:prod-app</code>、<code>tag:ci-runner</code>）、ACL 用 tag 寫規則。Tag 在 enrollment 時 bind、之後不能改（要重新 enroll）；<code>tagOwners</code> 控制誰能 mint 該 tag、防止 dev tag 升 prod tag。</p>
<p><strong>Subnet Router 與 Exit Node</strong>：<em>Subnet Router</em> 把 on-prem subnet（例如 <code>10.0.0.0/16</code> 的舊資料中心）route 到 tailnet、不用在每台舊機器裝 Tailscale daemon — 適合 legacy infra migration。<em>Exit Node</em> 把所有流量（不只 tailnet）走某個 node 出去、適合 remote worker 需要從固定 IP 出網。兩者都是 mesh 之外的擴展、不是 first-class、容易擴大 blast radius 要謹慎用。</p>
<p><strong>Funnel（external HTTPS access）</strong>：Funnel 把 tailnet 上的 internal service 暴露到 internet（透過 Tailscale relay、Tailscale 出 TLS cert）、適合 webhook receiver、dev preview environment、demo URL。Production-grade external access 應該走 <a href="/blog/backend/07-security-data-protection/vendors/cloudflare-access/" data-link-title="Cloudflare Access" data-link-desc="Zero Trust Network Access (ZTNA)、取代 VPN 的 application-layer access、Argo Tunnel &#43; Device Posture &#43; IdP integration">Cloudflare Access</a> 或 reverse proxy + WAF — Funnel 沒有 WAF、bot protection、rate limit，是 <em>zero-config 暴露</em>、不是 <em>production hardened ingress</em>。</p>
<p><strong>跟 OS firewall 互動</strong>：Tailscale 是 overlay network、不取代 OS firewall。Production node 應該用 OS firewall（iptables / nftables / Windows Firewall）封鎖 <em>非 tailnet</em> 流量到 port 22 / 3306 / 5432、只允許 <code>tailscale0</code> 介面進來；不然攻擊者拿到 node IP 後仍能繞過 ACL 直接 SSH。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Tailscale SSH</th>
          <th>Teleport</th>
          <th>Boundary</th>
          <th>Cloudflare Access</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>網路模型</td>
          <td>WireGuard overlay mesh（peer-to-peer）</td>
          <td>Identity-Aware Proxy（client → proxy → target）</td>
          <td>Network broker（client → broker → target）</td>
          <td>Application-layer reverse proxy</td>
      </tr>
      <tr>
          <td>Identity binding</td>
          <td>tailnet identity（IdP-bound、無 SSH key）</td>
          <td>Teleport cert（SSO-issued、short-lived）</td>
          <td>Boundary session token（IdP-bound）</td>
          <td>Cloudflare identity（SSO-issued、跟 ZTNA 整合）</td>
      </tr>
      <tr>
          <td>Session recording</td>
          <td>Enterprise tier、Tailscale-specific</td>
          <td>First-class、所有 tier、tsh play 回放</td>
          <td>無（依賴 target 自身）</td>
          <td>無（屬 application layer、不 record SSH）</td>
      </tr>
      <tr>
          <td>Audit 深度</td>
          <td>ACL change / device add / session start</td>
          <td>Full session recording + RBAC audit + approval</td>
          <td>Session log + dynamic credential audit</td>
          <td>HTTP request log（不適用 SSH）</td>
      </tr>
      <tr>
          <td>Credential model</td>
          <td>No credential（identity-bound）</td>
          <td>Short-lived cert（per-session）</td>
          <td>Dynamic credential（Vault-issued）</td>
          <td>OAuth / JWT（per-request）</td>
      </tr>
      <tr>
          <td>學習曲線</td>
          <td>緩 — 裝 client 即用</td>
          <td>中 — RBAC role / tsh CLI / approval workflow</td>
          <td>陡 — broker / target / credential brokering</td>
          <td>緩 — Cloudflare 既有用戶上手快</td>
      </tr>
      <tr>
          <td>部署模型</td>
          <td>SaaS（Tailscale）+ self-hosted（Headscale OSS）</td>
          <td>Self-hosted / Teleport Cloud</td>
          <td>Self-hosted（HashiCorp）/ HCP Boundary</td>
          <td>SaaS only（Cloudflare）</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>developer-heavy、SSH-first、zero-config 訴求</td>
          <td>Compliance / SOC 2 / 重 audit 場景</td>
          <td>Dynamic credential + Vault 已用</td>
          <td>Application 層存取（HTTP / API）</td>
      </tr>
      <tr>
          <td>退場成本</td>
          <td>低 — 拆 client + 開 sshd 即可</td>
          <td>中 — RBAC / approval workflow 已 codify</td>
          <td>中 — broker 設定 + Vault integration</td>
          <td>中 — ZTNA policy + IdP 整合</td>
      </tr>
  </tbody>
</table>
<p>選 Tailscale SSH 的核心訴求：<em>developer 易用性 + zero-trust mesh + 願意接受 Tailscale 控制面信任</em>、且 audit / compliance 要求是中度而非極致（SOC 2 Type II + 內部 SOX 等級就配 Enterprise tier session recording、HIPAA / FedRAMP / 重 compliance 走 Teleport）。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Tailscale SSH session recording（Enterprise）</strong>：2023 後 Enterprise tier 提供 SSH session 錄影、存到組織自己的 S3 / GCS（不是 Tailscale 控制面）、用 <em>recorder node</em>（tag:tailscale-recorder）攔流量寫盤。意義是 <em>audit 不再依賴 OS-level 工具（auditd / OSSEC）</em>；但跟 Teleport 比、Tailscale recording 仍偏簡單、approval workflow 是基本版、structured query 跟 keystroke replay UI 不如 Teleport。</p>
<p><strong>Subnet Router 的 blast radius</strong>：Subnet Router 把整個 subnet route 到 tailnet、ACL 控制粒度從 <em>device-level</em> 退到 <em>subnet-level</em>（除非搭 tag）— 一台 Subnet Router 給太多人用就是 jump host 復活。production 應該 <em>每個 subnet 至少兩個 Subnet Router</em>（HA）、tag 區分（<code>tag:subnet-router-prod</code>）、ACL 限定誰能透過它走。</p>
<p><strong>Headscale（OSS control plane alternative）</strong>：Headscale 是社群維護的 Tailscale control plane OSS 重實作、self-hosted、跟官方 Tailscale client 相容。適用 <em>資料主權 / air-gapped / 不信任 Tailscale 控制面</em> 場景。代價是 ACL JSON 編輯器 / GitOps / SCIM / IdP integration 都要自己拼、沒有官方 SaaS 的 console UX 跟 SLA。production 用 Headscale 通常配 <a href="/blog/backend/07-security-data-protection/vendors/spire/" data-link-title="SPIRE" data-link-desc="SPIFFE Runtime Environment、attested workload identity、short-lived SVID &#43; Trust Bundle、跨組織 federation">SPIRE</a> workload identity 補 machine identity。</p>
<p><strong>跟 SPIRE workload identity 對照</strong>：Tailscale tag 是 Tailscale-specific 的 machine identity primitive、語意接近 SPIRE 的 SPIFFE ID（<code>spiffe://example.org/prod-db</code>）；差異在 SPIRE 走 SPIFFE 開放標準、跨 platform（Kubernetes / VM / serverless）、tag 只在 tailnet 內有意義。重 multi-platform workload identity 走 SPIRE、SSH access 為主走 Tailscale tag。</p>
<p><strong>Just-In-Time access pattern</strong>：Tailscale 預設是 <em>standing access</em>（user 在 group:sre、永遠能 SSH 到 prod-db）、不是 JIT。要做 JIT 通常 <em>IdP 端做</em>（Okta Workflows 加 user 進 group:sre-oncall、SCIM 同步進 tailnet、ACL 給 group:sre-oncall 對 prod-db 的 SSH 權限）、或 <em>Tailscale API 自寫 ACL 寫入腳本</em>。Teleport / Boundary 有 first-class JIT approval、Tailscale 要自己拼。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>ACL 改錯把全公司鎖在外面</strong>：ACL JSON 寫錯 default deny 規則、Tailscale 控制面套用後沒人能連 — 用 Tailscale 控制面的 ACL preview / test 功能、production 走 GitOps PR review、保留 <code>admin-emergency-access</code> group bypass</li>
<li><strong>離職員工還能 SSH</strong>：IdP deprovision 沒連動 tailnet（手動管 user）— 改走 SCIM 同步 + IdP group binding、ACL 用 group 而非個別 user</li>
<li><strong>OpenSSH 還在 listen port 22 給 fallback</strong>：node 沒關 sshd、攻擊者拿到 IP 後用 SSH key 繞過 tailnet ACL — production node 關掉 sshd、OS firewall 只允許 tailscale0 介面的 22 port</li>
<li><strong>tag 被誤升 prod</strong>：dev user 自己 mint <code>tag:prod-db</code> 給 node、ACL 給 prod-db SSH 權限就此擴散 — <code>tagOwners</code> 限定 <code>tag:prod-*</code> 只有 group:sre 能 mint</li>
<li><strong>Funnel 暴露 internal service</strong>：dev 為了 demo 開 Funnel、忘了關、production data 外洩 — Funnel 走 audit log + alert、預設不該開、要開走 short-lived auth key + tag isolation</li>
<li><strong>Subnet Router 變新 jump host</strong>：一台 Subnet Router 給全公司用 legacy subnet、ACL 退到 subnet-level — tag 區分 router、ACL 限定誰能透過它、HA 跑兩台以上</li>
<li><strong>Audit log 沒進 SIEM</strong>：Tailscale console 看 audit log 很慢、跟 IdP / cloud control plane 沒 correlation — 啟用 Tailscale audit log streaming 到 <a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / <a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a>、跨來源 correlation</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Compliance / SOC 2 / 重 audit</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/teleport/" data-link-title="Teleport" data-link-desc="Identity-Aware Proxy &#43; PAM、SSH / DB / K8s / Desktop session 統一 short-lived cert &#43; session recording &#43; JIT、跟 Okta / Vault 互補">Teleport</a></td>
      </tr>
      <tr>
          <td>Dynamic credential + Vault 已用</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/boundary/" data-link-title="HashiCorp Boundary" data-link-desc="Identity-based access broker、跟 Vault 同生態組合（Boundary 控連線 / Vault 給 credential）、Multi-hop Worker 跨網路分段">Boundary</a> + <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a></td>
      </tr>
      <tr>
          <td>Application 層存取（HTTP / API）</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/cloudflare-access/" data-link-title="Cloudflare Access" data-link-desc="Zero Trust Network Access (ZTNA)、取代 VPN 的 application-layer access、Argo Tunnel &#43; Device Posture &#43; IdP integration">Cloudflare Access</a></td>
      </tr>
      <tr>
          <td>Workload identity 跨 platform</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/spire/" data-link-title="SPIRE" data-link-desc="SPIFFE Runtime Environment、attested workload identity、short-lived SVID &#43; Trust Bundle、跨組織 federation">SPIRE</a></td>
      </tr>
      <tr>
          <td>External HTTPS production ingress</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &#43; DDoS &#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF</a> + reverse proxy</td>
      </tr>
      <tr>
          <td>Audit log SIEM</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / <a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a></td>
      </tr>
      <tr>
          <td>Incident routing</td>
          <td><a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>WireGuard 協定本身的密碼學細節跟 NAT traversal 機制</li>
<li>Tailscale 計費 tier 的逐項功能對照（看 Tailscale 官方 pricing page）</li>
<li>Headscale 完整部署 + GitOps + SCIM 自拼方案</li>
<li>Tailscale 跟 OPNsense / pfSense 等傳統 VPN gateway 的整合</li>
<li>Tailscale 內網 DNS（MagicDNS）跟 split-horizon DNS 的細節</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 Tailscale SSH 的關係（對照啟示）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/uber-2022-mfa-fatigue/" data-link-title="7.R7.1.1 Uber 2022：MFA 疲勞與內部工具擴散" data-link-desc="從社交工程到內部工具存取，拆解身分流程與權限邊界的失效點">Uber 2022 MFA Fatigue</a></td>
          <td>Tailscale SSH 走 IdP identity、push MFA fail 後 attacker 仍要拿 IdP 通過 + tailnet enrollment、雙層 mitigation 比 SSH key 強；但 standing tailnet access 本身是風險、需配合 short-lived auth key 或 JIT group assignment</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/microsoft-storm-0558-2023-signing-key-chain/" data-link-title="7.R7.1.5 Microsoft Storm-0558 2023：簽章金鑰鏈與郵件存取" data-link-desc="從簽章金鑰保護失效到雲端郵件存取，拆解身分信任鏈的關鍵控制點">Microsoft Storm-0558 Signing Key Chain</a></td>
          <td>Tailscale 上游 IdP（Okta / Google / Microsoft）signing key 出事時、tailnet enrollment 也跟著受影響、要 force re-auth；Tailscale 自身的 control plane 信任也是同一條鏈、要 audit</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/mgm-2023-identity-lateral-impact/" data-link-title="7.R7.1.4 MGM 2023：身分流程被打穿後的營運中斷" data-link-desc="社交工程造成身分邊界失守後，如何演變成可用性與營運衝擊">MGM 2023 Identity Lateral Impact</a></td>
          <td>Tailscale ACL 做 tag-based scope（helpdesk group 不能 SSH 到 <code>tag:prod-db</code>）、限制 lateral movement blast radius；對照啟示是 helpdesk 工具不該共享 tailnet 跟 prod node、或 ACL 要切乾淨</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/identity-access-boundary/" data-link-title="7.2 身分與授權邊界" data-link-desc="以問題驅動方式整理身分、授權、會話與供應商身分鏈">7.2 身分與授權邊界</a>、<a href="/blog/backend/07-security-data-protection/entrypoint-and-server-protection/" data-link-title="7.3 入口治理與伺服器防護" data-link-desc="以問題驅動方式整理對外入口、管理平面與伺服器邊界">7.3 入口治理與伺服器防護</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/teleport/" data-link-title="Teleport" data-link-desc="Identity-Aware Proxy &#43; PAM、SSH / DB / K8s / Desktop session 統一 short-lived cert &#43; session recording &#43; JIT、跟 Okta / Vault 互補">Teleport</a>、<a href="/blog/backend/07-security-data-protection/vendors/boundary/" data-link-title="HashiCorp Boundary" data-link-desc="Identity-based access broker、跟 Vault 同生態組合（Boundary 控連線 / Vault 給 credential）、Multi-hop Worker 跨網路分段">Boundary</a>、<a href="/blog/backend/07-security-data-protection/vendors/cloudflare-access/" data-link-title="Cloudflare Access" data-link-desc="Zero Trust Network Access (ZTNA)、取代 VPN 的 application-layer access、Argo Tunnel &#43; Device Posture &#43; IdP integration">Cloudflare Access</a></li>
<li>下游：<a href="/blog/backend/07-security-data-protection/vendors/spire/" data-link-title="SPIRE" data-link-desc="SPIFFE Runtime Environment、attested workload identity、short-lived SVID &#43; Trust Bundle、跨組織 federation">SPIRE</a>（workload identity 補位）、<a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a>（dynamic credential 補位）</li>
<li>跨類：<a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a>（IdP 來源）、<a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a>（audit log SIEM）、<a href="/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &#43; DDoS &#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF</a>（external HTTPS production ingress）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（tailnet compromise IR routing）</li>
<li>官方：<a href="https://tailscale.com/kb/">Tailscale Documentation</a>、<a href="https://tailscale.com/kb/1193/tailscale-ssh/">Tailscale SSH</a>、<a href="https://github.com/juanfont/headscale">Headscale</a></li>
</ul>
]]></content:encoded></item><item><title>Cloudflare Access</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/cloudflare-access/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/cloudflare-access/</guid><description>&lt;p>Cloudflare Access 是 application-layer Zero Trust Network Access (ZTNA) portal、定位是 &lt;em>取代 VPN&lt;/em> — 使用者不再先撥 VPN 進內網再連 internal app、而是 IdP 認證後 Access policy 直接判斷能不能進該 application、流量走 Cloudflare global edge。它跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/teleport/" data-link-title="Teleport" data-link-desc="Identity-Aware Proxy &amp;#43; PAM、SSH / DB / K8s / Desktop session 統一 short-lived cert &amp;#43; session recording &amp;#43; JIT、跟 Okta / Vault 互補">Teleport&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/tailscale-ssh/" data-link-title="Tailscale SSH" data-link-desc="WireGuard-based zero-trust mesh &amp;#43; identity-bound SSH、ACL JSON policy、developer-friendly、跟 IdP integration 取代 SSH key">Tailscale SSH&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/boundary/" data-link-title="HashiCorp Boundary" data-link-desc="Identity-based access broker、跟 Vault 同生態組合（Boundary 控連線 / Vault 給 credential）、Multi-hop Worker 跨網路分段">Boundary&lt;/a> 解 &lt;em>不同層的 access&lt;/em> — Cloudflare Access 解 &lt;em>application 層 ZTNA&lt;/em>、Teleport 解 &lt;em>infrastructure 層 PAM + session recording&lt;/em>、Tailscale 解 &lt;em>device-level mesh VPN&lt;/em>、Boundary 解 &lt;em>credential brokering&lt;/em>。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Cloudflare Access 的核心責任是 &lt;em>application-level 認證 + authorization&lt;/em>、不是 network-level routing。一個 Application（hostname / subdomain）對應一組 Access Policy（rule with identity / device / network condition）、user 從 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta&lt;/a> / Google / Azure AD / GitHub 等 IdP 認證後、policy engine 決定能不能進、不能進連到 application backend 都沒機會。它是 Cloudflare Zero Trust suite 的核心、跟 &lt;em>WARP client&lt;/em>（device agent）、&lt;em>Gateway&lt;/em>（DNS / HTTP filtering、取代 Cisco Umbrella 類）、&lt;em>Argo Tunnel&lt;/em>（origin-side outbound、不開 ingress port）組成完整 SASE / Cloudflare One 平台。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/teleport/" data-link-title="Teleport" data-link-desc="Identity-Aware Proxy &amp;#43; PAM、SSH / DB / K8s / Desktop session 統一 short-lived cert &amp;#43; session recording &amp;#43; JIT、跟 Okta / Vault 互補">Teleport&lt;/a> 比、Cloudflare Access 走 &lt;em>application-layer + Cloudflare edge&lt;/em>、Teleport 走 &lt;em>infrastructure-layer + 完整 session recording&lt;/em>。需要 keystroke / RDP / kubectl 完整錄影做合規（PCI / HIPAA）走 Teleport、需要把所有 internal web app 收進統一 ZTNA portal 走 Cloudflare Access、兩者並存常見：Teleport 管 SSH / DB / Kubernetes、Cloudflare Access 管 internal web。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/tailscale-ssh/" data-link-title="Tailscale SSH" data-link-desc="WireGuard-based zero-trust mesh &amp;#43; identity-bound SSH、ACL JSON policy、developer-friendly、跟 IdP integration 取代 SSH key">Tailscale SSH&lt;/a> 比、Tailscale 是 &lt;em>mesh VPN + device-to-device WireGuard&lt;/em>、Cloudflare Access 是 &lt;em>application proxy via edge&lt;/em>。Tailscale 適合 developer 直接 SSH 到雲機、Cloudflare Access 適合 internal app（GitLab / Jenkins / 內部 dashboard）統一收口。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &amp;#43; DDoS &amp;#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF&lt;/a> 的關係：同 Cloudflare 控制面、共用 API token / Audit Log / Logpush、但解不同問題 — WAF 防 &lt;em>public app&lt;/em>（attacker 從外打 production web）、Access 防 &lt;em>internal app&lt;/em>（員工 / 廠商存取後台）、兩者常在同一個 Cloudflare account 共存。&lt;/p></description><content:encoded><![CDATA[<p>Cloudflare Access 是 application-layer Zero Trust Network Access (ZTNA) portal、定位是 <em>取代 VPN</em> — 使用者不再先撥 VPN 進內網再連 internal app、而是 IdP 認證後 Access policy 直接判斷能不能進該 application、流量走 Cloudflare global edge。它跟 <a href="/blog/backend/07-security-data-protection/vendors/teleport/" data-link-title="Teleport" data-link-desc="Identity-Aware Proxy &#43; PAM、SSH / DB / K8s / Desktop session 統一 short-lived cert &#43; session recording &#43; JIT、跟 Okta / Vault 互補">Teleport</a> / <a href="/blog/backend/07-security-data-protection/vendors/tailscale-ssh/" data-link-title="Tailscale SSH" data-link-desc="WireGuard-based zero-trust mesh &#43; identity-bound SSH、ACL JSON policy、developer-friendly、跟 IdP integration 取代 SSH key">Tailscale SSH</a> / <a href="/blog/backend/07-security-data-protection/vendors/boundary/" data-link-title="HashiCorp Boundary" data-link-desc="Identity-based access broker、跟 Vault 同生態組合（Boundary 控連線 / Vault 給 credential）、Multi-hop Worker 跨網路分段">Boundary</a> 解 <em>不同層的 access</em> — Cloudflare Access 解 <em>application 層 ZTNA</em>、Teleport 解 <em>infrastructure 層 PAM + session recording</em>、Tailscale 解 <em>device-level mesh VPN</em>、Boundary 解 <em>credential brokering</em>。</p>
<h2 id="服務定位">服務定位</h2>
<p>Cloudflare Access 的核心責任是 <em>application-level 認證 + authorization</em>、不是 network-level routing。一個 Application（hostname / subdomain）對應一組 Access Policy（rule with identity / device / network condition）、user 從 <a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a> / Google / Azure AD / GitHub 等 IdP 認證後、policy engine 決定能不能進、不能進連到 application backend 都沒機會。它是 Cloudflare Zero Trust suite 的核心、跟 <em>WARP client</em>（device agent）、<em>Gateway</em>（DNS / HTTP filtering、取代 Cisco Umbrella 類）、<em>Argo Tunnel</em>（origin-side outbound、不開 ingress port）組成完整 SASE / Cloudflare One 平台。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/teleport/" data-link-title="Teleport" data-link-desc="Identity-Aware Proxy &#43; PAM、SSH / DB / K8s / Desktop session 統一 short-lived cert &#43; session recording &#43; JIT、跟 Okta / Vault 互補">Teleport</a> 比、Cloudflare Access 走 <em>application-layer + Cloudflare edge</em>、Teleport 走 <em>infrastructure-layer + 完整 session recording</em>。需要 keystroke / RDP / kubectl 完整錄影做合規（PCI / HIPAA）走 Teleport、需要把所有 internal web app 收進統一 ZTNA portal 走 Cloudflare Access、兩者並存常見：Teleport 管 SSH / DB / Kubernetes、Cloudflare Access 管 internal web。跟 <a href="/blog/backend/07-security-data-protection/vendors/tailscale-ssh/" data-link-title="Tailscale SSH" data-link-desc="WireGuard-based zero-trust mesh &#43; identity-bound SSH、ACL JSON policy、developer-friendly、跟 IdP integration 取代 SSH key">Tailscale SSH</a> 比、Tailscale 是 <em>mesh VPN + device-to-device WireGuard</em>、Cloudflare Access 是 <em>application proxy via edge</em>。Tailscale 適合 developer 直接 SSH 到雲機、Cloudflare Access 適合 internal app（GitLab / Jenkins / 內部 dashboard）統一收口。跟 <a href="/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &#43; DDoS &#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF</a> 的關係：同 Cloudflare 控制面、共用 API token / Audit Log / Logpush、但解不同問題 — WAF 防 <em>public app</em>（attacker 從外打 production web）、Access 防 <em>internal app</em>（員工 / 廠商存取後台）、兩者常在同一個 Cloudflare account 共存。</p>
<p>關鍵張力：<em>Cloudflare 控制面信任成本</em> ↔ <em>統一 ZTNA portal 的工程紅利</em> 是 Cloudflare Access 客戶的長期取捨。Cloudflare 自家 control plane 出事（<a href="/blog/backend/07-security-data-protection/cases/cloudflare-control-plane-token-2023/" data-link-title="7.C2 Cloudflare：2023 Control-plane Token 事件" data-link-desc="控制面 token 事件如何回寫 secrets 與機器憑證治理。">Cloudflare 2023 control plane token</a>）會直接打到 Access policy 變更權、客戶側必須有非 Cloudflare 路徑的 break-glass。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>Cloudflare Access 在 ZTNA / PAM stack 中承擔哪一段（application access）、哪些要外接（<a href="/blog/backend/07-security-data-protection/vendors/teleport/" data-link-title="Teleport" data-link-desc="Identity-Aware Proxy &#43; PAM、SSH / DB / K8s / Desktop session 統一 short-lived cert &#43; session recording &#43; JIT、跟 Okta / Vault 互補">Teleport</a> 管 infrastructure session、<a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a> 管 IdP source of truth）</li>
<li>Application + Access Policy + Argo Tunnel 三者的 ownership 設計（誰建 Application、誰寫 policy、誰跑 cloudflared agent）</li>
<li>Cloudflare control plane 信任邊界 — 自家事故的 blast radius 跟客戶側 break-glass 預案</li>
<li>何時用 Cloudflare Access、何時走 Teleport / Tailscale / Zscaler 的取捨</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Cloudflare Access deployment 是否健康、最少看四件事：</p>
<ul>
<li><strong>誰能改 Access Policy</strong>：Cloudflare account 的 Super Admin / Access Admin 人數、policy change 是否走 Terraform / API + PR review、是否有 IdP claim 跟 Cloudflare group 雙重 enforcement</li>
<li><strong>Application 收口完整度</strong>：internal web / SSH / RDP / API 是否都進 Application 清單、是否還有 <em>bypass Cloudflare 直連 origin</em> 的暴露 IP、Argo Tunnel 是否強制（origin 防火牆只開 cloudflared outbound、不開 ingress）</li>
<li><strong>Device Posture / Service Auth 治理</strong>：human user 是否有 WARP + Device Posture 檢查（OS 版本 / EDR / disk encryption）、non-human（CI / 機器）是否走 Service Auth（mTLS cert / service token）而非共用 user account</li>
<li><strong>Logpush + break-glass</strong>：Access event / Audit Log 是否 Logpush 到 <a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> 或外部 SIEM、Cloudflare 自家 control plane 出事時是否有 <em>非 Cloudflare</em> 路徑可進關鍵 application（例如 emergency bastion 走獨立 IdP）</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/07-security-data-protection/identity-access-boundary/" data-link-title="7.2 身分與授權邊界" data-link-desc="以問題驅動方式整理身分、授權、會話與供應商身分鏈">Identity and Access Boundary</a> 邊界的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>Application + Access Policy</strong>：Application 是 first-class concept、對應一個 hostname（<code>gitlab.internal.example.com</code>）或一組 subdomain。Application 綁多個 Access Policy、每個 policy 是 <em>Allow / Block / Bypass</em> rule、條件可組合 identity（IdP group / email / SAML claim）、device（Device Posture 結果 / WARP enrolled）、network（country / IP range / Service Token）。policy 順序決定優先級、第一個 match 的生效。Production 寫法是 <em>deny by default + allow specific group</em>、不是 <em>allow all + block bad</em>。</p>
<p><strong>IdP integration</strong>：Cloudflare Access 不存身份、只接 IdP — SAML / OIDC 對 <a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a> / Azure AD / Google Workspace、OAuth 對 GitHub / GitLab、One-Time PIN 對外部廠商（沒 IdP 的合作方）。同一個 Application 可接多 IdP、policy 用 <code>identity.email ends with @vendor.com</code> 區分。IdP 是 source of truth、Cloudflare 是 enforcement point — IdP 出事（Okta / Azure AD 故障或被打）會直接擋住所有 Access user 登入、break-glass 預案必要。</p>
<p><strong>Argo Tunnel（cloudflared）</strong>：internal app 不開 ingress port、不需要 public IP、由 <code>cloudflared</code> agent 在 origin 主動建 outbound tunnel 到 Cloudflare edge。攻擊面從「IP + port + WAF rule」收成「cloudflared agent + Tunnel token」— attacker 從外掃不到 origin，必須先拿到 Tunnel token 或 compromise cloudflared host。Argo Tunnel 的 token 是高敏 secret、應該存 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a> 或 cloud secret manager、定期 rotate。</p>
<p><strong>Browser-based SSH / RDP / VNC</strong>：Cloudflare Access 對 SSH / RDP / VNC 提供 browser-based render — user 不裝 SSH client、瀏覽器直接連、session 經 Cloudflare edge proxy。可 log session metadata（user / app / time）但 <em>不像 Teleport 完整錄 keystroke / 螢幕</em>。合規場景（PCI 要求 session recording）需要外接 Teleport 或自己跑 session recording proxy、Cloudflare Access 解決的是 access enforcement 不是 audit replay。</p>
<p><strong>Service Auth（non-human access）</strong>：CI runner / 機器人 / API client 走 Service Auth、不需要 user identity。兩種模式：<em>mTLS</em>（client cert + Cloudflare 驗 CA）、<em>Service Token</em>（HTTP header 帶 <code>CF-Access-Client-Id</code> + <code>CF-Access-Client-Secret</code>）。token 進 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a> 或 GitHub Actions secret、定期 rotate、access log 標 service token ID 做事後追蹤。</p>
<p><strong>Device Posture</strong>：跟 WARP client / Gateway 整合、policy 可加 device 條件 — OS 版本最低、EDR（CrowdStrike / SentinelOne）running、disk encryption enabled、device certificate 已 enrolled。Device Posture check fail 時 deny access 或 fallback 到只讀 application。對應 <a href="/blog/backend/07-security-data-protection/blue-team/" data-link-title="7.B 防守者視角（藍隊）與控制面驗證" data-link-desc="從防守者角度整理控制面、偵測路由、驗證策略與演練回寫">zero-trust workforce architecture</a> 的章節原則。</p>
<p><strong>Gateway DNS / HTTP filtering</strong>：Cloudflare Gateway 是 secure web gateway（SWG）、取代 Cisco Umbrella / Zscaler ZIA 類。WARP client 把 device DNS / HTTP traffic 導到 Gateway、policy 過濾 malicious domain / category / DLP。跟 Access 共用 Cloudflare 帳號、policy 跨 Access + Gateway + WARP 統一 — 這是 Cloudflare One / SASE 的核心賣點。</p>
<p><strong>Logpush 進 SIEM</strong>：Access event（login / policy decision / session）+ Audit Log（policy change / admin action）透過 Logpush 推到 S3 / GCS / Splunk HEC / Datadog / Elastic。跟 <a href="/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &#43; DDoS &#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF</a> 共用同一個 Logpush job 配置、SIEM 端做 cross-product correlation（WAF block + Access deny 同 IP）。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Cloudflare Access</th>
          <th>Teleport</th>
          <th>Tailscale SSH</th>
          <th>Zscaler ZIA / ZPA</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>控制層級</td>
          <td>Application layer（hostname / subdomain）</td>
          <td>Infrastructure layer（SSH / DB / k8s / RDP）</td>
          <td>Network layer（device mesh WireGuard）</td>
          <td>Network + application（SASE 整套）</td>
      </tr>
      <tr>
          <td>流量路徑</td>
          <td>Cloudflare global edge proxy</td>
          <td>Teleport proxy（self-hosted / Cloud）</td>
          <td>Device-to-device WireGuard（peer-to-peer）</td>
          <td>Zscaler global cloud</td>
      </tr>
      <tr>
          <td>Session 錄影</td>
          <td>不錄 keystroke、只記 metadata</td>
          <td>完整 keystroke / 螢幕 / kubectl 錄影</td>
          <td>不錄（mesh 性質）</td>
          <td>HTTP / web session 可錄、SSH 弱</td>
      </tr>
      <tr>
          <td>取代 VPN</td>
          <td>強 — application-layer ZTNA 核心訴求</td>
          <td>部分 — 偏 PAM、需配 VPN 補 catch-all</td>
          <td>強 — mesh VPN 直接替代</td>
          <td>強 — ZPA 核心訴求</td>
      </tr>
      <tr>
          <td>Origin 暴露</td>
          <td>Argo Tunnel：origin 零 ingress</td>
          <td>Proxy 收口：origin 只開 Teleport node port</td>
          <td>不需 ingress：mesh peer 直連</td>
          <td>App connector：類似 Argo Tunnel</td>
      </tr>
      <tr>
          <td>IdP integration</td>
          <td>SAML / OIDC / OAuth、One-Time PIN for vendor</td>
          <td>SAML / OIDC</td>
          <td>SSO via IdP（簡單）</td>
          <td>SAML / OIDC</td>
      </tr>
      <tr>
          <td>計費</td>
          <td>Free（50 user）/ Standard / Premium per-user</td>
          <td>Per-user（Teleport Cloud / Enterprise）</td>
          <td>Per-user（含 free tier）</td>
          <td>Per-user enterprise license</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>Internal web app + browser SSH/RDP 統一 portal</td>
          <td>Infrastructure access + 合規 session recording</td>
          <td>Developer SSH mesh + 小型 team</td>
          <td>大型企業全 SASE（含 SWG / CASB / DLP）</td>
      </tr>
      <tr>
          <td>退場成本</td>
          <td>中 — policy 跟 Tunnel 改設可遷</td>
          <td>中 — session log 鎖在 Teleport</td>
          <td>低 — WireGuard 標準</td>
          <td>高 — 全 stack 鎖在 Zscaler</td>
      </tr>
  </tbody>
</table>
<p>選 Cloudflare Access 的核心訴求：<em>application-layer ZTNA 取代 VPN</em> + <em>internal web app 為主 + 偶爾 browser SSH/RDP</em> + <em>已用 Cloudflare WAF / CDN 控制面</em>。需要 infrastructure-level session recording 走 Teleport、developer SSH mesh 為主走 Tailscale、要全 SASE / SWG / CASB 套裝走 Zscaler。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Service Auth 的 non-human access 設計</strong>：CI / 機器人 / 第三方 API client 不該共用 user account、改走 Service Token 或 mTLS。設計重點：<em>token 不進 git</em>（<a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a> / GitHub Actions secret）、<em>per-service token</em>（不共用、追蹤責任）、<em>rotation lifecycle</em>（90 天 / 半年 rotate）、<em>access log 標 token ID</em>（事後追責）。token leak 的處理是 <em>rotate + audit log review</em>、不是 <em>all-users password reset</em>。</p>
<p><strong>Device Posture + EDR 整合</strong>：Gateway / WARP 可接 CrowdStrike Falcon / SentinelOne / Microsoft Defender for Endpoint 的 device health、policy 可寫 <code>require posture: crowdstrike.running == true AND crowdstrike.last_check &lt; 1h</code>。意義是 endpoint compromise 時 EDR 標紅、Access policy 自動 deny — 不需要 SOC 手動把 user disable。前提是 EDR fleet coverage 接近 100%、不然 fallback 設不好會誤殺。</p>
<p><strong>Cloudflare One（Access + WARP + Gateway + Magic Transit）</strong>：Cloudflare 把 ZTNA + SWG + CASB + 網路骨幹整成 SASE 套裝、競爭對手是 Zscaler / Netskope / Palo Alto Prisma Access。買整套的紅利是 policy / log / IdP 統一、痛點是 <em>Cloudflare 控制面信任成本指數放大</em> — 一個 admin 角色失控影響 Access + Gateway + WAF + DNS 全部、不只是單一產品。</p>
<p><strong>跟 <a href="/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &#43; DDoS &#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF</a> 共用 control plane 的取捨</strong>：紅利是同一 Logpush job / 同一 API token 管理 / 同一 Audit Log、SIEM 端 correlation 容易。信任成本是 <a href="/blog/backend/07-security-data-protection/cases/cloudflare-control-plane-token-2023/" data-link-title="7.C2 Cloudflare：2023 Control-plane Token 事件" data-link-desc="控制面 token 事件如何回寫 secrets 與機器憑證治理。">Cloudflare 2023 control plane token</a> 那類事故會同時影響 WAF rule + Access policy + DNS、客戶側必須有 <em>non-Cloudflare break-glass</em>（例如保留一條 emergency bastion 走獨立 IdP + 獨立網路、不經過 Cloudflare edge）。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>User 一進 Application 就被 deny</strong>：policy 順序錯（Block rule 在 Allow 前面 match）、或 IdP group claim 沒帶到 — 看 Access log 的 <code>decision_reason</code>、確認 policy 順序跟 IdP claim mapping</li>
<li><strong>Argo Tunnel 斷線 / 找不到 origin</strong>：cloudflared 程序掛或 token 過期、origin 防火牆把 outbound 443 擋了 — 重啟 cloudflared、確認 outbound 規則、token rotate 後重新 deploy</li>
<li><strong>Service Token 大量 leak / 在 GitHub repo 出現</strong>：CI secret 設定錯放成 plaintext、或第三方 vendor commit 了 — Cloudflare dashboard rotate token、audit log 找受影響時間窗、補 secret scanning（<a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GitHub Advanced Security</a> / <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a>）</li>
<li><strong>Device Posture 把合法 user 鎖在外</strong>：EDR agent 暫時離線或 OS 升級導致 posture check fail — fallback 設 graceful（降級到只讀 / 加 step-up MFA）、不是直接 deny；EDR fleet coverage 沒到位前不要 hard enforcement</li>
<li><strong>IdP 出事 Access user 全進不來</strong>：Okta / Azure AD downtime 把 Access login 全鎖死 — break-glass 走 <em>Service Token + 緊急 Application</em>（不接 IdP、只接 mTLS / token），預先 staging tested</li>
<li><strong>Bypass 流量直連 origin</strong>：Application 收口不完整、origin 還有 public IP + 沒設 firewall 只接 Cloudflare IP — Argo Tunnel 收完、origin firewall 只允許 Cloudflare IP range 或完全只開 cloudflared outbound</li>
<li><strong>Cloudflare control plane 出事</strong>：Cloudflare 自家 admin token / control plane 被打、客戶側 Access policy 暫時改不了或被偷改 — 預案：保留 <em>非 Cloudflare emergency bastion</em> + 關鍵 application 的 Logpush 進外部 SIEM（不只 Cloudflare dashboard）</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Infrastructure access + 合規錄影</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/teleport/" data-link-title="Teleport" data-link-desc="Identity-Aware Proxy &#43; PAM、SSH / DB / K8s / Desktop session 統一 short-lived cert &#43; session recording &#43; JIT、跟 Okta / Vault 互補">Teleport</a></td>
      </tr>
      <tr>
          <td>Developer SSH mesh / 小型 team</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/tailscale-ssh/" data-link-title="Tailscale SSH" data-link-desc="WireGuard-based zero-trust mesh &#43; identity-bound SSH、ACL JSON policy、developer-friendly、跟 IdP integration 取代 SSH key">Tailscale SSH</a></td>
      </tr>
      <tr>
          <td>Credential brokering / 動態 DB cred</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/boundary/" data-link-title="HashiCorp Boundary" data-link-desc="Identity-based access broker、跟 Vault 同生態組合（Boundary 控連線 / Vault 給 credential）、Multi-hop Worker 跨網路分段">Boundary</a> + <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a></td>
      </tr>
      <tr>
          <td>全 SASE 套裝（SWG + CASB + DLP）</td>
          <td>Zscaler / Netskope / Palo Alto Prisma Access</td>
      </tr>
      <tr>
          <td>Public app 入口防護</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &#43; DDoS &#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF</a> / <a href="/blog/backend/07-security-data-protection/vendors/aws-waf/" data-link-title="AWS WAF" data-link-desc="AWS-internal WAF、跟 ALB / CloudFront / API Gateway 直接整合、Web ACL &#43; Managed Rule Group &#43; Rate-based Rule、Shield Standard 內含">AWS WAF</a></td>
      </tr>
      <tr>
          <td>IdP 本體（身份 source of truth）</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a> / <a href="/blog/backend/07-security-data-protection/vendors/auth0/" data-link-title="Auth0" data-link-desc="B2C / B2B Customer Identity Provider、Universal Login、Action / Rule hook、屬 Okta 旗下 Customer Identity Cloud">Auth0</a> / <a href="/blog/backend/07-security-data-protection/vendors/keycloak/" data-link-title="Keycloak" data-link-desc="Open source self-hosted Identity Provider、Red Hat 主導、Realm-based multi-tenancy、適合資料主權與自訂 flow 需求">Keycloak</a></td>
      </tr>
      <tr>
          <td>SIEM 接 Access log</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / <a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-security-operations/" data-link-title="Google Security Operations" data-link-desc="Google 雲原生 SIEM &#43; SOAR &#43; Mandiant threat intel 三合一（前 Chronicle）、UDM &#43; YARA-L、fixed-price by data tier、PB-scale 友善">Google Security Operations</a></td>
      </tr>
      <tr>
          <td>Incident routing</td>
          <td><a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Cloudflare WARP client 完整部署 / device enrollment 細節</li>
<li>Gateway DNS / HTTP filtering 完整 policy 語法</li>
<li>Cloudflare One / Magic Transit / Magic WAN 的網路骨幹細節（屬 SD-WAN / SASE 整套架構、不在 ZTNA 範圍）</li>
<li>cloudflared agent 進階配置（multi-region / HA / load balancing）</li>
<li>Cloudflare account / API token 管理本身（屬 Cloudflare 平台治理、跨產品共用）</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>Cloudflare Access 在 07 案例庫的關聯來自 <em>Cloudflare 控制面信任</em> 跟 <em>IdP 上游事故傳導</em>：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 Cloudflare Access 的關係（對照啟示）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/cases/cloudflare-control-plane-token-2023/" data-link-title="7.C2 Cloudflare：2023 Control-plane Token 事件" data-link-desc="控制面 token 事件如何回寫 secrets 與機器憑證治理。">Cloudflare Control Plane Token 2023</a></td>
          <td>Cloudflare 自家 control plane 出事時、Access policy 變更權跟著受影響、客戶側必須有非 Cloudflare 路徑的 break-glass、關鍵 application 的 Logpush 進外部 SIEM</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/mgm-2023-identity-lateral-impact/" data-link-title="7.R7.1.4 MGM 2023：身分流程被打穿後的營運中斷" data-link-desc="社交工程造成身分邊界失守後，如何演變成可用性與營運衝擊">MGM 2023 Identity Lateral Impact</a></td>
          <td>Cloudflare Access 在 helpdesk SE 拿到 IdP credential 後、Device Posture + Application policy + Service Token 是額外 hop 成本、不是 IdP 一拿就全通</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/okta-cloudflare-2023-support-supply-chain/" data-link-title="7.R7.1.2 Okta &#43; Cloudflare 2023：支援流程與身分供應鏈" data-link-desc="支援工單與第三方身份供應商路徑如何變成入侵鏈的一部分">Okta-Cloudflare 2023 Support Supply Chain</a></td>
          <td>上游 IdP（Okta）出事傳導到 Cloudflare Access enrollment、需要 force re-auth + service token rotate + Logpush audit 找受影響時間窗、IdP 跟 Access 不可同時失能</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/identity-access-boundary/" data-link-title="7.2 身分與授權邊界" data-link-desc="以問題驅動方式整理身分、授權、會話與供應商身分鏈">7.2 身分與授權邊界</a>、<a href="/blog/backend/07-security-data-protection/blue-team/" data-link-title="7.B 防守者視角（藍隊）與控制面驗證" data-link-desc="從防守者角度整理控制面、偵測路由、驗證策略與演練回寫">zero-trust workforce architecture</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/teleport/" data-link-title="Teleport" data-link-desc="Identity-Aware Proxy &#43; PAM、SSH / DB / K8s / Desktop session 統一 short-lived cert &#43; session recording &#43; JIT、跟 Okta / Vault 互補">Teleport</a>、<a href="/blog/backend/07-security-data-protection/vendors/tailscale-ssh/" data-link-title="Tailscale SSH" data-link-desc="WireGuard-based zero-trust mesh &#43; identity-bound SSH、ACL JSON policy、developer-friendly、跟 IdP integration 取代 SSH key">Tailscale SSH</a>、<a href="/blog/backend/07-security-data-protection/vendors/boundary/" data-link-title="HashiCorp Boundary" data-link-desc="Identity-based access broker、跟 Vault 同生態組合（Boundary 控連線 / Vault 給 credential）、Multi-hop Worker 跨網路分段">Boundary</a></li>
<li>下游：<a href="/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &#43; DDoS &#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF</a>（共用 control plane）、<a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / <a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a>（Logpush 目的地）</li>
<li>跨類：<a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a> / <a href="/blog/backend/07-security-data-protection/vendors/auth0/" data-link-title="Auth0" data-link-desc="B2C / B2B Customer Identity Provider、Universal Login、Action / Rule hook、屬 Okta 旗下 Customer Identity Cloud">Auth0</a>（IdP source）、<a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a>（Tunnel token / Service Token 儲存）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（Access deny / 異常登入 routing）、<a href="/blog/backend/05-deployment-platform/vendors/" data-link-title="部署平台 Vendor 清單" data-link-desc="規劃 workload runtime、orchestration、traffic、IaC 與 discovery 的服務頁撰寫順序與判準">5 deployment vendors</a>（Argo Tunnel + CI 部署整合）</li>
<li>官方：<a href="https://developers.cloudflare.com/cloudflare-one/">Cloudflare Zero Trust Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>Wiz</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/wiz/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/wiz/</guid><description>&lt;p>Wiz 是 &lt;em>agentless CNAPP&lt;/em>（Cloud-Native Application Protection Platform）的代表、用 &lt;em>cloud API + snapshot scan&lt;/em> 從外面看雲、不在 workload 上裝 agent。2020 年由前 Microsoft Cloud Security Group 創辦人成立、2024 估值約 $12B、是 CNAPP 賽道的後起黑馬。它跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &amp;#43; Code (SAST) &amp;#43; Container &amp;#43; IaC &amp;#43; Cloud (CSPM)、Reachability analysis">Snyk&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &amp;#43; Secret &amp;#43; License &amp;#43; SBOM、Apache 2.0、CI 友善">Trivy&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &amp;#43; CSPM &amp;#43; CWS &amp;#43; AAP &amp;#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Security&lt;/a> 的差異在 &lt;em>風險優先級的組合方式&lt;/em>、vulnerability 掃描能力本身都具備 — Wiz 用 &lt;em>Security Graph + Toxic Combination&lt;/em> 把多個 low-risk finding 串成 &lt;em>attack path&lt;/em>、而不是給你 10000 個獨立 CVE。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Wiz 的核心定位是 &lt;em>agentless cloud posture + workload protection platform&lt;/em>、把 CSPM（Cloud Security Posture Management）/ CWP（Cloud Workload Protection）/ CIEM（Cloud Infrastructure Entitlement Management）/ KSPM（Kubernetes Security Posture Management）/ DSPM（Data Security Posture Management）整合在同一個 Security Graph 上面。底層是 &lt;em>Connector&lt;/em>（讀 AWS / GCP / Azure / OCI / K8s 的 read-only API + snapshot scan）、頂層是 &lt;em>Issues + Projects + Toxic Combination rules&lt;/em>。&lt;/p>
&lt;p>跟 Prisma Cloud / Lacework 比、Wiz 走 &lt;em>graph-first&lt;/em> — 把 resource / IAM / vulnerability / secret / network exposure 連成圖（跳過 finding list 層）、可以用 query 問「哪些 EC2 有 RCE CVE 且 IMDS v1 且能 assume 跨帳戶 admin role」。跟 CrowdStrike Falcon Cloud Security 比、Wiz 是 &lt;em>agentless-first&lt;/em>（CWP 才用 sensor、posture / 漏洞掃描 0 agent）、Falcon CS 走 &lt;em>endpoint agent 延伸到雲&lt;/em>。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &amp;#43; CSPM &amp;#43; CWS &amp;#43; AAP &amp;#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Security&lt;/a> CSPM 比、Datadog 是 &lt;em>observability platform 上的 security view&lt;/em>、Wiz 是 &lt;em>security-first CNAPP&lt;/em>、Wiz 的 graph 跟 toxic combination 深度大幅領先、但獨立 SIEM / log 能力不如 Datadog / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &amp;#43; indexer &amp;#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk&lt;/a>。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &amp;#43; Code (SAST) &amp;#43; Container &amp;#43; IaC &amp;#43; Cloud (CSPM)、Reachability analysis">Snyk&lt;/a> 比、Snyk 走 &lt;em>developer-first SAST + SCA + container&lt;/em>、Wiz 走 &lt;em>cloud posture + agentless workload scan&lt;/em>、兩者場景互補不替代 — 多數客戶 Snyk 管 left-shift dev 階段、Wiz 管 runtime cloud。&lt;/p></description><content:encoded><![CDATA[<p>Wiz 是 <em>agentless CNAPP</em>（Cloud-Native Application Protection Platform）的代表、用 <em>cloud API + snapshot scan</em> 從外面看雲、不在 workload 上裝 agent。2020 年由前 Microsoft Cloud Security Group 創辦人成立、2024 估值約 $12B、是 CNAPP 賽道的後起黑馬。它跟 <a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk</a> / <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> / <a href="/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &#43; CSPM &#43; CWS &#43; AAP &#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Security</a> 的差異在 <em>風險優先級的組合方式</em>、vulnerability 掃描能力本身都具備 — Wiz 用 <em>Security Graph + Toxic Combination</em> 把多個 low-risk finding 串成 <em>attack path</em>、而不是給你 10000 個獨立 CVE。</p>
<h2 id="服務定位">服務定位</h2>
<p>Wiz 的核心定位是 <em>agentless cloud posture + workload protection platform</em>、把 CSPM（Cloud Security Posture Management）/ CWP（Cloud Workload Protection）/ CIEM（Cloud Infrastructure Entitlement Management）/ KSPM（Kubernetes Security Posture Management）/ DSPM（Data Security Posture Management）整合在同一個 Security Graph 上面。底層是 <em>Connector</em>（讀 AWS / GCP / Azure / OCI / K8s 的 read-only API + snapshot scan）、頂層是 <em>Issues + Projects + Toxic Combination rules</em>。</p>
<p>跟 Prisma Cloud / Lacework 比、Wiz 走 <em>graph-first</em> — 把 resource / IAM / vulnerability / secret / network exposure 連成圖（跳過 finding list 層）、可以用 query 問「哪些 EC2 有 RCE CVE 且 IMDS v1 且能 assume 跨帳戶 admin role」。跟 CrowdStrike Falcon Cloud Security 比、Wiz 是 <em>agentless-first</em>（CWP 才用 sensor、posture / 漏洞掃描 0 agent）、Falcon CS 走 <em>endpoint agent 延伸到雲</em>。跟 <a href="/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &#43; CSPM &#43; CWS &#43; AAP &#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Security</a> CSPM 比、Datadog 是 <em>observability platform 上的 security view</em>、Wiz 是 <em>security-first CNAPP</em>、Wiz 的 graph 跟 toxic combination 深度大幅領先、但獨立 SIEM / log 能力不如 Datadog / <a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a>。跟 <a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk</a> 比、Snyk 走 <em>developer-first SAST + SCA + container</em>、Wiz 走 <em>cloud posture + agentless workload scan</em>、兩者場景互補不替代 — 多數客戶 Snyk 管 left-shift dev 階段、Wiz 管 runtime cloud。</p>
<p>關鍵張力：<em>agentless + multi-cloud + Security Graph</em> ↔ <em>單一 workload count 計費 + 多模組組合容易踩 sticker shock</em>。Wiz 的價值前提是組織夠大、cloud account / workload 夠多到 <em>toxic combination</em> 比 <em>單點 CVE list</em> 更有意義；小型團隊 + 單一雲 + 預算敏感、用 Wiz 等於買保時捷送外賣。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>Wiz 在 cloud security stack 中承擔哪一段（CSPM / CWP / CIEM / KSPM / DSPM / Wiz Code）、哪些要外接（<a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> 等 SIEM 接 Issues、<a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk</a> / <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> 是否要保留 dev-time scan）</li>
<li>Security Graph query 跟 Toxic Combination rule 的 ownership 設計（誰寫 rule、誰 triage Issue、誰調 Project scope）</li>
<li>Agentless scan 的可見性邊界（snapshot 能看到 / 看不到什麼、需不需要 Wiz Sensor / Defend 補 runtime）</li>
<li>何時用 Wiz、何時走 Prisma Cloud / Lacework / CrowdStrike Falcon CS / Datadog CSPM 的取捨</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Wiz deployment 是否健康、最少看四件事：</p>
<ul>
<li><strong>Connector 覆蓋率</strong>：所有 prod cloud account（AWS / GCP / Azure / OCI）跟 K8s cluster 是否都接上、IAM role 是否最小權限（Wiz 給的 CloudFormation / Terraform template 不要自己加權限）、snapshot scan 是否涵蓋所有 region / disk type</li>
<li><strong>Toxic Combination rule 設計</strong>：是不是只開預設 rule、有沒有針對自家環境 anti-pattern 寫 custom rule（例如 <em>cross-account assume + payment service + secret access</em>）、rule 走不走 PR review</li>
<li><strong>Issue triage SLA</strong>：critical / high Issue 的 mean-time-to-resolve、是否跟 <a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / Jira / Slack 整合、Project scope 是否依 service owner 切（不是丟整包給 SecOps）</li>
<li><strong>Wiz Code / Wiz Defend coverage 邊界</strong>：IaC scan 跟 dev-time CI 是 Wiz Code 還是 <a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk</a> / <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a>、runtime detection 是 Wiz Defend 還是 Falco / CrowdStrike、不要兩邊都裝又都沒人 triage</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/07-security-data-protection/entrypoint-and-server-protection/" data-link-title="7.3 入口治理與伺服器防護" data-link-desc="以問題驅動方式整理對外入口、管理平面與伺服器邊界">7.3 入口治理與伺服器防護</a> 跟 <a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">7.13 偵測覆蓋率與訊號治理</a> 的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>Connector 跟 agentless scan</strong>：Wiz 透過 <em>Connector</em>（每個 cloud account 一個 IAM role）讀 cloud control plane API、定期 snapshot EBS / Persistent Disk / Managed Disk、在 Wiz 自家環境裡 mount snapshot 做 vulnerability / secret / malware scan。對 workload 0 影響、不需要在 EC2 / GKE node / VM 裡裝任何 agent。代價是 <em>runtime 行為看不到</em>（process / network connection / syscall）— 那段要 Wiz Defend / Wiz Sensor 或外接 Falco / CrowdStrike。</p>
<p><strong>Security Graph</strong>：Wiz 把所有 resource（compute / storage / IAM principal / network / secret / vulnerability finding）建成 graph、用 GraphQL-like query 跨類型查詢。Security Graph 是 first-class concept、不只是 visualization — Toxic Combination rule、Issue correlation、blast radius 估算都走 graph。寫 SPL / KQL 跟寫 Wiz query 的 mindset 不一樣 — Wiz query 是 <em>relationship-first</em>（從 resource A 走幾跳到 resource B）、SPL 是 <em>event-first</em>（時間序列上的 log）。</p>
<p><strong>Toxic Combination</strong>：CNAPP vs 傳統 vulnerability scanner 的根本差異。單一 finding 是 low risk（一個 CVE / 一條 over-permission / 一個 public S3）、組合起來是 critical attack path（<em>public-facing EC2 + RCE CVE + IMDS v1 + assume admin role + 觸碰 customer PII bucket</em>）。Wiz 預設帶幾十條 toxic combination rule（attack-path-style）、organization 應該加自家 anti-pattern。對應 <a href="/blog/backend/07-security-data-protection/identity-access-boundary/" data-link-title="7.2 身分與授權邊界" data-link-desc="以問題驅動方式整理身分、授權、會話與供應商身分鏈">7.2 身分與授權邊界</a> 跟 <a href="/blog/backend/07-security-data-protection/entrypoint-and-server-protection/" data-link-title="7.3 入口治理與伺服器防護" data-link-desc="以問題驅動方式整理對外入口、管理平面與伺服器邊界">7.5 應用層風險</a> 的跨 control 整合。</p>
<p><strong>Issues + Projects</strong>：finding 進 Wiz 後變 <em>Issue</em>、按 <em>Project</em> 路由 — Project 是邏輯切分（按 BU / service / 環境）、每個 Project 有 owner、Issue 自動分派。反例是 <em>單一 default Project 收所有 Issue</em>、SecOps 一天看 5000 個 Issue 看不完、跟 <a href="/blog/backend/07-security-data-protection/blue-team/alert-fatigue-and-signal-quality/" data-link-title="7.B10 Alert Fatigue and Signal Quality" data-link-desc="建立告警疲勞治理方法，讓訊號品質、分級一致性與處置效率同步提升">Alert Fatigue and Signal Quality</a> 同樣模式。production 要 Project scope 對齊 service ownership、跟 Jira / Slack / <a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> 整合自動建 ticket。</p>
<p><strong>Wiz Code</strong>：dev-time / IaC scan、覆蓋 Terraform / CloudFormation / K8s manifest / Helm + container image build-time scan + SCA、跟 <a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk</a> Code/IaC 跟 <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> Config 重疊。多數客戶選一邊用、不會雙開。Wiz Code 的賣點是 <em>跟 runtime Wiz finding 同一個 graph</em> — 在 IDE / PR 階段就能看到「這條 IaC 改動會在 prod 產生哪條 toxic combination」。</p>
<p><strong>Wiz Defend (Gem)</strong>：2024 收購 Gem Security 整合 runtime detection / cloud detection、補 Wiz 早期缺的 runtime 層。Wiz Defend 走 <em>cloud-native log + Wiz Sensor</em>（K8s eBPF sensor）混合、跟 CrowdStrike Falcon EDR / Falco 競爭。產品成熟度仍在跟進、2024-2025 才大量 GA、不要假設它已經是 CrowdStrike / SentinelOne 等級的 EDR 替代品。</p>
<p><strong>Wiz Sensor</strong>：K8s admission controller + eBPF runtime sensor、補 agentless 看不到的 runtime 行為（container process / network connection / file integrity）。是 <em>選配</em>、不裝 Wiz 仍能做 posture / vulnerability scan、裝了才有 runtime detection。資源開銷比 Falco 大、跟 CrowdStrike Falcon container sensor 競爭。</p>
<p><strong>SIEM 整合</strong>：Wiz Issues / Detections 可推到 <a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / <a href="/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &#43; CSPM &#43; CWS &#43; AAP &#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Security</a> / <a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-security-operations/" data-link-title="Google Security Operations" data-link-desc="Google 雲原生 SIEM &#43; SOAR &#43; Mandiant threat intel 三合一（前 Chronicle）、UDM &#43; YARA-L、fixed-price by data tier、PB-scale 友善">Google Security Operations</a> 走 SOAR playbook。常見 pattern：Wiz 偵測到 toxic combination → 推 Issue 到 Splunk → SOAR playbook 自動 isolate workload 或 rotate credential、走 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a> API。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Wiz</th>
          <th>Prisma Cloud (Palo Alto)</th>
          <th>Lacework</th>
          <th>CrowdStrike Falcon CS</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>部署模型</td>
          <td>Agentless-first（snapshot scan）+ 選配 Sensor</td>
          <td>Agent + agentless 混合</td>
          <td>Agent + agentless 混合、Polygraph behavior-base</td>
          <td>Agent-first（Falcon sensor 延伸）</td>
      </tr>
      <tr>
          <td>核心 concept</td>
          <td>Security Graph + Toxic Combination</td>
          <td>Cloud Security 套件（CSPM/CWP/CIEM/DSPM)</td>
          <td>Polygraph（ML behavior model）</td>
          <td>Falcon platform（EDR + cloud workload）</td>
      </tr>
      <tr>
          <td>計費模型</td>
          <td>Per workload + module</td>
          <td>Credit-based（modular）</td>
          <td>Per workload + data ingestion</td>
          <td>Per endpoint + module</td>
      </tr>
      <tr>
          <td>Multi-cloud</td>
          <td>強（AWS/GCP/Azure/OCI/K8s）</td>
          <td>強</td>
          <td>強</td>
          <td>強（但 Falcon-first 文化）</td>
      </tr>
      <tr>
          <td>Runtime 偵測</td>
          <td>Wiz Defend（2024+、成熟度仍在跟進）</td>
          <td>Prisma Cloud Defender（成熟）</td>
          <td>Polygraph 行為偵測（成熟）</td>
          <td>業界最強（EDR 出身）</td>
      </tr>
      <tr>
          <td>Developer 整合</td>
          <td>Wiz Code（IaC/SCA/PR scan）</td>
          <td>Prisma Cloud Code Security</td>
          <td>弱</td>
          <td>弱</td>
      </tr>
      <tr>
          <td>學習曲線</td>
          <td>中 — Graph query 是新語法但結構清楚</td>
          <td>陡 — 模組多、UX 較重</td>
          <td>中</td>
          <td>中 — Falcon UI 一致</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>Multi-cloud + 大型 org + 看重 attack path</td>
          <td>已用 Palo Alto 生態、需要 NGFW 整合</td>
          <td>ML-first 偵測、不想自己寫 rule</td>
          <td>已用 Falcon EDR、想擴到 cloud workload</td>
      </tr>
      <tr>
          <td>退場成本</td>
          <td>中 — Graph query / Toxic Combination 量大</td>
          <td>高 — 跟 Palo Alto 生態耦合</td>
          <td>中</td>
          <td>高 — Falcon sensor 已大規模部署很難換</td>
      </tr>
  </tbody>
</table>
<p>選 Wiz 的核心訴求：<em>multi-cloud + 中大型組織 + 願意接受 agentless 的 runtime 邊界 + 重視 toxic combination 的優先級</em>。如果組織已重度使用 CrowdStrike Falcon EDR、走 Falcon CS 延伸更一致；如果已重度 Palo Alto、走 Prisma Cloud 整合更深。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Security Graph query language</strong>：類 GraphQL 的 query syntax、可以寫「找所有 public-facing EC2、有 CVE-2024-XXX、能 assume role 到 admin account、且該 role 可讀 prod-pii bucket」這種 5-hop query。production 用法：把高頻 query 存成 <em>Saved Query</em> + alert、把 attack pattern 寫成 <em>Toxic Combination rule</em>。Graph query 寫得好不好直接決定 <em>attack path 是否被涵蓋</em>、跟 SPL 寫 correlation rule 是同一個 ownership 議題。</p>
<p><strong>Toxic Combination 設計</strong>：預設 rule 是 <em>generic 雲安全 anti-pattern</em>（public + vulnerable + over-permission）、organization 應該補 <em>industry-specific</em> 跟 <em>organization-specific</em> anti-pattern — 金融業要看「payment workload + cross-region replication + non-encrypted snapshot」、SaaS 多租戶要看「tenant-A workload + assume tenant-B role + 跨 tenant data access」。Toxic combination rule 走 PR review + staging tenant 驗證、跟 <a href="/blog/backend/07-security-data-protection/blue-team/detection-engineering-lifecycle/" data-link-title="7.B5 Detection Engineering Lifecycle" data-link-desc="把偵測規則視為可維護資產，建立從來源、測試、調校到退場的完整生命週期">Detection Engineering Lifecycle</a> 同流程。</p>
<p><strong>Wiz AI (2024+)</strong>：LLM-assisted investigation — 用自然語言查 graph（「show me all critical issues touching prod payment service」翻譯成 graph query）、Issue triage 自動 summarize attack path、根因建議。實務上是 query 翻譯 + summarize、不是替代 analyst 判讀；高 stake 決策仍要人類 review。</p>
<p><strong>Agentless secret scan</strong>：Wiz snapshot scan disk 時也掃 hardcoded secret（AWS access key / API token / private key）、跟 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a> / <a href="/blog/backend/07-security-data-protection/vendors/aws-secrets-manager/" data-link-title="AWS Secrets Manager" data-link-desc="AWS 原生 secret store &#43; 內建 RDS / Redshift rotation Lambda、Resource Policy 跨帳號共享、KMS 加密">AWS Secrets Manager</a> 整合做 rotation 路由。對應 <a href="/blog/backend/07-security-data-protection/secrets-and-machine-credential-governance/" data-link-title="7.6 秘密管理與機器憑證治理" data-link-desc="以問題驅動方式整理 secret、token、key 與機器身份治理">7.6 秘密管理與機器憑證治理</a> 的偵測層。</p>
<p><strong>Sigstore / SBOM 整合</strong>：Wiz 可消費 SBOM（<a href="/blog/backend/07-security-data-protection/vendors/syft-grype/" data-link-title="Syft &#43; Grype" data-link-desc="Anchore 開源姐妹工具：Syft 產 SBOM (CycloneDX / SPDX) &#43; Grype scan 漏洞、Unix philosophy、cosign attestation 整合">Syft / Grype</a> 或 <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> 產出）+ verify Cosign / Sigstore 簽章、把 <em>artifact trust</em> 接進 Security Graph。對應 <a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">7.12 供應鏈完整性與工件信任</a> 的 build-to-runtime 證據鏈。</p>
<p><strong>Wiz for AI</strong>：2024+ 新 module、針對 AI workload（LLM model storage / training dataset / inference endpoint）做 posture scan、找 misconfigured model bucket / exposed inference endpoint / training data leak。早期產品、定位是 <em>AI workload 的 CSPM 延伸</em>、不是替代 <a href="/blog/backend/07-security-data-protection/entrypoint-and-server-protection/" data-link-title="7.3 入口治理與伺服器防護" data-link-desc="以問題驅動方式整理對外入口、管理平面與伺服器邊界">AI red team / prompt injection 偵測</a> 工具。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Issue 爆炸 / 沒人 triage</strong>：default Project 收所有 finding、沒對齊 service ownership — 切 Project 給每個 BU / service、autoclose 已知 accepted risk、跟 Jira / Slack 整合自動分派</li>
<li><strong>Toxic Combination 沒命中真實 incident</strong>：只開預設 rule、沒寫 organization-specific rule — 從 <a href="/blog/backend/07-security-data-protection/red-team/" data-link-title="7.1 攻擊者視角（紅隊）與攻擊面驗證" data-link-desc="從攻擊者角度盤點暴露面、邊界、濫用路徑與資料外洩風險">red team case 庫</a> 反推自家環境的 attack path、寫成 custom rule</li>
<li><strong>Snapshot scan 漏掉 ephemeral workload</strong>：scan 間隔 12-24hr、短命 Lambda / Fargate task 沒掃到 — 補 Wiz runtime sensor 或外接 Falco；ephemeral workload 改用 build-time scan（<a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> / Wiz Code）</li>
<li><strong>Connector IAM role 權限漂移</strong>：自己加了權限結果踩 over-permission — Connector role 用 Wiz 提供的 CloudFormation / Terraform template、走 <a href="/blog/backend/05-deployment-platform/vendors/terraform/" data-link-title="Terraform / OpenTofu" data-link-desc="Infrastructure as Code 主流工具">Terraform</a> 版控、不手改</li>
<li><strong>Sticker shock / 計費爆炸</strong>：開了所有 module（CSPM + CWP + CIEM + KSPM + DSPM + Wiz Code + Defend）、workload count 暴衝 — 只開核心 module、ephemeral workload 走 sampling、enterprise contract 談 cap</li>
<li><strong>Wiz Code 跟 Snyk / Trivy 雙開</strong>：dev team 用 Snyk、SecOps 用 Wiz Code、PR 兩邊 finding 重複 — 選一邊做 dev-time gate、另一邊只當 visibility、不要兩邊都 block PR</li>
<li><strong>Wiz Defend 當 EDR 用結果偵測能力不夠</strong>：runtime detection 期待 CrowdStrike 等級 — Wiz Defend 仍在跟進、純 EDR 需求保留 CrowdStrike / SentinelOne、Wiz Defend 補 cloud context 層</li>
<li><strong>Audit log retention 不夠</strong>：Wiz 預設 audit retention 偏短、incident 回查時資料缺 — push Issue 跟 audit log 到 <a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / <a href="/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &#43; CSPM &#43; CWS &#43; AAP &#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog</a> 做長期保存</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>已用 Palo Alto NGFW / Prisma 生態</td>
          <td>Prisma Cloud</td>
      </tr>
      <tr>
          <td>已用 CrowdStrike Falcon EDR</td>
          <td>Falcon Cloud Security</td>
      </tr>
      <tr>
          <td>ML-first 偵測 / 不想寫 rule</td>
          <td>Lacework</td>
      </tr>
      <tr>
          <td>小型 / 單一雲 / 預算敏感</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> + cloud-native scanner（AWS Inspector / GCP SCC）</td>
      </tr>
      <tr>
          <td>Developer-first SAST + SCA</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk</a> / <a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GitHub Advanced Security</a></td>
      </tr>
      <tr>
          <td>Observability 已用 Datadog、不想再買 CNAPP</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &#43; CSPM &#43; CWS &#43; AAP &#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Security CSPM</a></td>
      </tr>
      <tr>
          <td>SIEM / 跨 source correlation</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / <a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-security-operations/" data-link-title="Google Security Operations" data-link-desc="Google 雲原生 SIEM &#43; SOAR &#43; Mandiant threat intel 三合一（前 Chronicle）、UDM &#43; YARA-L、fixed-price by data tier、PB-scale 友善">Google Security Operations</a></td>
      </tr>
      <tr>
          <td>Runtime container 行為偵測 (OSS)</td>
          <td>Falco / Cilium Tetragon</td>
      </tr>
      <tr>
          <td>Incident routing</td>
          <td><a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Security Graph query syntax 完整 reference 跟所有 built-in toxic combination rule 清單</li>
<li>Wiz Defend / Wiz Sensor 的 eBPF 內部實作細節</li>
<li>Wiz Code 跟 IDE plugin（VSCode / JetBrains）的具體設定</li>
<li>Cloud-native scanner（AWS Inspector / GCP Security Command Center / Azure Defender）的對照細節</li>
<li>Wiz API 的具體 SDK 用法跟 Terraform Provider 配置</li>
<li>CNAPP 市場的完整 vendor 比較（Gartner Magic Quadrant 等）</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>Wiz 在 07 案例庫沒有直接 vendor-level 事件、但多個 case 是 CNAPP 風險組合的對照：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 Wiz 的關係（對照啟示）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/data-exfiltration/snowflake-2024-credential-abuse/" data-link-title="7.R7.4.2 Snowflake 2024：憑證濫用與資料竊取" data-link-desc="外洩憑證與 MFA 缺口如何在資料平台形成高風險外送事件">Snowflake 2024 Credential Abuse</a></td>
          <td>Security Graph 可關聯「leaked credential + 過寬 IAM + 缺 MFA + 大量 data egress」四個 low-risk finding 成 toxic combination、提前 alert</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/data-exfiltration/lastpass-2022-backup-chain/" data-link-title="7.R7.4.1 LastPass 2022：備份路徑與鏈式入侵" data-link-desc="開發環境資訊外流如何沿著備份路徑擴大成資料風險">LastPass 2022 Backup Chain</a></td>
          <td>Wiz 可掃 S3 bucket public exposure + sensitive data + IAM scope、發現 backup bucket 配置漂移、對應 DSPM 場景</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/log4shell-cve-2021-44228-component-chain/" data-link-title="7.R7.2.7 Log4Shell 2021：共用元件風險與修補鏈" data-link-desc="共用元件漏洞如何同步影響多服務，並迫使團隊建立依賴治理 workflow">Log4Shell CVE-2021-44228</a></td>
          <td>Agentless snapshot scan 在 Log4Shell 期間可秒級回答「哪些 prod workload 有 log4j-core vulnerable version」、不需 endpoint agent rollout</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/solarwinds-2020-sunburst/" data-link-title="7.R7.2.1 SolarWinds 2020：更新鏈被濫用" data-link-desc="合法更新流程遭植入後，攻擊者如何長期潛伏與橫向擴散">SolarWinds 2020 Sunburst</a></td>
          <td>Wiz Code + Sigstore 整合可驗證 build artifact 來源、Security Graph 可串「signed artifact + 異常 runtime behavior」</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/entrypoint-and-server-protection/" data-link-title="7.3 入口治理與伺服器防護" data-link-desc="以問題驅動方式整理對外入口、管理平面與伺服器邊界">7.3 入口治理與伺服器防護 (section)</a></td>
          <td>Network exposure scan + IAM analysis 對應 section 原則、把「public + over-permission + sensitive」串成 toxic combination</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">7.12 供應鏈完整性 (section)</a></td>
          <td>Wiz Code IaC scan + image scan + SBOM 消費對應 build-to-runtime 證據鏈</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/entrypoint-and-server-protection/" data-link-title="7.3 入口治理與伺服器防護" data-link-desc="以問題驅動方式整理對外入口、管理平面與伺服器邊界">7.3 入口治理與伺服器防護</a>、<a href="/blog/backend/07-security-data-protection/identity-access-boundary/" data-link-title="7.2 身分與授權邊界" data-link-desc="以問題驅動方式整理身分、授權、會話與供應商身分鏈">7.2 身分與授權邊界</a>、<a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">7.13 偵測覆蓋率與訊號治理</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk</a>（dev-first SAST/SCA）、<a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a>（OSS scanner）、<a href="/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &#43; CSPM &#43; CWS &#43; AAP &#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Security</a>（observability + CSPM）</li>
<li>下游：<a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a>（Issues → SIEM）、<a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a>（SOAR 自動 rotation）、<a href="/blog/backend/07-security-data-protection/vendors/syft-grype/" data-link-title="Syft &#43; Grype" data-link-desc="Anchore 開源姐妹工具：Syft 產 SBOM (CycloneDX / SPDX) &#43; Grype scan 漏洞、Unix philosophy、cosign attestation 整合">Syft / Grype</a>（SBOM 接 Wiz Code）</li>
<li>跨類：<a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google Cloud IAM</a> / <a href="/blog/backend/07-security-data-protection/vendors/azure-rbac/" data-link-title="Azure RBAC &#43; Entra ID" data-link-desc="Azure 雙層身份/權限體系、Entra ID（IdP）&#43; Azure RBAC（resource permission）、Conditional Access、PIM、Managed Identity">Azure RBAC</a>（CIEM 分析對象）、<a href="/blog/backend/05-deployment-platform/vendors/terraform/" data-link-title="Terraform / OpenTofu" data-link-desc="Infrastructure as Code 主流工具">Terraform</a>（Connector / IaC 版控）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（Toxic combination → IR routing）、<a href="/blog/backend/05-deployment-platform/" data-link-title="模組五：部署平台與網路入口" data-link-desc="整理 Kubernetes、systemd、load balancer、container 與服務生命週期合約">5 部署平台</a>（cloud account / K8s onboarding）</li>
<li>官方：<a href="https://docs.wiz.io/">Wiz Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>Prisma Cloud</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/prisma-cloud/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/prisma-cloud/</guid><description>&lt;p>Prisma Cloud 是 Palo Alto Networks 旗下的 CNAPP（Cloud-Native Application Protection Platform）、把 &lt;em>runtime workload 防護&lt;/em>（Defender agent）跟 &lt;em>agentless cloud posture&lt;/em> 同一個 Console 整合。它的歷史是多次併購疊起來的 — Twistlock（container security）/ Redlock（CSPM）/ Bridgecrew（IaC scan）/ Aporeto（microsegmentation）— 五個模組各自有獨立的 data model 與 UI 軌跡。它跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/wiz/" data-link-title="Wiz" data-link-desc="Agentless CNAPP、Security Graph &amp;#43; Toxic Combination 風險優先級、API-only scan 不需 workload agent">Wiz&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/lacework/" data-link-title="Lacework" data-link-desc="CNAPP 走 Polygraph ML behavioral baseline 路線、2024 跟 Fortinet 合併成 FortiCNAPP、自動學 normal、anomaly 自動 alert">Lacework&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/crowdstrike-falcon-cs/" data-link-title="CrowdStrike Falcon Cloud Security" data-link-desc="CrowdStrike 在 Falcon endpoint EDR 之上的 CNAPP、agent 統一跨 endpoint &amp;#43; workload &amp;#43; container、CrowdStrike Intelligence 內建">CrowdStrike Falcon Cloud Security&lt;/a> 的差異在 &lt;em>是否走 host-level agent + 是否綁 Palo Alto 生態&lt;/em>、功能清單相近。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Prisma Cloud 的核心定位是 &lt;em>agent + agentless 雙軌 CNAPP&lt;/em>、五模組覆蓋 cloud workload 從 IaC 到 runtime 的完整鏈：&lt;em>Compute Security&lt;/em>（前 Twistlock、container / serverless / host workload 的 Defender agent + image scan）、&lt;em>CSPM&lt;/em>（cloud posture、misconfiguration、compliance baseline）、&lt;em>Code Security&lt;/em>（前 Bridgecrew、IaC 與 SCM scan）、&lt;em>Data Security&lt;/em>（DSPM、雲端資料庫與 bucket 敏感資料偵測）、&lt;em>CIEM&lt;/em>（cloud entitlement、跨雲 over-permission 治理）。Defender agent 是 host / pod / Lambda extension 上跑的常駐元件、提供 runtime IDS、file integrity、process anomaly 等 &lt;em>agentless 抓不到的訊號&lt;/em>。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/wiz/" data-link-title="Wiz" data-link-desc="Agentless CNAPP、Security Graph &amp;#43; Toxic Combination 風險優先級、API-only scan 不需 workload agent">Wiz&lt;/a> 比、Prisma 走 &lt;em>agent + agentless 雙軌&lt;/em>、Wiz 走 &lt;em>agentless-only&lt;/em>。Wiz 用 cloud snapshot scan + control-plane API 抽訊號、部署快、不踩 host；Prisma Defender agent 補上 &lt;em>runtime behavior&lt;/em> 的覆蓋（process spawn pattern、JNDI lookup、anomalous network connect）、代價是要在 host / pod / Lambda 上佈 agent、deployment 複雜度高一個層級。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/lacework/" data-link-title="Lacework" data-link-desc="CNAPP 走 Polygraph ML behavioral baseline 路線、2024 跟 Fortinet 合併成 FortiCNAPP、自動學 normal、anomaly 自動 alert">Lacework&lt;/a> 比、Lacework 用 &lt;em>Polygraph behavior graph&lt;/em> 做 host-level anomaly、focus 在 detection；Prisma 覆蓋面廣（含 IaC + CIEM + DSPM）、但每個模組深度比 Lacework 偵測單點淺一點。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/crowdstrike-falcon-cs/" data-link-title="CrowdStrike Falcon Cloud Security" data-link-desc="CrowdStrike 在 Falcon endpoint EDR 之上的 CNAPP、agent 統一跨 endpoint &amp;#43; workload &amp;#43; container、CrowdStrike Intelligence 內建">CrowdStrike Falcon Cloud Security&lt;/a> 比、CrowdStrike 的 endpoint agent 已在多數 enterprise 環境跑、Cloud Security 直接共用 endpoint plane；Prisma 是 &lt;em>cloud-first CNAPP 加上 agent&lt;/em>、不是 endpoint EDR 延伸。&lt;/p></description><content:encoded><![CDATA[<p>Prisma Cloud 是 Palo Alto Networks 旗下的 CNAPP（Cloud-Native Application Protection Platform）、把 <em>runtime workload 防護</em>（Defender agent）跟 <em>agentless cloud posture</em> 同一個 Console 整合。它的歷史是多次併購疊起來的 — Twistlock（container security）/ Redlock（CSPM）/ Bridgecrew（IaC scan）/ Aporeto（microsegmentation）— 五個模組各自有獨立的 data model 與 UI 軌跡。它跟 <a href="/blog/backend/07-security-data-protection/vendors/wiz/" data-link-title="Wiz" data-link-desc="Agentless CNAPP、Security Graph &#43; Toxic Combination 風險優先級、API-only scan 不需 workload agent">Wiz</a> / <a href="/blog/backend/07-security-data-protection/vendors/lacework/" data-link-title="Lacework" data-link-desc="CNAPP 走 Polygraph ML behavioral baseline 路線、2024 跟 Fortinet 合併成 FortiCNAPP、自動學 normal、anomaly 自動 alert">Lacework</a> / <a href="/blog/backend/07-security-data-protection/vendors/crowdstrike-falcon-cs/" data-link-title="CrowdStrike Falcon Cloud Security" data-link-desc="CrowdStrike 在 Falcon endpoint EDR 之上的 CNAPP、agent 統一跨 endpoint &#43; workload &#43; container、CrowdStrike Intelligence 內建">CrowdStrike Falcon Cloud Security</a> 的差異在 <em>是否走 host-level agent + 是否綁 Palo Alto 生態</em>、功能清單相近。</p>
<h2 id="服務定位">服務定位</h2>
<p>Prisma Cloud 的核心定位是 <em>agent + agentless 雙軌 CNAPP</em>、五模組覆蓋 cloud workload 從 IaC 到 runtime 的完整鏈：<em>Compute Security</em>（前 Twistlock、container / serverless / host workload 的 Defender agent + image scan）、<em>CSPM</em>（cloud posture、misconfiguration、compliance baseline）、<em>Code Security</em>（前 Bridgecrew、IaC 與 SCM scan）、<em>Data Security</em>（DSPM、雲端資料庫與 bucket 敏感資料偵測）、<em>CIEM</em>（cloud entitlement、跨雲 over-permission 治理）。Defender agent 是 host / pod / Lambda extension 上跑的常駐元件、提供 runtime IDS、file integrity、process anomaly 等 <em>agentless 抓不到的訊號</em>。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/wiz/" data-link-title="Wiz" data-link-desc="Agentless CNAPP、Security Graph &#43; Toxic Combination 風險優先級、API-only scan 不需 workload agent">Wiz</a> 比、Prisma 走 <em>agent + agentless 雙軌</em>、Wiz 走 <em>agentless-only</em>。Wiz 用 cloud snapshot scan + control-plane API 抽訊號、部署快、不踩 host；Prisma Defender agent 補上 <em>runtime behavior</em> 的覆蓋（process spawn pattern、JNDI lookup、anomalous network connect）、代價是要在 host / pod / Lambda 上佈 agent、deployment 複雜度高一個層級。跟 <a href="/blog/backend/07-security-data-protection/vendors/lacework/" data-link-title="Lacework" data-link-desc="CNAPP 走 Polygraph ML behavioral baseline 路線、2024 跟 Fortinet 合併成 FortiCNAPP、自動學 normal、anomaly 自動 alert">Lacework</a> 比、Lacework 用 <em>Polygraph behavior graph</em> 做 host-level anomaly、focus 在 detection；Prisma 覆蓋面廣（含 IaC + CIEM + DSPM）、但每個模組深度比 Lacework 偵測單點淺一點。跟 <a href="/blog/backend/07-security-data-protection/vendors/crowdstrike-falcon-cs/" data-link-title="CrowdStrike Falcon Cloud Security" data-link-desc="CrowdStrike 在 Falcon endpoint EDR 之上的 CNAPP、agent 統一跨 endpoint &#43; workload &#43; container、CrowdStrike Intelligence 內建">CrowdStrike Falcon Cloud Security</a> 比、CrowdStrike 的 endpoint agent 已在多數 enterprise 環境跑、Cloud Security 直接共用 endpoint plane；Prisma 是 <em>cloud-first CNAPP 加上 agent</em>、不是 endpoint EDR 延伸。</p>
<p>關鍵張力：<em>覆蓋面廣度</em> ↔ <em>模組整合成熟度</em> 是 Prisma 客戶最常踩的 trade-off。五模組來自不同收購、UI / API / data model 整合仍在進行中、客戶常遇到「同一個 finding 在 Compute Console 顯示是 critical、在 CSPM 是 medium」、或「Code Security 報的 IaC issue 跟 Runtime 報的實際 config 對不起來」。預算允許就用 Prisma 拿覆蓋面廣度、不允許就走 Wiz（agentless 部署快）或 Lacework（單模組偵測深）。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>Prisma Cloud 在 cloud security stack 中承擔哪幾段（Compute / CSPM / Code / Data / CIEM）、哪些跟既有 SIEM / EDR / IdP 重疊或互補</li>
<li>Defender agent 該佈在 host / pod / Lambda 哪幾層、跟 <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> / <a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk</a> 等 OSS / SaaS image scanner 的分工</li>
<li>Compliance template（PCI / HIPAA / NIST / FedRAMP）跟自家 custom policy 的混用方式、誰能改 policy、誰 review</li>
<li>何時用 Prisma、何時改走 Wiz（agentless-only）/ Lacework（detection-focused）/ Trivy（OSS CLI）/ EDR</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Prisma 部署是否健康、最少看四件事：</p>
<ul>
<li><strong>Defender agent 覆蓋率</strong>：production K8s cluster 的 DaemonSet 是否所有 node 跑、VM workload 的 agent install rate、Lambda function 的 extension 啟用比例；缺一塊就有 runtime 偵測盲點</li>
<li><strong>Console 跟模組一致性</strong>：Compute Console / CSPM dashboard / Code Security finding / CIEM report 同一個 resource 的風險評級是否一致、不一致時誰是 SSoT</li>
<li><strong>Compliance template 對齊</strong>：啟用了哪幾套（PCI-DSS / HIPAA / NIST 800-53 / CIS / FedRAMP / SOC2）、跟內部 baseline 的客製 rule 是否走版控</li>
<li><strong>Alert 跟 SOC handoff</strong>：Prisma alert 是進自家 incident queue 還是 forward 到 <a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-security-operations/" data-link-title="Google Security Operations" data-link-desc="Google 雲原生 SIEM &#43; SOAR &#43; Mandiant threat intel 三合一（前 Chronicle）、UDM &#43; YARA-L、fixed-price by data tier、PB-scale 友善">Google Security Operations</a>、Cortex XSOAR 是否串 playbook</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">Detection Coverage and Signal Governance</a> 邊界的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>Defender agent deployment</strong>：agent 三種 footprint — <em>K8s DaemonSet</em>（每個 node 一個、攔截 container syscall + image runtime scan）、<em>VM / host agent</em>（Linux / Windows 安裝、file integrity + process anomaly）、<em>Lambda extension</em>（function runtime 注入、serverless 行為偵測）。Production 通常是 DaemonSet + VM agent 雙軌、Lambda extension 視 serverless workload 規模啟用。deployment 比 Wiz 多一步 — 要走 IaC（Helm chart / Terraform module）管 agent rollout、不能手動裝。</p>
<p><strong>Console 跟 RBAC</strong>：Prisma Cloud Console 是統一入口、但底下 <em>Compute</em>（前 Twistlock UI 殘留）跟 <em>Cloud</em>（CSPM / Code / Data / CIEM）兩個 plane 分開。RBAC 角色設計常踩坑 — Compute 的 collection（host group）跟 Cloud 的 account group 是不同概念、需要分別給權限。</p>
<p><strong>CSPM connector</strong>：CSPM 走 read-only cloud API（AWS Cross-Account Role / GCP Service Account / Azure App Registration）抽 config snapshot、定期 reconcile baseline。連 cloud account 是 onboarding 第一步、跟 <a href="/blog/backend/07-security-data-protection/vendors/wiz/" data-link-title="Wiz" data-link-desc="Agentless CNAPP、Security Graph &#43; Toxic Combination 風險優先級、API-only scan 不需 workload agent">Wiz</a> / <a href="/blog/backend/07-security-data-protection/vendors/lacework/" data-link-title="Lacework" data-link-desc="CNAPP 走 Polygraph ML behavioral baseline 路線、2024 跟 Fortinet 合併成 FortiCNAPP、自動學 normal、anomaly 自動 alert">Lacework</a> 同樣的 pattern、Prisma 的 connector permission template 偏寬、要 review 哪些 API 真用得到。</p>
<p><strong>Code Security（Bridgecrew）</strong>：IaC scan 走 GitHub / GitLab / Bitbucket App、Terraform / CloudFormation / Kubernetes manifest / Dockerfile 在 PR 階段攔截 misconfiguration。Checkov 是 Bridgecrew 開源的底層引擎、Prisma 把 Checkov 規則庫 + 自家 policy 包成 SaaS。對應 <a href="/blog/backend/06-reliability/release-gate/" data-link-title="6.8 Release Gate 與變更節奏" data-link-desc="把驗證、migration、相容性納入放行判準">6.6 release gate</a>、IaC issue 在 PR 階段擋比 runtime 抓便宜兩個量級。</p>
<p><strong>CIEM</strong>：cloud entitlement 治理、跨 AWS IAM / GCP IAM / Azure RBAC 找 over-permission 跟 toxic combination（例如 user 同時有 <code>iam:PassRole</code> + <code>lambda:CreateFunction</code> 可 privilege escalation）。CIEM 報告通常是大量「建議收權限」、實際 remediation 要跟 <a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google Cloud IAM</a> owner 排優先序、不是看到全收。</p>
<p><strong>Data Security（DSPM）</strong>：雲端資料庫（RDS / BigQuery / Snowflake）+ object store（S3 / GCS）的 sensitive data discovery、跟 <a href="/blog/backend/07-security-data-protection/vendors/google-dlp/" data-link-title="Google DLP" data-link-desc="GCP 原生 Sensitive Data Protection：infoType discovery &#43; transformation (mask / FPE / tokenize / k-anonymity)、整合 BigQuery / GCS / Cloud SQL">Google DLP</a> / <a href="/blog/backend/07-security-data-protection/vendors/microsoft-purview/" data-link-title="Microsoft Purview" data-link-desc="Microsoft 跨 M365 / Azure / endpoint 的 data governance &#43; information protection &#43; DLP &#43; insider risk 統合平台、label-driven">Microsoft Purview</a> 功能重疊。Prisma DSPM 的優勢是跟 CSPM / CIEM 同 Console、可以看「敏感資料所在的 bucket 是否有 public ACL + 哪些 role 可以讀」、是 <em>資料 + 入口 + 身份</em> 同 plane 的關聯。</p>
<p><strong>Runtime Protection（Aporeto microsegmentation）</strong>：Defender agent 提供 process / network level 的 runtime IDS / IPS — JNDI lookup 行為、異常 outbound callback、container escape 嘗試、unsigned binary 執行。比起 image-scan-only 多了 <em>已知 CVE 沒 patch 但 runtime 行為偵測到</em> 的覆蓋層。</p>
<p><strong>跟 Palo Alto 生態整合</strong>：Prisma alert 可直接打到 Palo Alto <em>Cortex XSOAR</em>（SOAR / playbook）/ <em>Cortex XDR</em>（endpoint + cloud unified detection）/ <em>NGFW / SASE</em>（firewall rule 自動 push）。對已是 Palo Alto-heavy 環境是生態一致性增加；對非 Palo Alto 環境、Prisma 也 forward 到 <a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / <a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a> 走 webhook / Syslog。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Prisma Cloud</th>
          <th>Wiz</th>
          <th>Lacework</th>
          <th>CrowdStrike Falcon Cloud Security</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>部署模型</td>
          <td>Agent (Defender) + Agentless 雙軌</td>
          <td>Agentless-only（snapshot scan + API）</td>
          <td>Lightweight agent + agentless 雙軌</td>
          <td>沿用 CrowdStrike endpoint agent + agentless</td>
      </tr>
      <tr>
          <td>部署速度</td>
          <td>慢 — agent rollout 走 IaC + RBAC 設定多</td>
          <td>快 — connector 連 cloud account 就開始 scan</td>
          <td>中 — agent 較輕、但仍需安裝</td>
          <td>快（若已用 CrowdStrike）/ 中（新導入）</td>
      </tr>
      <tr>
          <td>Runtime 偵測</td>
          <td>強 — Defender 攔 syscall / network / file IDS</td>
          <td>弱 — runtime behavior 靠 snapshot 對照、延遲高</td>
          <td>強 — Polygraph behavior graph 為核心</td>
          <td>強 — endpoint agent runtime telemetry</td>
      </tr>
      <tr>
          <td>Posture / CSPM</td>
          <td>強 — Redlock 出身、compliance template 最完整</td>
          <td>強 — graph-based blast radius 視覺化最好</td>
          <td>中 — 有 CSPM 但 focus 在 detection</td>
          <td>中 — CSPM 後加入、深度比 Prisma / Wiz 淺</td>
      </tr>
      <tr>
          <td>IaC scan</td>
          <td>強 — Bridgecrew 整合、Checkov 底層</td>
          <td>中 — IaC scan 較新</td>
          <td>弱 — 非主力</td>
          <td>弱 — 非主力</td>
      </tr>
      <tr>
          <td>CIEM</td>
          <td>強 — 五模組原生</td>
          <td>強 — graph-based entitlement analysis</td>
          <td>中</td>
          <td>中</td>
      </tr>
      <tr>
          <td>DSPM</td>
          <td>中 — Data Security 模組</td>
          <td>強 — DSPM 是近年強推</td>
          <td>弱</td>
          <td>弱</td>
      </tr>
      <tr>
          <td>模組整合成熟度</td>
          <td>中 — 五次收購、UI / data model 仍在整合</td>
          <td>強 — single platform 原生設計</td>
          <td>強 — 單一 data model</td>
          <td>中 — endpoint + cloud 整合中</td>
      </tr>
      <tr>
          <td>Compliance 廣度</td>
          <td>強 — PCI / HIPAA / NIST / FedRAMP / SOC2 完整</td>
          <td>中 — 主要 compliance 都有但模板較淺</td>
          <td>中</td>
          <td>中</td>
      </tr>
      <tr>
          <td>生態整合</td>
          <td>強 — Palo Alto NGFW / Cortex XDR / XSOAR 同 plane</td>
          <td>中 — vendor-neutral、走 webhook / API</td>
          <td>中</td>
          <td>強 — CrowdStrike Falcon 生態</td>
      </tr>
      <tr>
          <td>計費複雜度</td>
          <td>高 — module + credit + workload + multi-year</td>
          <td>中 — workload / cloud account 為主</td>
          <td>中</td>
          <td>中</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>Palo Alto-heavy、agent + posture 雙覆蓋、合規重</td>
          <td>Cloud-native、agentless-first、部署速度優先</td>
          <td>Detection-heavy、Polygraph anomaly 為核心</td>
          <td>CrowdStrike-heavy、endpoint + cloud 統一</td>
      </tr>
      <tr>
          <td>退場成本</td>
          <td>高 — agent + policy + Cortex 整合多</td>
          <td>中 — agentless、移除 connector 就乾淨</td>
          <td>中</td>
          <td>高（若深度整合 CrowdStrike）</td>
      </tr>
  </tbody>
</table>
<p>選 Prisma 的核心訴求：<em>已在 Palo Alto 生態（NGFW / SASE / Cortex XDR / XSOAR）+ 需要 runtime agent + posture 雙覆蓋 + compliance audit heavy（PCI / HIPAA / FedRAMP）</em>、且能承擔模組整合不完美 + 部署複雜度 + multi-year contract。純 agentless 用 Wiz、detection-focused 用 Lacework、純 OSS PR scan 用 <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> + <a href="/blog/backend/07-security-data-protection/vendors/syft-grype/" data-link-title="Syft &#43; Grype" data-link-desc="Anchore 開源姐妹工具：Syft 產 SBOM (CycloneDX / SPDX) &#43; Grype scan 漏洞、Unix philosophy、cosign attestation 整合">Syft / Grype</a>。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Defender agent rollout 策略</strong>：K8s DaemonSet 用 Helm chart 管 version + tolerations、staging cluster 先跑 1-2 週觀察 syscall overhead 跟 false positive、再 promote 到 production。VM agent 走 Ansible / SCCM / Terraform user-data、image baking 把 agent 包進 golden AMI 比每次 boot 安裝穩。Lambda extension 走 Lambda Layer、只對 high-value function 開（金流 / IdP / secret access）、不是全 function 都包。</p>
<p><strong>Runtime IDS / IPS 模式</strong>：Defender 可設 <em>audit only</em>（只 log、不阻擋）或 <em>prevent</em>（自動 kill process / block network）。production 多數 workload 走 audit、只對 <em>確定無誤報</em> 的 rule 開 prevent（已知 malware hash、明確 CVE exploit pattern）。誤判 prevent 業務 process 比放過 alert 代價高、應該預設 audit + SIEM forward + SOC triage。</p>
<p><strong>Compliance template + Custom policy 混用</strong>：Prisma 提供 PCI-DSS / HIPAA / NIST 800-53 / CIS Benchmark / FedRAMP / SOC2 完整 baseline、可直接啟用。但 baseline 通常太嚴或太寬、實務做法是 <em>fork baseline + 加自家 exception + 加 organization-specific rule</em>、走 Git 版控（policy as code、JSON / YAML）、PR review 後 sync 回 Console。policy 不能 console 直改、否則跟既有 SIEM rule 一樣失去 change history。</p>
<p><strong>Cortex XSOAR / XDR 整合</strong>：Prisma alert → XSOAR playbook 是 Palo Alto 環境的標準路徑、playbook 自動執行 enrichment（拉 threat intel）/ containment（NGFW block / disable IAM user）/ remediation（Terraform PR auto-create）。playbook 要走版控 + dry-run、高影響動作（disable IAM user / delete resource）走 approval gate、不能 fire-and-forget。</p>
<p><strong>計費結構</strong>：Prisma 按 <em>module 選購</em> + 按 <em>credit 消耗</em> + 按 <em>workload count</em> 三層計費、enterprise 通常是 <em>multi-year package</em>（3 年 commit 拿折扣）。實務坑 — 加新 cloud account 沒控管會吃 credit、Code Security 對大 monorepo scan 也吃 credit、Data Security 對大 bucket scan 是高成本項。月底常見的 sticker shock 來自 <em>Defender agent 數量爆衝</em>（K8s auto-scale 把 node count 推高）跟 <em>新 cloud account onboard 沒走 quota 控管</em>。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Defender agent overhead 影響業務 process</strong>：DaemonSet pod 吃 CPU / memory 過高、container syscall hook 拖慢 latency-sensitive workload — 把 <em>runtime rule</em> 從 prevent 改 audit、調 collection scope 排除 latency-critical namespace、向 Palo Alto support 開 ticket 看 agent profile</li>
<li><strong>同一個 finding 模組評級不一致</strong>：Compute Console 顯示 critical、CSPM 顯示 medium — 確認 <em>SSoT 是哪個模組</em>、Compute 是 workload-level、CSPM 是 cloud-config-level、兩者本來就看不同 layer、用 Cortex XSOAR 統一 prioritization 而非靠 Console 對齊</li>
<li><strong>CSPM connector permission 報錯</strong>：Prisma 預設 IAM policy 太寬 / 太窄 — 走 <em>least privilege</em> 版本、跟 <a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM</a> owner 確認哪些 API 真用到、不要照官方 template 全開</li>
<li><strong>Compliance template 一啟用就 1000+ finding</strong>：baseline 太嚴 + 既有環境本來就沒符合 — 走 <em>staged adoption</em>、先選 critical control（IAM / encryption / public exposure）、剩下進 backlog 排期、不要一次全開</li>
<li><strong>Code Security PR scan block 太多</strong>：Bridgecrew rule 對既有 IaC noisy — 用 <em>baseline mode</em>（既有 issue 標記、只 block 新 issue）、給 team 12 週 SLA 清 backlog、不要 day-1 block 全部</li>
<li><strong>CIEM 報告太多 over-permission</strong>：5000+ unused permission 看不完 — 排序看 <em>toxic combination</em>（privilege escalation path）優先、單純 unused 走每季 access review、不一次處理</li>
<li><strong>Cortex XSOAR playbook 誤殺</strong>：自動 disable IAM user 結果關到 CI/CD service account — 高影響動作走 <em>approval gate</em>、playbook default 是 <em>containment</em>（temporary block）not <em>deletion</em></li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>純 agentless / 部署速度優先</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/wiz/" data-link-title="Wiz" data-link-desc="Agentless CNAPP、Security Graph &#43; Toxic Combination 風險優先級、API-only scan 不需 workload agent">Wiz</a></td>
      </tr>
      <tr>
          <td>Polygraph behavior detection 為核心</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/lacework/" data-link-title="Lacework" data-link-desc="CNAPP 走 Polygraph ML behavioral baseline 路線、2024 跟 Fortinet 合併成 FortiCNAPP、自動學 normal、anomaly 自動 alert">Lacework</a></td>
      </tr>
      <tr>
          <td>CrowdStrike-heavy 環境</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/crowdstrike-falcon-cs/" data-link-title="CrowdStrike Falcon Cloud Security" data-link-desc="CrowdStrike 在 Falcon endpoint EDR 之上的 CNAPP、agent 統一跨 endpoint &#43; workload &#43; container、CrowdStrike Intelligence 內建">CrowdStrike Falcon Cloud Security</a></td>
      </tr>
      <tr>
          <td>純 OSS image / IaC scan</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> / <a href="/blog/backend/07-security-data-protection/vendors/syft-grype/" data-link-title="Syft &#43; Grype" data-link-desc="Anchore 開源姐妹工具：Syft 產 SBOM (CycloneDX / SPDX) &#43; Grype scan 漏洞、Unix philosophy、cosign attestation 整合">Syft / Grype</a> / <a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk</a></td>
      </tr>
      <tr>
          <td>DLP / sensitive data 為主</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/google-dlp/" data-link-title="Google DLP" data-link-desc="GCP 原生 Sensitive Data Protection：infoType discovery &#43; transformation (mask / FPE / tokenize / k-anonymity)、整合 BigQuery / GCS / Cloud SQL">Google DLP</a> / <a href="/blog/backend/07-security-data-protection/vendors/microsoft-purview/" data-link-title="Microsoft Purview" data-link-desc="Microsoft 跨 M365 / Azure / endpoint 的 data governance &#43; information protection &#43; DLP &#43; insider risk 統合平台、label-driven">Microsoft Purview</a></td>
      </tr>
      <tr>
          <td>SIEM 偵測 / SOC</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / <a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a></td>
      </tr>
      <tr>
          <td>入口 WAF</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &#43; DDoS &#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF</a> / <a href="/blog/backend/07-security-data-protection/vendors/aws-waf/" data-link-title="AWS WAF" data-link-desc="AWS-internal WAF、跟 ALB / CloudFront / API Gateway 直接整合、Web ACL &#43; Managed Rule Group &#43; Rate-based Rule、Shield Standard 內含">AWS WAF</a></td>
      </tr>
      <tr>
          <td>事故 routing</td>
          <td><a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Defender agent 完整 syscall hook 清單 / runtime rule 語法 reference</li>
<li>Bridgecrew Checkov 規則庫的逐條解釋 / 自寫 Checkov rule 細節</li>
<li>Palo Alto Cortex XSOAR playbook 的 Python SDK 實作</li>
<li>Prisma SASE / NGFW / Cortex XDR 完整功能（屬 network security / EDR、不在 CNAPP 範圍）</li>
<li>Compliance 法規的逐條解讀（PCI-DSS / HIPAA 法律面）</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>Prisma 在 07 案例庫沒有直接 vendor-level 事件、但多個 supply chain / edge exposure case 是 Defender runtime + image scan 雙層的對照：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 Prisma 的關係（對照啟示）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/log4shell-cve-2021-44228-component-chain/" data-link-title="7.R7.2.7 Log4Shell 2021：共用元件風險與修補鏈" data-link-desc="共用元件漏洞如何同步影響多服務，並迫使團隊建立依賴治理 workflow">Log4Shell CVE-2021-44228</a></td>
          <td>Defender agent runtime 可偵測 JNDI lookup 行為、補 SBOM / image scan 看不到的 <em>dynamic class load 在 runtime 才觸發</em> 缺口、跟 <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> image scan 互補</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/3cx-2023-desktopapp-supply-chain/" data-link-title="7.R7.2.8 3CX 2023：桌面軟體更新鏈攻擊" data-link-desc="合法更新流程被植入後，桌面端供應鏈事件如何傳到企業端點">3CX 2023 Desktop App Supply Chain</a></td>
          <td>Defender runtime 偵測異常 process spawn + outbound C2 callback、補 image-level scan 對 <em>已簽章但 runtime 行為異常</em> 的缺口、不能只靠 IoC</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/solarwinds-2020-sunburst/" data-link-title="7.R7.2.1 SolarWinds 2020：更新鏈被濫用" data-link-desc="合法更新流程遭植入後，攻擊者如何長期潛伏與橫向擴散">SolarWinds 2020 Sunburst</a></td>
          <td>runtime behavior anomaly（DNS beacon + dormant period）優於 IoC-only 規則、配合 image signing 雙層覆蓋、Defender + Code Security 在 build / runtime 雙閘</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/edge-exposure/citrix-bleed-2023-session-hijack/" data-link-title="7.R7.3.3 Citrix Bleed 2023：會話被劫持與重放風險" data-link-desc="邊界設備會話資料外洩後，如何演變成帳號與服務風險">Citrix Bleed 2023 Session Hijack</a></td>
          <td>Defender host-layer 偵測異常 session 動作（不能阻擋上游 edge zero-day、但事後 forensic 跟 lateral movement containment 有用）、補 edge appliance 看不到的 host-side 軌跡</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">7.13 偵測覆蓋率與訊號治理</a>、<a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">7.10 供應鏈與第三方信任</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/wiz/" data-link-title="Wiz" data-link-desc="Agentless CNAPP、Security Graph &#43; Toxic Combination 風險優先級、API-only scan 不需 workload agent">Wiz</a>、<a href="/blog/backend/07-security-data-protection/vendors/lacework/" data-link-title="Lacework" data-link-desc="CNAPP 走 Polygraph ML behavioral baseline 路線、2024 跟 Fortinet 合併成 FortiCNAPP、自動學 normal、anomaly 自動 alert">Lacework</a>、<a href="/blog/backend/07-security-data-protection/vendors/crowdstrike-falcon-cs/" data-link-title="CrowdStrike Falcon Cloud Security" data-link-desc="CrowdStrike 在 Falcon endpoint EDR 之上的 CNAPP、agent 統一跨 endpoint &#43; workload &#43; container、CrowdStrike Intelligence 內建">CrowdStrike Falcon Cloud Security</a></li>
<li>下游：<a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / <a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a>（Prisma alert forward）、<a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google Cloud IAM</a>（CIEM remediation 落地）</li>
<li>跨類：<a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> / <a href="/blog/backend/07-security-data-protection/vendors/syft-grype/" data-link-title="Syft &#43; Grype" data-link-desc="Anchore 開源姐妹工具：Syft 產 SBOM (CycloneDX / SPDX) &#43; Grype scan 漏洞、Unix philosophy、cosign attestation 整合">Syft / Grype</a>（OSS image scan 互補）、<a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GitHub Advanced Security</a> / <a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk</a>（SCA 互補）</li>
<li>跨模組：<a href="/blog/backend/06-reliability/release-gate/" data-link-title="6.8 Release Gate 與變更節奏" data-link-desc="把驗證、migration、相容性納入放行判準">6.6 release gate</a>（Code Security PR scan）、<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（alert handoff）</li>
<li>官方：<a href="https://docs.prismacloud.io/">Prisma Cloud Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>Lacework</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/lacework/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/lacework/</guid><description>&lt;p>Lacework 是 CNAPP（Cloud-Native Application Protection Platform）走 &lt;em>Polygraph ML behavioral baseline&lt;/em> 路線的代表廠商、2024 年跟 Fortinet 合併、新品牌叫 &lt;em>Fortinet Lacework FortiCNAPP&lt;/em>、但 Lacework 名稱與獨立產品線仍在運作。它跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/wiz/" data-link-title="Wiz" data-link-desc="Agentless CNAPP、Security Graph &amp;#43; Toxic Combination 風險優先級、API-only scan 不需 workload agent">Wiz&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/prisma-cloud/" data-link-title="Prisma Cloud" data-link-desc="Palo Alto CNAPP、agent (Defender) &amp;#43; agentless 雙軌、五模組（Compute / CSPM / Code / Data / CIEM）、Compliance template 強">Prisma Cloud&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/crowdstrike-falcon-cs/" data-link-title="CrowdStrike Falcon Cloud Security" data-link-desc="CrowdStrike 在 Falcon endpoint EDR 之上的 CNAPP、agent 統一跨 endpoint &amp;#43; workload &amp;#43; container、CrowdStrike Intelligence 內建">CrowdStrike Falcon Cloud Security&lt;/a> 的差異在 &lt;em>偵測設計哲學&lt;/em>、覆蓋面相近 — Lacework 的核心競爭力是 Polygraph 自動從 log + process + network + cloud API call 學 baseline、anomaly 自動觸發、不需 SOC 手寫 detection rule。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Lacework 的核心定位是 &lt;em>Polygraph 驅動的 CNAPP&lt;/em>、以 ML 自動學習正常行為作為偵測基礎。產品線涵蓋四個能力面：&lt;em>CSPM&lt;/em>（Cloud Security Posture Management、misconfiguration 與合規 scan）、&lt;em>CWPP&lt;/em>（Cloud Workload Protection Platform、host + container runtime 防護）、&lt;em>Code Security&lt;/em>（IaC scan、container image scan、SAST baseline）、以及貫穿全平台的 &lt;em>Polygraph behavioral baseline engine&lt;/em>。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/wiz/" data-link-title="Wiz" data-link-desc="Agentless CNAPP、Security Graph &amp;#43; Toxic Combination 風險優先級、API-only scan 不需 workload agent">Wiz&lt;/a> 比、設計哲學是相反的：Wiz 走 &lt;em>Security Graph + Toxic Combination&lt;/em>（你顯式定義「EC2 + RCE + IMDS v1 + cross-account role」是 toxic、graph 找匹配 path）、Lacework 走 &lt;em>Polygraph implicit baseline&lt;/em>（你不定義、ML 從 30 天歷史學 normal、偏離就 alert）。兩種都是 graph、但一個是 rule-driven graph、一個是 behavior-learned graph。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/prisma-cloud/" data-link-title="Prisma Cloud" data-link-desc="Palo Alto CNAPP、agent (Defender) &amp;#43; agentless 雙軌、五模組（Compute / CSPM / Code / Data / CIEM）、Compliance template 強">Prisma Cloud&lt;/a> 比、Prisma 是 &lt;em>多模組 agent + agentless 寬覆蓋&lt;/em>、Lacework 主打 Polygraph 為單一核心引擎、不靠堆模組廣度競爭。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/crowdstrike-falcon-cs/" data-link-title="CrowdStrike Falcon Cloud Security" data-link-desc="CrowdStrike 在 Falcon endpoint EDR 之上的 CNAPP、agent 統一跨 endpoint &amp;#43; workload &amp;#43; container、CrowdStrike Intelligence 內建">CrowdStrike Falcon CS&lt;/a> 比、Falcon CS 是 &lt;em>endpoint EDR 延伸到 cloud&lt;/em>、Lacework 從第一天就為 cloud-native designed、沒 endpoint EDR 包袱。&lt;/p></description><content:encoded><![CDATA[<p>Lacework 是 CNAPP（Cloud-Native Application Protection Platform）走 <em>Polygraph ML behavioral baseline</em> 路線的代表廠商、2024 年跟 Fortinet 合併、新品牌叫 <em>Fortinet Lacework FortiCNAPP</em>、但 Lacework 名稱與獨立產品線仍在運作。它跟 <a href="/blog/backend/07-security-data-protection/vendors/wiz/" data-link-title="Wiz" data-link-desc="Agentless CNAPP、Security Graph &#43; Toxic Combination 風險優先級、API-only scan 不需 workload agent">Wiz</a> / <a href="/blog/backend/07-security-data-protection/vendors/prisma-cloud/" data-link-title="Prisma Cloud" data-link-desc="Palo Alto CNAPP、agent (Defender) &#43; agentless 雙軌、五模組（Compute / CSPM / Code / Data / CIEM）、Compliance template 強">Prisma Cloud</a> / <a href="/blog/backend/07-security-data-protection/vendors/crowdstrike-falcon-cs/" data-link-title="CrowdStrike Falcon Cloud Security" data-link-desc="CrowdStrike 在 Falcon endpoint EDR 之上的 CNAPP、agent 統一跨 endpoint &#43; workload &#43; container、CrowdStrike Intelligence 內建">CrowdStrike Falcon Cloud Security</a> 的差異在 <em>偵測設計哲學</em>、覆蓋面相近 — Lacework 的核心競爭力是 Polygraph 自動從 log + process + network + cloud API call 學 baseline、anomaly 自動觸發、不需 SOC 手寫 detection rule。</p>
<h2 id="服務定位">服務定位</h2>
<p>Lacework 的核心定位是 <em>Polygraph 驅動的 CNAPP</em>、以 ML 自動學習正常行為作為偵測基礎。產品線涵蓋四個能力面：<em>CSPM</em>（Cloud Security Posture Management、misconfiguration 與合規 scan）、<em>CWPP</em>（Cloud Workload Protection Platform、host + container runtime 防護）、<em>Code Security</em>（IaC scan、container image scan、SAST baseline）、以及貫穿全平台的 <em>Polygraph behavioral baseline engine</em>。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/wiz/" data-link-title="Wiz" data-link-desc="Agentless CNAPP、Security Graph &#43; Toxic Combination 風險優先級、API-only scan 不需 workload agent">Wiz</a> 比、設計哲學是相反的：Wiz 走 <em>Security Graph + Toxic Combination</em>（你顯式定義「EC2 + RCE + IMDS v1 + cross-account role」是 toxic、graph 找匹配 path）、Lacework 走 <em>Polygraph implicit baseline</em>（你不定義、ML 從 30 天歷史學 normal、偏離就 alert）。兩種都是 graph、但一個是 rule-driven graph、一個是 behavior-learned graph。跟 <a href="/blog/backend/07-security-data-protection/vendors/prisma-cloud/" data-link-title="Prisma Cloud" data-link-desc="Palo Alto CNAPP、agent (Defender) &#43; agentless 雙軌、五模組（Compute / CSPM / Code / Data / CIEM）、Compliance template 強">Prisma Cloud</a> 比、Prisma 是 <em>多模組 agent + agentless 寬覆蓋</em>、Lacework 主打 Polygraph 為單一核心引擎、不靠堆模組廣度競爭。跟 <a href="/blog/backend/07-security-data-protection/vendors/crowdstrike-falcon-cs/" data-link-title="CrowdStrike Falcon Cloud Security" data-link-desc="CrowdStrike 在 Falcon endpoint EDR 之上的 CNAPP、agent 統一跨 endpoint &#43; workload &#43; container、CrowdStrike Intelligence 內建">CrowdStrike Falcon CS</a> 比、Falcon CS 是 <em>endpoint EDR 延伸到 cloud</em>、Lacework 從第一天就為 cloud-native designed、沒 endpoint EDR 包袱。</p>
<p>關鍵張力：<em>implicit behavioral baseline</em> ↔ <em>explicit auditable rule</em> 是 Lacework 客戶最大的取捨。Polygraph 內部用 ML 學行為、好處是 zero rule maintenance、自動覆蓋未知 attack pattern；代價是內部邏輯不透明、false positive / false negative 都不容易 debug、強合規場景需要 explicit rule 可審計時會卡住。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>Lacework 在 cloud security stack 中承擔哪段（CSPM / CWPP / Code Security / behavioral detection）、哪些要外接（<a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> 等 SIEM 接 alert、<a href="/blog/backend/08-incident-response/" data-link-title="模組八：事故處理與復盤" data-link-desc="用 IR 領域詞彙建問題節點、以服務級案例庫累積事故脈絡，先建概念與案例庫再進實作交接">8 事故處理</a> 接 IR routing）</li>
<li>Polygraph ML baseline 的 ownership 設計（誰調 anomaly threshold、false positive 由誰判讀、ML model retraining cadence 誰負責）</li>
<li><em>implicit baseline</em> vs <em>explicit rule</em> 的取捨何時偏 Lacework、何時要補 Wiz / Prisma 的 explicit rule layer</li>
<li>何時用 Lacework、何時走 Wiz / Prisma Cloud / Falcon CS</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Lacework deployment 是否健康、最少看四件事：</p>
<ul>
<li><strong>Polygraph baseline 覆蓋面</strong>：哪些 cloud account / workload / container 進了 Polygraph 學習、baseline window 多長（預設 30 天）、新 workload 進來幾天才視為 baseline 成熟、未覆蓋的 workload 是否走 fallback rule</li>
<li><strong>Anomaly tuning ownership</strong>：誰看 Polygraph alert、false positive 由誰標記、標記後怎麼回饋 model、有沒有 <em>alert backlog grooming</em> lifecycle（不是黑箱 fire-and-forget）</li>
<li><strong>CSPM 跟合規 mapping</strong>：CIS / PCI / SOC 2 / HIPAA framework 哪些開、misconfiguration finding 走 ticket workflow（誰修、deadline）、Compliance report 多久 export 一次給 audit team</li>
<li><strong>跟 SIEM / SOAR handoff</strong>：Polygraph alert 是否同步進 <a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / <a href="/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &#43; CSPM &#43; CWS &#43; AAP &#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Security</a> 給 SOC、是否跟 <a href="/blog/backend/08-incident-response/" data-link-title="模組八：事故處理與復盤" data-link-desc="用 IR 領域詞彙建問題節點、以服務級案例庫累積事故脈絡，先建概念與案例庫再進實作交接">8 incident response</a> playbook 對接、high severity 是否觸發 SOAR</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">Detection Coverage and Signal Governance</a> 的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>Polygraph behavioral baseline</strong>：Lacework 的 first-class concept、從 cloud API call（CloudTrail / Audit Log）+ host process tree + container syscall + network connection 四種 source 同時學習、用 time-series graph 表達「正常情況下 user X 在 workload Y 上會 spawn process Z、連 destination W」。anomaly 是 graph 上不在 baseline 中的 edge、自動 trigger alert。baseline window 預設 30 天、新 workload 進來時用同類 workload 的 baseline 過渡、避免 cold start 全部 alert。</p>
<p><strong>CSPM（misconfiguration + compliance）</strong>：agentless 從 cloud API 拉 resource 設定、對照 CIS Benchmark / PCI / SOC 2 / HIPAA / CSA CCM 等 framework 跑 rule、出 finding。這部分是 <em>explicit rule</em>、不靠 Polygraph、跟 Wiz / Prisma 的 CSPM 能力同等級。Compliance report 可 schedule export 給 audit team。</p>
<p><strong>CWPP（host + container runtime）</strong>：兩種模式 — <em>agentless</em>（從 cloud API + snapshot 掃 vulnerability + misconfiguration、低 overhead 但無 runtime signal）、<em>agent-based</em>（Lacework agent on host / DaemonSet on K8s、提供 process tree + syscall + file integrity monitoring 給 Polygraph）。production runtime detection 必須 agent、不然 Polygraph 沒 process / syscall 資料源。</p>
<p><strong>Code Security（IaC + container image）</strong>：Terraform / CloudFormation / Helm chart 掃 misconfiguration、container image 掃 CVE + secret + SBOM、跟 <a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk</a> / <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> 同層級。整合 GitHub / GitLab PR check、release gate 前 block 高風險 IaC。</p>
<p><strong>Compliance reporting</strong>：CSPM finding 自動 map 到 framework（CIS AWS / PCI DSS / SOC 2 等）、定期 export PDF / CSV 給 audit team、不需 SOC 手工整理。跨 cloud 帳號 aggregate view 對 multi-account 治理有用。</p>
<p><strong>跟 SIEM 整合</strong>：Polygraph alert 走 webhook / S3 export / Splunk Add-on 進 <a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / <a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a> / <a href="/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &#43; CSPM &#43; CWS &#43; AAP &#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Security</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-security-operations/" data-link-title="Google Security Operations" data-link-desc="Google 雲原生 SIEM &#43; SOAR &#43; Mandiant threat intel 三合一（前 Chronicle）、UDM &#43; YARA-L、fixed-price by data tier、PB-scale 友善">Google Security Operations</a>、做 cross-source correlation。Lacework 不取代 SIEM、是 cloud-native detection 的 <em>upstream signal source</em>。</p>
<p><strong>計費模型</strong>：按 workload count（vCPU 數 / container 數 / cloud account 數）+ 啟用模組。enterprise contract 為主、不公開 list price。跟 Wiz / Prisma 同模型、預算敏感場景需試算。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Lacework</th>
          <th>Wiz</th>
          <th>Prisma Cloud</th>
          <th>CrowdStrike Falcon CS</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>偵測設計哲學</td>
          <td>Polygraph ML implicit baseline</td>
          <td>Security Graph + 顯式 Toxic Combination</td>
          <td>多模組 rule + ML 混合</td>
          <td>EDR 延伸到 cloud、process-centric</td>
      </tr>
      <tr>
          <td>主要訴求</td>
          <td>zero rule maintenance、自動覆蓋未知 attack</td>
          <td>顯式 rule 可審計、cross-asset 關聯路徑清楚</td>
          <td>寬覆蓋、agent + agentless 混合</td>
          <td>endpoint + cloud 同 console、process tree 一致</td>
      </tr>
      <tr>
          <td>Runtime 偵測</td>
          <td>agent (Polygraph syscall + process tree)</td>
          <td>agent (Runtime Sensor、後加)</td>
          <td>agent (Defender)</td>
          <td>強 — 沿用 Falcon EDR agent</td>
      </tr>
      <tr>
          <td>Agentless scan</td>
          <td>強 — CSPM + vulnerability snapshot</td>
          <td>強 — agentless 為 design 起點</td>
          <td>強 — 雙模式並重</td>
          <td>中 — 為 Falcon agent 補位</td>
      </tr>
      <tr>
          <td>合規可審計</td>
          <td>中 — Polygraph 黑箱、CSPM 部分清楚</td>
          <td>強 — 顯式 rule、規則邏輯可審查</td>
          <td>強 — rule-based、模組化清楚</td>
          <td>中</td>
      </tr>
      <tr>
          <td>跟 SIEM 整合</td>
          <td>webhook / Splunk Add-on / S3</td>
          <td>webhook / 多家 SIEM connector</td>
          <td>多家 SIEM connector</td>
          <td>Falcon 自家 NG-SIEM 為主、外接次要</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>cloud-native + 信任 ML、不想自寫 detection rule</td>
          <td>多雲 + 要顯式 rule 治理、需 cross-asset 攻擊路徑</td>
          <td>Palo Alto-heavy 環境、寬覆蓋優先</td>
          <td>CrowdStrike-heavy 環境、endpoint + cloud 統一</td>
      </tr>
      <tr>
          <td>不適合場景</td>
          <td>強合規要 explicit rule 可審計、SOC 要 rule 客製化</td>
          <td>不想自己寫 rule、想 ML 自動覆蓋</td>
          <td>預算敏感（多模組計費容易膨脹）</td>
          <td>沒在用 Falcon EDR、純 cloud-native</td>
      </tr>
      <tr>
          <td>Fortinet 整合</td>
          <td>強（2024+ FortiCNAPP、跟 NGFW / FortiSOAR 整合）</td>
          <td>無 Fortinet 直接整合</td>
          <td>無 Fortinet 直接整合</td>
          <td>無 Fortinet 直接整合</td>
      </tr>
  </tbody>
</table>
<p>選 Lacework 的核心訴求：<em>cloud-native + 信任 ML behavioral baseline + 不想養 detection engineering team 寫 rule</em> + 願意接受 Polygraph 是相對黑箱、false positive 要由 ML retraining 而非 rule edit 解決。強合規要 explicit rule 可審計、或 SOC 要深度 rule 客製化、走 Wiz / Prisma 更合適。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Polygraph internals</strong>：Polygraph 不是單一 ML model、是 time-series behavioral graph + 多個 detection algorithm 組合。node 是 entity（user / workload / process / network endpoint）、edge 是 observed interaction、edge 上掛 frequency + temporal pattern。anomaly detection 用 unsupervised learning（clustering + outlier detection）找 baseline 外的 edge。優點是 <em>zero-day attack pattern 不需事先定義也可能偵測到</em>（行為偏離即可）、缺點是 detection 為何 trigger / 為何沒 trigger 都不易解釋、tuning 不是改 rule、是調整 baseline window 或標記 false positive 回饋 model。</p>
<p><strong>Fortinet FortiCNAPP 整合（2024+）</strong>：Fortinet 收購後加速跟 <em>Fortinet NGFW</em>（network log 進 Polygraph 當 source）、<em>FortiSOAR</em>（Lacework alert 自動觸發 firewall block / endpoint isolation playbook）、<em>FortiSandbox</em>（suspicious file 進 sandbox 再回饋 baseline）整合。Fortinet-heavy 環境吃整合紅利、非 Fortinet 環境 Polygraph 跟原 connector 仍獨立運作。</p>
<p><strong>Anomaly tuning lifecycle</strong>：Polygraph alert 出來不是終點、要走 <em>triage → label false positive → ML model retraining</em> lifecycle。實務上 SOC 看 alert 標 <em>true positive / false positive / benign anomaly</em>（合法但意外）、Lacework 後台用 label 重訓 model、下一個 baseline cycle 調整。組織要決定 <em>誰負責 label</em>（SOC analyst / detection engineer）、<em>backlog grooming cadence</em>（每週 / 每月）、<em>retraining cycle</em>（自動 / 手動觸發）。沒 lifecycle 就是「alert 看一陣子放著」、Polygraph 退化成噪音源。</p>
<p><strong>跨 SIEM webhook / SOAR 整合</strong>：alert 推 <a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / <a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a> / <a href="/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &#43; CSPM &#43; CWS &#43; AAP &#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Security</a> 後、SOC 可用 SIEM correlation 補 cross-source（例如 Polygraph anomaly + Okta MFA fail + GitHub clone spike）、再進 SOAR playbook 自動 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a> rotate / <a href="/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &#43; DDoS &#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF</a> block。Lacework 是 <em>detective layer</em>、SIEM 是 <em>correlation + orchestration layer</em>。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>新 workload 進來大量 alert（cold start）</strong>：baseline 還沒建好、ML 把正常當異常 — 用同類 workload baseline 過渡、給 7-14 天 warm-up 再 enforce alert</li>
<li><strong>Polygraph alert 看不懂為何 trigger</strong>：ML 黑箱本質、不像 explicit rule 可指 line — 看 alert 帶的 <em>involved entities + observed deviation</em>、跨 entity 對 baseline 看差異、必要時補 Wiz / Prisma explicit rule 在強合規場景</li>
<li><strong>False positive 持續多但 model 沒進步</strong>：label lifecycle 沒跑、analyst 把 alert dismiss 沒打 label — 強制走 <em>true positive / false positive / benign anomaly</em> triage、不能直接 close</li>
<li><strong>Agent 沒裝 / 裝不到的 workload</strong>：legacy host / serverless / edge node 沒 agent、Polygraph 只有 cloud API source 沒 process / syscall — 接受 agentless-only 覆蓋面、不要假設 Polygraph 全 stack 看得到</li>
<li><strong>CSPM finding backlog 爆炸</strong>：framework 一次開全、misconfiguration 數千條沒人修 — 分批 enable framework、按 severity + asset criticality 排優先級、走 ticket workflow + deadline</li>
<li><strong>Compliance audit 要 explicit rule 可審查</strong>：Polygraph 內部邏輯不能交給 auditor — CSPM 部分可以審（是 explicit rule）、Polygraph 部分要補 detection engineering 文件 + label history 證明 ML 有治理</li>
<li><strong>Alert 進 SIEM 後沒 correlation</strong>：Lacework alert 跟 IdP / WAF / cloud control plane log 沒在 <a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> 跨 source 串 — 寫 correlation rule 把 Polygraph anomaly 當 <em>one signal</em>、不是當 final verdict</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>顯式 rule + 多雲 cross-asset 路徑</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/wiz/" data-link-title="Wiz" data-link-desc="Agentless CNAPP、Security Graph &#43; Toxic Combination 風險優先級、API-only scan 不需 workload agent">Wiz</a></td>
      </tr>
      <tr>
          <td>寬覆蓋 + Palo Alto-heavy</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/prisma-cloud/" data-link-title="Prisma Cloud" data-link-desc="Palo Alto CNAPP、agent (Defender) &#43; agentless 雙軌、五模組（Compute / CSPM / Code / Data / CIEM）、Compliance template 強">Prisma Cloud</a></td>
      </tr>
      <tr>
          <td>Endpoint EDR + cloud 統一</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/crowdstrike-falcon-cs/" data-link-title="CrowdStrike Falcon Cloud Security" data-link-desc="CrowdStrike 在 Falcon endpoint EDR 之上的 CNAPP、agent 統一跨 endpoint &#43; workload &#43; container、CrowdStrike Intelligence 內建">CrowdStrike Falcon Cloud Security</a></td>
      </tr>
      <tr>
          <td>SIEM 主導、CNAPP signal 進 SOC</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-security-operations/" data-link-title="Google Security Operations" data-link-desc="Google 雲原生 SIEM &#43; SOAR &#43; Mandiant threat intel 三合一（前 Chronicle）、UDM &#43; YARA-L、fixed-price by data tier、PB-scale 友善">Google Security Operations</a></td>
      </tr>
      <tr>
          <td>Container image / IaC scan 為主</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk</a> / <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a></td>
      </tr>
      <tr>
          <td>資料分類 / DLP</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/google-dlp/" data-link-title="Google DLP" data-link-desc="GCP 原生 Sensitive Data Protection：infoType discovery &#43; transformation (mask / FPE / tokenize / k-anonymity)、整合 BigQuery / GCS / Cloud SQL">Google DLP</a> / <a href="/blog/backend/07-security-data-protection/vendors/microsoft-purview/" data-link-title="Microsoft Purview" data-link-desc="Microsoft 跨 M365 / Azure / endpoint 的 data governance &#43; information protection &#43; DLP &#43; insider risk 統合平台、label-driven">Microsoft Purview</a></td>
      </tr>
      <tr>
          <td>Incident routing</td>
          <td><a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Polygraph ML 演算法的學術細節（unsupervised clustering / graph anomaly detection 具體方法）</li>
<li>FortiCNAPP 跟 Fortinet 其他產品（FortiGate / FortiAnalyzer / FortiSIEM）的 deep integration 設定</li>
<li>Lacework Labs threat research 報告的逐篇解讀</li>
<li>完整 CIS / PCI / SOC 2 framework 對應的 rule 清單</li>
<li>Container runtime 防護的 OS-level 細節（cgroup / namespace / seccomp）</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>Lacework 在 07 案例庫沒有直接 vendor-level 事件、但多個 case 是 Polygraph behavioral baseline 的對照啟示：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 Lacework 的關係（對照啟示）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/solarwinds-2020-sunburst/" data-link-title="7.R7.2.1 SolarWinds 2020：更新鏈被濫用" data-link-desc="合法更新流程遭植入後，攻擊者如何長期潛伏與橫向擴散">SolarWinds 2020 Sunburst</a></td>
          <td>Polygraph 在 SolarWinds 期間可從 Orion 程序的 DNS callback 行為偏離 baseline 偵測、不靠 IoC list — Lacework marketing 強打的 zero-day 案例</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/3cx-2023-desktopapp-supply-chain/" data-link-title="7.R7.2.8 3CX 2023：桌面軟體更新鏈攻擊" data-link-desc="合法更新流程被植入後，桌面端供應鏈事件如何傳到企業端點">3CX 2023 Desktop App Supply Chain</a></td>
          <td>Desktop app process spawn 異常 + unusual outbound 是 Polygraph baseline 可抓的 pattern、補簽章驗證通過後的 runtime 偵測窗口</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/log4shell-cve-2021-44228-component-chain/" data-link-title="7.R7.2.7 Log4Shell 2021：共用元件風險與修補鏈" data-link-desc="共用元件漏洞如何同步影響多服務，並迫使團隊建立依賴治理 workflow">Log4Shell CVE-2021-44228</a></td>
          <td>Polygraph 偵測 JNDI lookup 後的 outbound LDAP 連線異常、補 CVE scanner agent rollout 之前的偵測窗口、不依賴事先 CVE 公開</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/data-exfiltration/snowflake-2024-credential-abuse/" data-link-title="7.R7.4.2 Snowflake 2024：憑證濫用與資料竊取" data-link-desc="外洩憑證與 MFA 缺口如何在資料平台形成高風險外送事件">Snowflake 2024 Credential Abuse</a></td>
          <td>對照啟示：Polygraph 對 cloud API call pattern 異常（短時間大量 GetObject / 跨 schema query）可 baseline-based 偵測、不需事先寫 query rule</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/blue-team/detection-engineering-lifecycle/" data-link-title="7.B5 Detection Engineering Lifecycle" data-link-desc="把偵測規則視為可維護資產，建立從來源、測試、調校到退場的完整生命週期">Detection Engineering Lifecycle (section)</a></td>
          <td>Polygraph 把 detection lifecycle 從「寫 rule → tune → review」改成「baseline → label false positive → retrain」、流程不同但治理責任沒消失</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/blue-team/alert-fatigue-and-signal-quality/" data-link-title="7.B10 Alert Fatigue and Signal Quality" data-link-desc="建立告警疲勞治理方法，讓訊號品質、分級一致性與處置效率同步提升">Alert Fatigue and Signal Quality (section)</a></td>
          <td>Polygraph 自動 baseline 不等於免 alert fatigue — label lifecycle 跟 retraining cadence 沒做、false positive 一樣會淹 SOC</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">7.13 偵測覆蓋率與訊號治理</a>、<a href="/blog/backend/07-security-data-protection/blue-team/detection-engineering-lifecycle/" data-link-title="7.B5 Detection Engineering Lifecycle" data-link-desc="把偵測規則視為可維護資產，建立從來源、測試、調校到退場的完整生命週期">Detection Engineering Lifecycle</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/wiz/" data-link-title="Wiz" data-link-desc="Agentless CNAPP、Security Graph &#43; Toxic Combination 風險優先級、API-only scan 不需 workload agent">Wiz</a>、<a href="/blog/backend/07-security-data-protection/vendors/prisma-cloud/" data-link-title="Prisma Cloud" data-link-desc="Palo Alto CNAPP、agent (Defender) &#43; agentless 雙軌、五模組（Compute / CSPM / Code / Data / CIEM）、Compliance template 強">Prisma Cloud</a>、<a href="/blog/backend/07-security-data-protection/vendors/crowdstrike-falcon-cs/" data-link-title="CrowdStrike Falcon Cloud Security" data-link-desc="CrowdStrike 在 Falcon endpoint EDR 之上的 CNAPP、agent 統一跨 endpoint &#43; workload &#43; container、CrowdStrike Intelligence 內建">CrowdStrike Falcon Cloud Security</a></li>
<li>下游：<a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / <a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a> / <a href="/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &#43; CSPM &#43; CWS &#43; AAP &#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Security</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-security-operations/" data-link-title="Google Security Operations" data-link-desc="Google 雲原生 SIEM &#43; SOAR &#43; Mandiant threat intel 三合一（前 Chronicle）、UDM &#43; YARA-L、fixed-price by data tier、PB-scale 友善">Google Security Operations</a>（SIEM 接 Polygraph alert）</li>
<li>跨類：<a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk</a> / <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a>（Code Security 重疊、CI 階段優先級）、<a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a>（SOAR playbook 拉 API rotate）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（Polygraph alert → IR routing）、<a href="/blog/backend/04-observability/" data-link-title="模組四：可觀測性平台" data-link-desc="整理 log、metric、trace、dashboard 與 alert 的後端操作實務">4 observability</a>（log pipeline 共用）</li>
<li>官方：<a href="https://docs.lacework.net/">Lacework Documentation</a> / <a href="https://www.fortinet.com/products/forticnapp">Fortinet Lacework FortiCNAPP</a></li>
</ul>
]]></content:encoded></item><item><title>CrowdStrike Falcon Cloud Security</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/crowdstrike-falcon-cs/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/crowdstrike-falcon-cs/</guid><description>&lt;p>CrowdStrike Falcon Cloud Security 是 CrowdStrike 在 Falcon endpoint EDR 平台之上擴張出來的 CNAPP（Cloud-Native Application Protection Platform）產品線。它的核心邏輯是把已經跑在 endpoint 上的 &lt;em>Falcon agent&lt;/em> 同時拿來收 cloud workload / container / Kubernetes node 的 telemetry、再把 CrowdStrike Intelligence 的 threat actor profile 直接餵進 detection rule。對已是 CrowdStrike endpoint 客戶來說、邊際 onboarding cost 接近 0；對非 CrowdStrike 環境、選它的訴求應該是 &lt;em>threat intel + EDR 同 console&lt;/em> 而不是 CSPM 本身。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Falcon Cloud Security 的定位是 &lt;em>agent-first 的 CNAPP&lt;/em>、設計重心在「endpoint EDR agent 順便收 cloud workload 訊號」這條路徑、agentless CSPM 是補位、不是主軸。產品線靠多次收購整合：&lt;em>Bionic&lt;/em>（2023 收購、現為 Falcon ASPM、application security posture management）負責 application architecture + runtime risk map；&lt;em>Flow Security&lt;/em>（2024 收購、現為 Falcon Data Protection / DSPM）負責 sensitive data 發現與 access path；endpoint / workload / container runtime 偵測由 Falcon agent 自家補。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/wiz/" data-link-title="Wiz" data-link-desc="Agentless CNAPP、Security Graph &amp;#43; Toxic Combination 風險優先級、API-only scan 不需 workload agent">Wiz&lt;/a> 比、Falcon CS 走 &lt;em>agent-first + EDR 整合&lt;/em>、Wiz 走 &lt;em>agentless-first + cloud workload graph&lt;/em>。已部署 Falcon endpoint 的客戶上 Falcon CS 邊際成本 0；純 cloud-native 沒 endpoint workload 的環境、Falcon 的 agent 紅利不存在、Wiz 更快出價值。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/prisma-cloud/" data-link-title="Prisma Cloud" data-link-desc="Palo Alto CNAPP、agent (Defender) &amp;#43; agentless 雙軌、五模組（Compute / CSPM / Code / Data / CIEM）、Compliance template 強">Prisma Cloud&lt;/a> 比、兩者都走 agent + agentless 雙軌、Prisma 強項是 &lt;em>compliance pack 跟 IaC scanning 模板&lt;/em>、Falcon 強項是 &lt;em>CrowdStrike Intelligence threat actor profile + Counter Adversary Operations 提供的 hunting 服務&lt;/em>。跟 Lacework 比、Lacework 走 &lt;em>behavioral baseline / anomaly detection&lt;/em>、Falcon 走 &lt;em>signature + threat intel&lt;/em>、兩種偵測哲學。&lt;/p></description><content:encoded><![CDATA[<p>CrowdStrike Falcon Cloud Security 是 CrowdStrike 在 Falcon endpoint EDR 平台之上擴張出來的 CNAPP（Cloud-Native Application Protection Platform）產品線。它的核心邏輯是把已經跑在 endpoint 上的 <em>Falcon agent</em> 同時拿來收 cloud workload / container / Kubernetes node 的 telemetry、再把 CrowdStrike Intelligence 的 threat actor profile 直接餵進 detection rule。對已是 CrowdStrike endpoint 客戶來說、邊際 onboarding cost 接近 0；對非 CrowdStrike 環境、選它的訴求應該是 <em>threat intel + EDR 同 console</em> 而不是 CSPM 本身。</p>
<h2 id="服務定位">服務定位</h2>
<p>Falcon Cloud Security 的定位是 <em>agent-first 的 CNAPP</em>、設計重心在「endpoint EDR agent 順便收 cloud workload 訊號」這條路徑、agentless CSPM 是補位、不是主軸。產品線靠多次收購整合：<em>Bionic</em>（2023 收購、現為 Falcon ASPM、application security posture management）負責 application architecture + runtime risk map；<em>Flow Security</em>（2024 收購、現為 Falcon Data Protection / DSPM）負責 sensitive data 發現與 access path；endpoint / workload / container runtime 偵測由 Falcon agent 自家補。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/wiz/" data-link-title="Wiz" data-link-desc="Agentless CNAPP、Security Graph &#43; Toxic Combination 風險優先級、API-only scan 不需 workload agent">Wiz</a> 比、Falcon CS 走 <em>agent-first + EDR 整合</em>、Wiz 走 <em>agentless-first + cloud workload graph</em>。已部署 Falcon endpoint 的客戶上 Falcon CS 邊際成本 0；純 cloud-native 沒 endpoint workload 的環境、Falcon 的 agent 紅利不存在、Wiz 更快出價值。跟 <a href="/blog/backend/07-security-data-protection/vendors/prisma-cloud/" data-link-title="Prisma Cloud" data-link-desc="Palo Alto CNAPP、agent (Defender) &#43; agentless 雙軌、五模組（Compute / CSPM / Code / Data / CIEM）、Compliance template 強">Prisma Cloud</a> 比、兩者都走 agent + agentless 雙軌、Prisma 強項是 <em>compliance pack 跟 IaC scanning 模板</em>、Falcon 強項是 <em>CrowdStrike Intelligence threat actor profile + Counter Adversary Operations 提供的 hunting 服務</em>。跟 Lacework 比、Lacework 走 <em>behavioral baseline / anomaly detection</em>、Falcon 走 <em>signature + threat intel</em>、兩種偵測哲學。</p>
<p>關鍵張力：<em>agent 是 single point of compromise</em> 是 Falcon agent-first 路線的長期信任成本。2024-07 Falcon sensor 推 bad content update 導致全球 Windows host BSOD 的事件、把 <em>kernel-level agent 一改全炸</em> 的風險具象化、對 agent-first vendor 是長期教訓。選 Falcon CS 等於買 agent 在 host kernel 的存取權、要把 <em>agent 自身的供應鏈</em> 當成風險來源納入評估。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>Falcon Cloud Security 在 cloud security stack 中承擔哪一段（CSPM / CWPP / CIEM / ASPM / DSPM）、哪些靠 Falcon agent、哪些靠 agentless connector</li>
<li>已有 CrowdStrike endpoint 跟沒有 CrowdStrike endpoint 兩種起點下、Falcon CS 的判讀是否一樣</li>
<li>CrowdStrike Intelligence 跟 Counter Adversary Operations 在 detection lifecycle 的位置</li>
<li>何時用 Falcon CS、何時走 <a href="/blog/backend/07-security-data-protection/vendors/wiz/" data-link-title="Wiz" data-link-desc="Agentless CNAPP、Security Graph &#43; Toxic Combination 風險優先級、API-only scan 不需 workload agent">Wiz</a> / <a href="/blog/backend/07-security-data-protection/vendors/prisma-cloud/" data-link-title="Prisma Cloud" data-link-desc="Palo Alto CNAPP、agent (Defender) &#43; agentless 雙軌、五模組（Compute / CSPM / Code / Data / CIEM）、Compliance template 強">Prisma Cloud</a> / Lacework 的取捨</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Falcon Cloud Security deployment 是否健康、最少看四件事：</p>
<ul>
<li><strong>Agent coverage 跟版本治理</strong>：哪些 host / workload / container 跑 Falcon agent、是否跨 endpoint + cloud workload + Kubernetes node 一致、agent version 跟 sensor content channel 是否走 staging tenant + canary rollout（2024-07 incident 後的硬性要求）</li>
<li><strong>Agentless connector 覆蓋</strong>：CSPM 連到哪些 cloud account（AWS / GCP / Azure / OCI）、CIEM 是否拉 IAM identity graph、ASPM 連到哪些 application code repo</li>
<li><strong>Threat intel 是否接進 detection lifecycle</strong>：CrowdStrike Intelligence 的 IoC / threat actor TTP 是否餵進 Falcon detection rule、Counter Adversary Operations（MDR / threat hunting 服務）是否訂閱</li>
<li><strong>跟 Falcon EDR 同 console / IR handoff</strong>：cloud finding 跟 endpoint finding 是否在同一個 Incident view、SOC team 跟 cloud team 的 routing 是否定義、跟 <a href="/blog/backend/08-incident-response/" data-link-title="模組八：事故處理與復盤" data-link-desc="用 IR 領域詞彙建問題節點、以服務級案例庫累積事故脈絡，先建概念與案例庫再進實作交接">8 incident response</a> 是否對齊</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">Detection Coverage and Signal Governance</a> 邊界的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>Falcon agent 統一</strong>：endpoint EDR 用的 Falcon sensor 同時收 cloud workload 上的 process / file / network telemetry、不需要再裝第二支 agent。對已用 Falcon endpoint 的組織意義最大 — VM / container host 上裝 Falcon 就同時是 EDR + CWPP + container runtime detection。新環境要評估 <em>agent 的 kernel 存取權</em> 是否可接受、container 內是否能或需要部署 agent（Falcon Container Sensor 走 sidecar / DaemonSet）。</p>
<p><strong>CSPM</strong>：agentless 連 cloud account（AWS / GCP / Azure / OCI）、掃 misconfiguration（public S3 / over-privileged role / unencrypted disk）、對照 CIS Benchmark / NIST / PCI 模板。CSPM 是 <em>配置面</em> 訊號、補 agent 看不到的 cloud control plane 行為（例如 IAM policy change、S3 bucket policy 改變）。</p>
<p><strong>CWPP — workload + container + Kubernetes</strong>：Falcon agent 在 VM host / container host / Kubernetes node 上做 runtime detection、看 process spawn、file integrity、network connection、container escape attempt。比 agentless snapshot scan 強的是 <em>runtime behavior</em>（看到實際發生的 process tree），比 Wiz agentless 弱的是 <em>初始 coverage 速度</em>（要先部署 agent）。</p>
<p><strong>CIEM</strong>：把 cloud IAM identity 跟 access 畫成 graph、識別 over-privileged role / unused permission / cross-account trust risk。跟 <a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM</a> Access Analyzer / <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google Cloud IAM</a> Policy Intelligence 是補位、不是替代 — CIEM 給的是 <em>跨雲 + 跨 identity provider</em> 的 risk view。</p>
<p><strong>ASPM（前 Bionic）</strong>：application security posture management、把 application architecture（service graph / data flow / external dependency / vulnerability）畫成 map、識別哪個 vulnerability 真的可達 production attack surface。跟 Wiz Code / Snyk 的訴求重疊、但 Bionic 強項是 <em>runtime + architecture</em> 而不是 pure SAST/SCA。導入需要拉 application telemetry、不是裝完就有結果。</p>
<p><strong>DSPM（前 Flow Security）</strong>：data security posture management、掃 cloud storage / database / SaaS 裡的 sensitive data 位置、誰能存取、access path 是什麼。跟 <a href="/blog/backend/07-security-data-protection/vendors/google-dlp/" data-link-title="Google DLP" data-link-desc="GCP 原生 Sensitive Data Protection：infoType discovery &#43; transformation (mask / FPE / tokenize / k-anonymity)、整合 BigQuery / GCS / Cloud SQL">Google DLP</a> / <a href="/blog/backend/07-security-data-protection/vendors/microsoft-purview/" data-link-title="Microsoft Purview" data-link-desc="Microsoft 跨 M365 / Azure / endpoint 的 data governance &#43; information protection &#43; DLP &#43; insider risk 統合平台、label-driven">Microsoft Purview</a> 不同層 — DSPM 是 <em>posture 層</em>（who can access what）、DLP 是 <em>runtime 層</em>（actual data egress event）、兩者互補。</p>
<p><strong>CrowdStrike Intelligence 整合</strong>：CrowdStrike Intelligence 是 CrowdStrike 自家的 threat intel team、定期發 threat actor profile（COZY BEAR / FANCY BEAR / Scattered Spider 等命名來自 CrowdStrike）、IoC、TTP。Falcon CS detection rule 直接吃這層、不用 SOC team 自己訂閱外部 threat feed。這是 Falcon CS 跟 <em>純 CNAPP 競品</em>（Wiz / Prisma）最大差異 — 競品要再買 Mandiant / Recorded Future 才能補。</p>
<p><strong>Charlotte AI</strong>：CrowdStrike 的 LLM-assisted investigation 介面、SOC analyst 用自然語言問 incident（「過去 24hr 有哪些 process 是 first-seen across fleet」）、Charlotte 翻成 Falcon query 跑。屬 SOC productivity 補位、不是 detection logic 本身。</p>
<p><strong>跟 Falcon LogScale / Identity Protection 同 plane</strong>：完整 CrowdStrike stack 客戶可以把 Falcon LogScale（前 Humio 收購、SIEM）+ Falcon Identity Protection（identity threat detection）跟 Falcon CS 整合在同一個 console。Single pane of glass 強、但 vendor lock-in 也最深、退場成本是業界最高。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>CrowdStrike Falcon CS</th>
          <th>Wiz</th>
          <th>Prisma Cloud</th>
          <th>Lacework</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Agent 策略</td>
          <td>Agent-first（Falcon sensor）+ agentless 補位</td>
          <td>Agentless-first（snapshot scan）+ runtime sensor</td>
          <td>Agent + agentless 雙軌（Defender agent）</td>
          <td>Agent-based（Lacework agent + Polygraph）</td>
      </tr>
      <tr>
          <td>強項</td>
          <td>EDR 整合、threat intel、Counter Adversary Ops</td>
          <td>Cloud workload graph、快速 onboarding、無 agent</td>
          <td>Compliance pack、IaC scanning、廣覆蓋</td>
          <td>Behavioral baseline、anomaly detection</td>
      </tr>
      <tr>
          <td>Threat intel</td>
          <td>CrowdStrike Intelligence 內建</td>
          <td>外部 feed integration</td>
          <td>Unit 42 threat intel 內建</td>
          <td>外部 feed integration</td>
      </tr>
      <tr>
          <td>ASPM / app layer</td>
          <td>Falcon ASPM（前 Bionic、runtime + architecture）</td>
          <td>Wiz Code（SAST / SCA / IaC）</td>
          <td>Prisma Code Security（前 Bridgecrew）</td>
          <td>有限</td>
      </tr>
      <tr>
          <td>DSPM</td>
          <td>Falcon Data Protection（前 Flow Security）</td>
          <td>Wiz DSPM</td>
          <td>Data Security Posture Management</td>
          <td>有限</td>
      </tr>
      <tr>
          <td>MDR / hunting</td>
          <td>Counter Adversary Operations（業界先驅）</td>
          <td>無 first-party MDR</td>
          <td>Cortex MDR（Palo Alto）</td>
          <td>有限</td>
      </tr>
      <tr>
          <td>跟 EDR 同 console</td>
          <td>內建（Falcon EDR / Identity Protection / LogScale）</td>
          <td>需外接</td>
          <td>Cortex XDR（同 Palo Alto stack）</td>
          <td>需外接</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>已用 Falcon endpoint、看重 threat intel + MDR</td>
          <td>Cloud-native、無 endpoint workload、要快</td>
          <td>Palo Alto stack 客戶、compliance-heavy 產業</td>
          <td>中等規模、behavioral detection 為主</td>
      </tr>
      <tr>
          <td>退場成本</td>
          <td>最高（agent + console + threat intel + MDR 綁定）</td>
          <td>中（agentless 退出較快）</td>
          <td>高（Palo Alto stack 整合深）</td>
          <td>中</td>
      </tr>
  </tbody>
</table>
<p>選 Falcon CS 的核心訴求：<em>已是 CrowdStrike endpoint 客戶 / SOC team 已熟 Falcon console + 看重 CrowdStrike Intelligence threat intel + 願意接受 agent-first 的供應鏈風險</em>。純 cloud-only 沒 endpoint workload、agent 紅利不存在、走 <a href="/blog/backend/07-security-data-protection/vendors/wiz/" data-link-title="Wiz" data-link-desc="Agentless CNAPP、Security Graph &#43; Toxic Combination 風險優先級、API-only scan 不需 workload agent">Wiz</a> 更划算。非 CrowdStrike 環境想要 compliance + IaC、走 <a href="/blog/backend/07-security-data-protection/vendors/prisma-cloud/" data-link-title="Prisma Cloud" data-link-desc="Palo Alto CNAPP、agent (Defender) &#43; agentless 雙軌、五模組（Compute / CSPM / Code / Data / CIEM）、Compliance template 強">Prisma Cloud</a>。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Counter Adversary Operations（MDR + threat hunting）</strong>：CrowdStrike 的 managed detection and response 服務、24x7 SOC team + threat hunter 主動掃客戶環境裡的 adversary 跡象。跟一般 MDR 不同的是、它直接接 CrowdStrike Intelligence 的 threat actor profile、看到 TTP 匹配就主動 hunt 而不是等 alert。對 SOC team 規模有限但要面對 nation-state actor 的組織、是補 SOC capability 的快路。</p>
<p><strong>CrowdStrike Intelligence threat actor profile</strong>：CrowdStrike 把 threat actor 用命名規則（BEAR = Russian state、PANDA = Chinese state、KITTEN = Iranian state、SPIDER = eCrime）+ 編號管理、每個 actor 有 TTP、tooling、target sector 的 profile。Detection rule 不再只看 IoC（hash / IP）而是看 <em>actor 的 behavioral pattern</em>、IoC 變了也能抓。配對 <a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/microsoft-storm-0558-2023-signing-key-chain/" data-link-title="7.R7.1.5 Microsoft Storm-0558 2023：簽章金鑰鏈與郵件存取" data-link-desc="從簽章金鑰保護失效到雲端郵件存取，拆解身分信任鏈的關鍵控制點">Microsoft Storm-0558 Signing Key Chain</a> 的 nation-state actor lesson。</p>
<p><strong>Falcon LogScale 整合</strong>：Falcon LogScale（前 Humio）是 CrowdStrike 自家的 SIEM、可以把 Falcon agent telemetry + cloud log + 自家 app log 全收。跟 <a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> 比、LogScale 強在 <em>跟 Falcon detection 同 plane</em>、計費也不是 ingestion-based；弱在 <em>detection content 跟 ecosystem 比 Splunk 淺</em>。</p>
<p><strong>Charlotte AI + LLM-assisted investigation</strong>：SOC analyst triage 時間長是普遍痛點、Charlotte AI 用 LLM 把自然語言問題翻成 Falcon query、補出 incident timeline summary。屬 SOC productivity 工具、不取代 detection rule、也不取代 analyst judgement。</p>
<p><strong>Falcon Identity Protection 補位</strong>：identity-layer threat detection（pass-the-hash、Kerberoasting、AD enumeration）、跟 <a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a> ITDR 訊號互補。完整 stack 客戶可把 endpoint + cloud + identity 三層 telemetry 一起 correlate。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Agent rollout 一改全炸</strong>：sensor content channel 沒有 staging tenant、prod 直接吃 vendor push 的 update — 2024-07 incident 後 CrowdStrike 推 Sensor Update Policy 允許客戶設 canary ring、所有 prod 都該開、不開等於把 fleet 命交給 vendor QA</li>
<li><strong>Cloud workload coverage 不全 / 偵測盲點</strong>：只有部分 VM 部署 Falcon agent、container / Kubernetes 沒覆蓋 — 補 Falcon Container Sensor（DaemonSet）+ CSPM agentless 連 cloud account 補配置面</li>
<li><strong>Threat intel 沒接進 detection lifecycle</strong>：訂了 CrowdStrike Intelligence 但 SOC team 沒把 actor TTP 對應到自家 detection rule — 走 <a href="/blog/backend/07-security-data-protection/blue-team/detection-engineering-lifecycle/" data-link-title="7.B5 Detection Engineering Lifecycle" data-link-desc="把偵測規則視為可維護資產，建立從來源、測試、調校到退場的完整生命週期">Detection Engineering Lifecycle</a>、定期 review intel report + rule coverage gap</li>
<li><strong>CIEM finding 太多 / SOC 看不完</strong>：cloud IAM 累積 over-permission 沒清、CIEM 一掃幾千條 finding — 走 risk prioritization（哪些 identity 真的可達 sensitive resource）+ 跟 <a href="/blog/backend/07-security-data-protection/identity-access-boundary/" data-link-title="7.2 身分與授權邊界" data-link-desc="以問題驅動方式整理身分、授權、會話與供應商身分鏈">Cloud IAM</a> ownership 對齊、不是 dump 給 SOC</li>
<li><strong>ASPM 拉不出 application graph</strong>：Bionic 需要 application telemetry + repo integration、只裝 Falcon agent 不會有 application architecture map — 補 ASPM 的 application onboarding（repo / CI / runtime telemetry）</li>
<li><strong>DSPM 找到 sensitive data 但沒 follow-up</strong>：DSPM 是 <em>posture 層</em>、發現問題後要走 <a href="/blog/backend/07-security-data-protection/data-protection-and-masking-governance/" data-link-title="7.4 資料保護與遮罩治理" data-link-desc="以問題驅動方式整理資料分級、遮罩、匯出與備份治理">Data Classification</a> lifecycle、不是只把 finding 丟到 dashboard</li>
<li><strong>Vendor lock-in 過深、退場時 SOC 工作流崩潰</strong>：所有 detection content / IR playbook / Charlotte query / LogScale dashboard 都綁 Falcon — 關鍵 detection rule 同步 export 成 Sigma format（中性 format）、IR playbook 寫成 vendor-neutral 文件、不全押在 Falcon console</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Cloud-native / 無 endpoint workload</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/wiz/" data-link-title="Wiz" data-link-desc="Agentless CNAPP、Security Graph &#43; Toxic Combination 風險優先級、API-only scan 不需 workload agent">Wiz</a></td>
      </tr>
      <tr>
          <td>Palo Alto stack + compliance-heavy</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/prisma-cloud/" data-link-title="Prisma Cloud" data-link-desc="Palo Alto CNAPP、agent (Defender) &#43; agentless 雙軌、五模組（Compute / CSPM / Code / Data / CIEM）、Compliance template 強">Prisma Cloud</a></td>
      </tr>
      <tr>
          <td>Behavioral baseline / anomaly 為主</td>
          <td>Lacework</td>
      </tr>
      <tr>
          <td>Runtime container syscall 深度偵測</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/" data-link-title="資安與資料保護 Vendor 清單" data-link-desc="規劃身份、秘密、金鑰、入口防護、供應鏈與偵測工具的服務頁撰寫順序與教學大綱">Falco</a> / Cilium Tetragon</td>
      </tr>
      <tr>
          <td>DLP / sensitive data egress event</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/google-dlp/" data-link-title="Google DLP" data-link-desc="GCP 原生 Sensitive Data Protection：infoType discovery &#43; transformation (mask / FPE / tokenize / k-anonymity)、整合 BigQuery / GCS / Cloud SQL">Google DLP</a> / <a href="/blog/backend/07-security-data-protection/vendors/microsoft-purview/" data-link-title="Microsoft Purview" data-link-desc="Microsoft 跨 M365 / Azure / endpoint 的 data governance &#43; information protection &#43; DLP &#43; insider risk 統合平台、label-driven">Microsoft Purview</a></td>
      </tr>
      <tr>
          <td>純 SIEM / log aggregation</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / <a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-security-operations/" data-link-title="Google Security Operations" data-link-desc="Google 雲原生 SIEM &#43; SOAR &#43; Mandiant threat intel 三合一（前 Chronicle）、UDM &#43; YARA-L、fixed-price by data tier、PB-scale 友善">Google Security Operations</a></td>
      </tr>
      <tr>
          <td>Incident response routing</td>
          <td><a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Falcon agent 內部 architecture（kernel module / sensor content channel 細節）</li>
<li>CrowdStrike Intelligence 完整 threat actor 名單與 TTP reference</li>
<li>Falcon LogScale 完整 SIEM 操作（屬獨立 SIEM 章節範圍、跟 Splunk 對照）</li>
<li>2024-07 Falcon update incident 的完整 root cause（屬 <a href="/blog/backend/08-incident-response/" data-link-title="模組八：事故處理與復盤" data-link-desc="用 IR 領域詞彙建問題節點、以服務級案例庫累積事故脈絡，先建概念與案例庫再進實作交接">8 incident response</a> 範圍）</li>
<li>Falcon Identity Protection 的 AD-specific detection rule（屬 identity-access 範圍）</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 Falcon Cloud Security 的關係（對照啟示）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/solarwinds-2020-sunburst/" data-link-title="7.R7.2.1 SolarWinds 2020：更新鏈被濫用" data-link-desc="合法更新流程遭植入後，攻擊者如何長期潛伏與橫向擴散">SolarWinds 2020 Sunburst</a></td>
          <td>CrowdStrike 是 SolarWinds incident response 主導 vendor、Falcon endpoint + CrowdStrike Intelligence 整合在事件期間是強項、agent + threat intel 同 plane 的價值具象案例</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/3cx-2023-desktopapp-supply-chain/" data-link-title="7.R7.2.8 3CX 2023：桌面軟體更新鏈攻擊" data-link-desc="合法更新流程被植入後，桌面端供應鏈事件如何傳到企業端點">3CX 2023 Desktop App Supply Chain</a></td>
          <td>CrowdStrike 公開 attribution（指向 LABYRINTH CHOLLIMA）與 detection、Falcon agent runtime 偵測異常 process spawn、signed binary 也要看 behavior</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/log4shell-cve-2021-44228-component-chain/" data-link-title="7.R7.2.7 Log4Shell 2021：共用元件風險與修補鏈" data-link-desc="共用元件漏洞如何同步影響多服務，並迫使團隊建立依賴治理 workflow">Log4Shell CVE-2021-44228</a></td>
          <td>Falcon agent runtime 偵測 JNDI lookup process tree、CrowdStrike Intelligence push IoC + TTP、漏洞披露 → fleet-wide detection deployment 是時間競賽</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/microsoft-storm-0558-2023-signing-key-chain/" data-link-title="7.R7.1.5 Microsoft Storm-0558 2023：簽章金鑰鏈與郵件存取" data-link-desc="從簽章金鑰保護失效到雲端郵件存取，拆解身分信任鏈的關鍵控制點">Microsoft Storm-0558 Signing Key Chain</a></td>
          <td>對照啟示：endpoint agent vendor 自己也是 supply chain target、2024-07 Falcon bad sensor update 全球 Windows BSOD 是這個 risk 的具體表現、agent-first 路線的長期信任成本</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/entrypoint-and-server-protection/" data-link-title="7.3 入口治理與伺服器防護" data-link-desc="以問題驅動方式整理對外入口、管理平面與伺服器邊界">7.12 雲端控制面安全與 CNAPP</a>、<a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">Detection Coverage and Signal Governance</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/wiz/" data-link-title="Wiz" data-link-desc="Agentless CNAPP、Security Graph &#43; Toxic Combination 風險優先級、API-only scan 不需 workload agent">Wiz</a>、<a href="/blog/backend/07-security-data-protection/vendors/prisma-cloud/" data-link-title="Prisma Cloud" data-link-desc="Palo Alto CNAPP、agent (Defender) &#43; agentless 雙軌、五模組（Compute / CSPM / Code / Data / CIEM）、Compliance template 強">Prisma Cloud</a>、Lacework</li>
<li>下游：<a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-security-operations/" data-link-title="Google Security Operations" data-link-desc="Google 雲原生 SIEM &#43; SOAR &#43; Mandiant threat intel 三合一（前 Chronicle）、UDM &#43; YARA-L、fixed-price by data tier、PB-scale 友善">Google Security Operations</a>（SIEM 對照）、<a href="/blog/backend/07-security-data-protection/vendors/google-dlp/" data-link-title="Google DLP" data-link-desc="GCP 原生 Sensitive Data Protection：infoType discovery &#43; transformation (mask / FPE / tokenize / k-anonymity)、整合 BigQuery / GCS / Cloud SQL">Google DLP</a> / <a href="/blog/backend/07-security-data-protection/vendors/microsoft-purview/" data-link-title="Microsoft Purview" data-link-desc="Microsoft 跨 M365 / Azure / endpoint 的 data governance &#43; information protection &#43; DLP &#43; insider risk 統合平台、label-driven">Microsoft Purview</a>（DLP 補位）</li>
<li>跨類：<a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google Cloud IAM</a>（CIEM 訊號來源）、<a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a>（identity threat 對照）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（cloud finding → IR routing）、<a href="/blog/backend/06-reliability/" data-link-title="模組六：可靠性驗證流程" data-link-desc="用 SRE 領域詞彙建問題節點、以服務級案例庫累積驗證脈絡，先建概念與案例庫再進實作交接">6.4 release gate</a>（ASPM finding → release gate）</li>
<li>官方：<a href="https://www.crowdstrike.com/platform/cloud-security/">CrowdStrike Falcon Cloud Security</a></li>
</ul>
]]></content:encoded></item><item><title>Open Policy Agent (OPA)</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/opa/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/opa/</guid><description>&lt;p>Open Policy Agent (OPA) 是 CNCF graduated 的 &lt;em>general-purpose policy engine&lt;/em>、設計目的是把「誰能做什麼、什麼 config 才合法」從 application code 抽到外部 policy decision layer。它跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/kyverno/" data-link-title="Kyverno" data-link-desc="K8s-native policy engine、YAML policy（非 Rego）、五類 rule（Validate / Mutate / Generate / Verify Images / Cleanup）、CNCF Incubating">Kyverno&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &amp;#43; Constraint 兩層、Rego policy &amp;#43; Audit &amp;#43; Mutation">Gatekeeper&lt;/a> 的差別是：後兩者鎖在 K8s admission controller 領域、OPA 是 &lt;em>跨 enforcement point&lt;/em> 的 unified policy framework — 同一份 policy 可以同時管 K8s admission、API authz、Terraform plan、SQL row-level filter。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/conftest/" data-link-title="Conftest" data-link-desc="OPA CLI wrapper for static config policy check、Rego policy &amp;#43; 多 parser（Terraform / K8s / Dockerfile / JSON）、CI-time gate">Conftest&lt;/a> 的差別是：Conftest 是 OPA 的 &lt;em>CLI wrapper for static config&lt;/em>（在 CI 跑 Terraform / Dockerfile / K8s YAML 檢查）、OPA 本體是 &lt;em>runtime evaluation engine&lt;/em>（線上服務查詢決策）。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>OPA 的核心抽象是 &lt;em>decoupled decision + enforcement&lt;/em> — OPA 只負責 &lt;em>decide&lt;/em>（&lt;code>input&lt;/code> 進來、&lt;code>allow&lt;/code> / &lt;code>deny&lt;/code> + decision metadata 出去）、application 負責 &lt;em>enforce&lt;/em>（拿到 decision 後實際 reject request / block deploy / mask data）。這個解耦讓同一份 policy 跨 K8s admission（透過 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &amp;#43; Constraint 兩層、Rego policy &amp;#43; Audit &amp;#43; Mutation">Gatekeeper&lt;/a> 或 kube-mgmt sidecar）、Envoy authz filter、API gateway、Terraform pre-plan、SQL row-level filter、Kafka topic ACL 都能重用。&lt;/p>
&lt;p>OPA 的查詢語言是 &lt;em>Rego&lt;/em>、Datalog-like declarative language、設計上適合表達「給定一組 fact，這個動作合法嗎」。Rego 跟一般 imperative programming（Python / Go / YAML rules）差距大、team 要投入 1-2 週才能寫出 production-grade policy；換回的是 &lt;em>表達力 + 跨情境一致性&lt;/em> — Kyverno 的 YAML policy 易上手、但跨 K8s 邊界後沒辦法用。&lt;/p></description><content:encoded><![CDATA[<p>Open Policy Agent (OPA) 是 CNCF graduated 的 <em>general-purpose policy engine</em>、設計目的是把「誰能做什麼、什麼 config 才合法」從 application code 抽到外部 policy decision layer。它跟 <a href="/blog/backend/07-security-data-protection/vendors/kyverno/" data-link-title="Kyverno" data-link-desc="K8s-native policy engine、YAML policy（非 Rego）、五類 rule（Validate / Mutate / Generate / Verify Images / Cleanup）、CNCF Incubating">Kyverno</a> / <a href="/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &#43; Constraint 兩層、Rego policy &#43; Audit &#43; Mutation">Gatekeeper</a> 的差別是：後兩者鎖在 K8s admission controller 領域、OPA 是 <em>跨 enforcement point</em> 的 unified policy framework — 同一份 policy 可以同時管 K8s admission、API authz、Terraform plan、SQL row-level filter。跟 <a href="/blog/backend/07-security-data-protection/vendors/conftest/" data-link-title="Conftest" data-link-desc="OPA CLI wrapper for static config policy check、Rego policy &#43; 多 parser（Terraform / K8s / Dockerfile / JSON）、CI-time gate">Conftest</a> 的差別是：Conftest 是 OPA 的 <em>CLI wrapper for static config</em>（在 CI 跑 Terraform / Dockerfile / K8s YAML 檢查）、OPA 本體是 <em>runtime evaluation engine</em>（線上服務查詢決策）。</p>
<h2 id="服務定位">服務定位</h2>
<p>OPA 的核心抽象是 <em>decoupled decision + enforcement</em> — OPA 只負責 <em>decide</em>（<code>input</code> 進來、<code>allow</code> / <code>deny</code> + decision metadata 出去）、application 負責 <em>enforce</em>（拿到 decision 後實際 reject request / block deploy / mask data）。這個解耦讓同一份 policy 跨 K8s admission（透過 <a href="/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &#43; Constraint 兩層、Rego policy &#43; Audit &#43; Mutation">Gatekeeper</a> 或 kube-mgmt sidecar）、Envoy authz filter、API gateway、Terraform pre-plan、SQL row-level filter、Kafka topic ACL 都能重用。</p>
<p>OPA 的查詢語言是 <em>Rego</em>、Datalog-like declarative language、設計上適合表達「給定一組 fact，這個動作合法嗎」。Rego 跟一般 imperative programming（Python / Go / YAML rules）差距大、team 要投入 1-2 週才能寫出 production-grade policy；換回的是 <em>表達力 + 跨情境一致性</em> — Kyverno 的 YAML policy 易上手、但跨 K8s 邊界後沒辦法用。</p>
<p>關鍵張力：<em>Rego 學習曲線</em> ↔ <em>unified policy 的長期價值</em>。只跑 K8s 的團隊用 Kyverno YAML 更直覺；只跑 CI policy 的用 Conftest 更輕；要在 K8s + API + Terraform + DB 跨層統一 policy、或要 audit-grade decision log、或預期 policy 會長期累積成資產的、才值得投資 OPA + Rego。</p>
<p>商業模型：核心 OPA 是 Apache 2.0 OSS、免費。Styra DAS（OPA 創辦人公司）是 enterprise SKU、提供 policy library + impact analysis + multi-cluster management + audit dashboard、適合大型團隊。OPAL（Permit.io 維護的 OSS）是 GitOps-style policy distribution layer、補 OSS OPA 缺的 bundle server。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>OPA 在 policy stack 中承擔哪一段（decision engine） vs enforcement point 各自的 ownership</li>
<li>Rego 投資門檻是否值得（K8s-only vs 跨 enforcement point）</li>
<li>Policy bundle / Decision log / Partial evaluation 三個 first-class concept 在 production 的設計形狀</li>
<li>何時用 OPA、何時走 <a href="/blog/backend/07-security-data-protection/vendors/kyverno/" data-link-title="Kyverno" data-link-desc="K8s-native policy engine、YAML policy（非 Rego）、五類 rule（Validate / Mutate / Generate / Verify Images / Cleanup）、CNCF Incubating">Kyverno</a> / <a href="/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &#43; Constraint 兩層、Rego policy &#43; Audit &#43; Mutation">Gatekeeper</a> / <a href="/blog/backend/07-security-data-protection/vendors/conftest/" data-link-title="Conftest" data-link-desc="OPA CLI wrapper for static config policy check、Rego policy &#43; 多 parser（Terraform / K8s / Dockerfile / JSON）、CI-time gate">Conftest</a> 的取捨</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 OPA deployment 是否健康、最少看四件事：</p>
<ul>
<li><strong>Policy ownership</strong>：誰能寫 / 改 Rego policy（platform team / security team / SRE）、policy 是否進 Git、change 是否經 PR review + staging tenant 跑 24-48hr 觀察</li>
<li><strong>Bundle distribution</strong>：policy 是否 build 成 bundle（tar.gz）、是否簽章、OPA agent 是否定期 pull、bundle server 在哪（自管 nginx / S3 / OPAL / Styra DAS）</li>
<li><strong>Decision log governance</strong>：每個 decision 是否進 audit log（input + output + policy version + timestamp）、log 是否進 SIEM（<a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / Elastic）、retention 多久</li>
<li><strong>Enforcement coverage</strong>：哪些 enforcement point 接 OPA（K8s admission / API / Envoy / Terraform）、policy 是否 share 還是各 point 各寫一份、跨 point 的一致性怎麼驗</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/07-security-data-protection/security-as-risk-routing-system/" data-link-title="7.15 資安作為風險路由系統" data-link-desc="建立資安作為風險路由系統的導讀大綱，串接問題節點、控制面與跨模組交接">Policy as Code Foundations</a> 的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>Rego policy 形狀</strong>：Rego 是 Datalog-like declarative language、policy 寫成 <code>allow { ... }</code> rule、所有條件成立才 evaluate 為 true。實務 idiom：底層寫 <em>base policy</em>（如 <code>policies/k8s/required_labels.rego</code>）、上層寫 <em>policy library</em>（共用 helper 如 <code>policies/lib/registry.rego</code>）、application 端傳 <code>input</code>（K8s admission request / API request / Terraform plan JSON）查詢。Rego 鼓勵 <em>small composable rule</em>、不寫長 imperative function。</p>
<p><strong>Policy bundle</strong>：OPA 不從 Git 直接讀 policy、而是讀 <em>bundle</em>（tar.gz、含 <code>.rego</code> + data JSON、optional 簽章）。Bundle 從 <em>bundle server</em> pull（自管 nginx / S3 / OPAL / Styra DAS）、OPA agent 定期 polling（預設 60s）。Bundle 的核心價值是 <em>versioned + signed + atomically swap</em> — policy 更新不會 partial apply、簽章確保中間沒被改、版本 metadata 讓 decision log 可追到當時用哪版 policy。</p>
<p><strong>Decision log</strong>：每個 OPA query 都可開 decision logging、log entry 含 <code>input</code> + <code>result</code> + <code>policy_version</code> + <code>timestamp</code> + <code>decision_id</code>。意義是 <em>audit-grade reconstruction</em> — 事後可以重跑 <code>opa eval --bundle &lt;version&gt; --input &lt;log_input&gt;</code> 驗證當時 decision 是否正確。Decision log 進 SIEM 後可做 <em>over-permission analysis</em>（哪些 user 拿到 allow 但實際從不該被 allow）跟 <em>policy coverage check</em>（哪些 rule 從沒被觸發過、可能是 dead code）。</p>
<p><strong>Integration pattern</strong>：production OPA 主要四種 enforcement integration — <em>K8s admission</em>（走 <a href="/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &#43; Constraint 兩層、Rego policy &#43; Audit &#43; Mutation">Gatekeeper</a> 是 OPA 官方 K8s integration、或 kube-mgmt 把 OPA 當 sidecar 跑、admission webhook 把 request 送進 OPA decide）；<em>API authz</em>（application 在 request handler 開頭 query OPA、拿 allow/deny 後 enforce）；<em>Envoy / service mesh</em>（Envoy 的 ext_authz filter 接 OPA、L7 authz decision）；<em>Infrastructure as Code</em>（CI 跑 <a href="/blog/backend/07-security-data-protection/vendors/conftest/" data-link-title="Conftest" data-link-desc="OPA CLI wrapper for static config policy check、Rego policy &#43; 多 parser（Terraform / K8s / Dockerfile / JSON）、CI-time gate">Conftest</a> 對 Terraform plan / K8s YAML 做 OPA 評估）。</p>
<p><strong>Partial evaluation</strong>：OPA 進階 feature、把一份 policy 對某個 <em>partial input</em>（如 <code>user=&quot;alice&quot;</code>）pre-evaluate、產出 <em>殘餘 query</em>（如 SQL <code>WHERE tenant_id IN (...)</code> 或 regex），下發給 enforcement point 直接用。意義是 <em>把 policy decision 推到 enforcement point 內部</em>、減少每次 query 都要過 OPA 的 latency；常用於 row-level data filter（policy 寫一次、partial eval 出 SQL WHERE clause、application 直接拼進 query）。</p>
<p><strong>OPAL（GitOps for OPA）</strong>：OSS、Permit.io 維護、解決「policy 從 Git push 到所有 OPA agent」的 distribution 問題。Git → OPAL Server → OPA Agent 的 push model、policy commit 到 main branch 後幾秒內所有 OPA 更新。對應 OSS-only 的 production setup；Styra DAS 提供同等功能 + 管理 UI。</p>
<p><strong>Styra DAS（商業 management）</strong>：Styra 是 OPA 創辦人公司、DAS 是 enterprise SKU。核心價值：<em>policy library</em>（pre-built policy for K8s / Terraform / Kafka）、<em>impact analysis</em>（policy 上 production 前 dry-run 看會 deny 多少現有 resource）、<em>multi-cluster policy distribution</em>、<em>audit dashboard</em>。OSS-only 自己拼 OPAL + decision log + SIEM 也能做、但團隊 &gt; 50 個 cluster / 多 BU 時 DAS 划算。</p>
<p><strong>Constraint Framework</strong>：<a href="/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &#43; Constraint 兩層、Rego policy &#43; Audit &#43; Mutation">Gatekeeper</a> 在 OPA 之上加的 K8s-specific 抽象、用 <code>ConstraintTemplate</code>（Rego policy 模板）+ <code>Constraint</code>（K8s CRD instance、實際 enforce）。對純 K8s 場景比直接寫 Rego 更 K8s-native；但這個抽象只在 K8s 領域有意義、不會跨到 API / Terraform。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>OPA</th>
          <th>Kyverno</th>
          <th>Gatekeeper</th>
          <th>Conftest</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>定位</td>
          <td>General-purpose policy engine</td>
          <td>K8s-native admission controller</td>
          <td>OPA 的 K8s admission integration（官方）</td>
          <td>OPA 的 CLI wrapper for static config</td>
      </tr>
      <tr>
          <td>語言</td>
          <td>Rego（Datalog-like declarative）</td>
          <td>YAML（K8s-native）</td>
          <td>Rego（透過 ConstraintTemplate）</td>
          <td>Rego</td>
      </tr>
      <tr>
          <td>Enforcement</td>
          <td>K8s / API / Envoy / Terraform / SQL / Kafka 跨層</td>
          <td>K8s admission only</td>
          <td>K8s admission only</td>
          <td>CI / pre-commit（不在 runtime）</td>
      </tr>
      <tr>
          <td>學習曲線</td>
          <td>陡 — Rego 1-2 週</td>
          <td>緩 — YAML 1-2 天</td>
          <td>中 — ConstraintTemplate 抽象 + Rego</td>
          <td>中 — Rego 1-2 週、但 scope 小</td>
      </tr>
      <tr>
          <td>部署模型</td>
          <td>OPA agent（sidecar / daemon / library embed）</td>
          <td>K8s controller + webhook</td>
          <td>K8s controller + webhook</td>
          <td>CLI（CI / 本地）</td>
      </tr>
      <tr>
          <td>Mutation</td>
          <td>透過 Gatekeeper Mutation 或 application enforce 補上</td>
          <td>原生 mutate webhook（強項）</td>
          <td>Mutation 是 v3.10+ beta、功能不及 Kyverno</td>
          <td>無（static check only）</td>
      </tr>
      <tr>
          <td>Bundle / 分發</td>
          <td>Bundle server + sign + OPA agent pull / OPAL push</td>
          <td>K8s CRD apply（kubectl）</td>
          <td>K8s CRD apply</td>
          <td>Git repo（CI 直接 clone）</td>
      </tr>
      <tr>
          <td>Decision log</td>
          <td>First-class、audit-grade</td>
          <td>K8s event + audit log</td>
          <td>K8s event + audit log</td>
          <td>CI build log</td>
      </tr>
      <tr>
          <td>商業 SKU</td>
          <td>Styra DAS（management + impact analysis）</td>
          <td>Nirmata Kyverno Enterprise</td>
          <td>無（純 OSS）</td>
          <td>無（純 OSS）</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>跨 enforcement point + long-term policy investment</td>
          <td>K8s-only + 快速上手 + YAML-friendly team</td>
          <td>K8s-only + 已用 OPA / Rego、要 OPA 官方整合</td>
          <td>CI pre-deploy check + Terraform / K8s YAML / Dockerfile</td>
      </tr>
      <tr>
          <td>退場成本</td>
          <td>中 — Rego policy 可移到其他 OPA-compatible engine</td>
          <td>高 — YAML policy 僅 Kyverno 認</td>
          <td>中 — Rego 可重用、Constraint 抽象要重寫</td>
          <td>低 — CLI tool、policy 可移到 OPA runtime</td>
      </tr>
  </tbody>
</table>
<p>選 OPA 的核心訴求：<em>跨 enforcement point 的 unified policy</em> + <em>long-term policy 資產化</em> + <em>audit-grade decision log</em> + 團隊願意投資 Rego。純 K8s + 想快速上手用 <a href="/blog/backend/07-security-data-protection/vendors/kyverno/" data-link-title="Kyverno" data-link-desc="K8s-native policy engine、YAML policy（非 Rego）、五類 rule（Validate / Mutate / Generate / Verify Images / Cleanup）、CNCF Incubating">Kyverno</a>；K8s + 已決定走 OPA 生態用 <a href="/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &#43; Constraint 兩層、Rego policy &#43; Audit &#43; Mutation">Gatekeeper</a>；只跑 CI 不跑 runtime 用 <a href="/blog/backend/07-security-data-protection/vendors/conftest/" data-link-title="Conftest" data-link-desc="OPA CLI wrapper for static config policy check、Rego policy &#43; 多 parser（Terraform / K8s / Dockerfile / JSON）、CI-time gate">Conftest</a>。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Rego idioms（policy library + base policy）</strong>：production Rego 走分層結構 — <code>lib/</code>（utility function、registry whitelist、CIDR check）、<code>base/</code>（concrete policy、引用 lib）、<code>tests/</code>（用 <code>opa test</code> 跑 unit test）。Policy 也是 code、走 PR review + CI test + staging tenant、不是 console 直改。</p>
<p><strong>Partial evaluation for SQL row-level filter</strong>：把 policy 寫成「user 能看哪些 row」、用 <code>opa eval --partial</code> 把 <code>user=&quot;alice&quot;</code> 部分 pre-evaluate、output 殘餘 query 變 SQL <code>WHERE tenant_id IN ('a', 'b', 'c')</code>、application 拼進 query。意義是 <em>policy 不在 query path latency 上</em>、policy 規則仍是 SSoT。對應 RLS（row-level security）的工程化作法。</p>
<p><strong>跟 <a href="/blog/backend/07-security-data-protection/vendors/spire/" data-link-title="SPIRE" data-link-desc="SPIFFE Runtime Environment、attested workload identity、short-lived SVID &#43; Trust Bundle、跨組織 federation">SPIRE</a> workload identity 整合 authz</strong>：service-to-service authz 場景、SPIRE 簽 SVID（SPIFFE ID + mTLS cert）證明 caller 身份、OPA 拿到 SPIFFE ID 後 decide「這個 service 能呼叫這個 API 嗎」。SPIRE 解 <em>who</em>、OPA 解 <em>can they do this</em>、職責清楚分離。</p>
<p><strong>跟 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a> 整合 dynamic credential policy</strong>：Vault 簽 dynamic credential（DB password / cloud STS token）的 issue 決定可以走 OPA — Vault 收到 issue request、轉 OPA decide「這個 caller 在這個 context 能不能拿這個 scope 的 token」。對應 <a href="/blog/backend/07-security-data-protection/cases/failure-credential-rotation-without-scope/" data-link-title="7.C9 反例：憑證輪替未分 Scope" data-link-desc="憑證輪替若未分域分批，容易造成跨系統連鎖中斷。">Failure: Credential Rotation Without Scope</a> 的 lesson：scope 判斷不分散在應用層、集中到 policy engine。</p>
<p><strong>Decision log 進 SIEM</strong>：OPA decision log 設成 push 到 <a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> HEC / Elastic / Datadog、進 SIEM 後可做三件事 — over-permission analysis（哪些 allow 從沒被合法理由觸發）、dead policy detection（哪些 rule 從沒被 evaluate）、anomalous decision pattern（某 service 突然大量 allow 不在 baseline）。</p>
<p><strong>跟 K8s admission 的兩條路</strong>：純 K8s admission 場景、走 <a href="/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &#43; Constraint 兩層、Rego policy &#43; Audit &#43; Mutation">Gatekeeper</a>（OPA 官方 K8s integration、有 Constraint Framework 抽象、社群活躍）比直接跑 OPA + kube-mgmt sidecar 更 production-ready。kube-mgmt 路線適合 already-running OPA 想加 K8s admission 而不引入 Gatekeeper 抽象。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Rego policy review 卡 SRE</strong>：policy 都得 SRE 寫、security team 看不懂 — 拆 <code>lib/</code> 給 SRE 維護、<code>base/</code> 給 security review、用 <code>opa test</code> unit test 保持迭代速度</li>
<li><strong>Bundle distribution 慢 / policy 不一致</strong>：自管 nginx bundle server 沒高可用、agent pull 失敗 fallback 用舊版 — 換 OPAL push model 或 S3 + CloudFront、bundle pull 失敗時 OPA <code>--set status.console=true</code> 直接 alert</li>
<li><strong>Decision log 沒進 SIEM</strong>：OPA 開了 decision log 但只進本地 file、沒人看 — 設 decision log plugin push 到 <a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> HEC / Kafka、不是寫本地 disk</li>
<li><strong>Policy 改完 production 大量 deny</strong>：新 policy 沒在 staging dry-run、上 production 後合法 traffic 被擋 — Styra DAS 的 impact analysis 或自己跑 <code>opa eval --partial</code> 對歷史 decision log replay、看 deny 數量再 promote</li>
<li><strong>OPA latency 高 / API 卡</strong>：每個 request 都 round-trip OPA、policy 複雜 evaluation 慢 — embed OPA as library（Go SDK / WASM）跑 in-process、或用 partial evaluation 把 policy compile 進 SQL / regex</li>
<li><strong>Rego policy bug 線上才發現</strong>：沒 unit test、staging 沒 cover edge case — 強制 PR 要含 <code>opa test</code> case、staging 跑 shadow mode（log only 不 enforce）24hr 再切 enforce</li>
<li><strong>跨 cluster policy drift</strong>：多 cluster 各自 apply、版本不同步 — OPAL 或 Styra DAS multi-cluster sync、不靠 kubectl apply 人工同步</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>K8s admission only + YAML-friendly</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/kyverno/" data-link-title="Kyverno" data-link-desc="K8s-native policy engine、YAML policy（非 Rego）、五類 rule（Validate / Mutate / Generate / Verify Images / Cleanup）、CNCF Incubating">Kyverno</a></td>
      </tr>
      <tr>
          <td>K8s admission + 已選 OPA 生態</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &#43; Constraint 兩層、Rego policy &#43; Audit &#43; Mutation">Gatekeeper</a></td>
      </tr>
      <tr>
          <td>CI pre-deploy check（Terraform / K8s YAML / Dockerfile）</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/conftest/" data-link-title="Conftest" data-link-desc="OPA CLI wrapper for static config policy check、Rego policy &#43; 多 parser（Terraform / K8s / Dockerfile / JSON）、CI-time gate">Conftest</a></td>
      </tr>
      <tr>
          <td>Runtime container behavior（不是 admission）</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/" data-link-title="資安與資料保護 Vendor 清單" data-link-desc="規劃身份、秘密、金鑰、入口防護、供應鏈與偵測工具的服務頁撰寫順序與教學大綱">Falco</a></td>
      </tr>
      <tr>
          <td>Image scan + vulnerability policy</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a>（scan）+ OPA（gate）</td>
      </tr>
      <tr>
          <td>Workload identity / mTLS</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/spire/" data-link-title="SPIRE" data-link-desc="SPIFFE Runtime Environment、attested workload identity、short-lived SVID &#43; Trust Bundle、跨組織 federation">SPIRE</a> + OPA（identity → authz 分工）</td>
      </tr>
      <tr>
          <td>Cloud IAM policy（AWS / GCP / Azure 本體）</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google Cloud IAM</a></td>
      </tr>
      <tr>
          <td>Decision log → SIEM</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / <a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Rego 完整語法 reference（rule / function / built-in / <code>with</code> / <code>some</code>）</li>
<li>Gatekeeper Constraint Framework 的 ConstraintTemplate / Constraint CRD 設計細節（屬 Gatekeeper 頁）</li>
<li>Conftest CLI 用法跟 <code>conftest test</code> / <code>conftest verify</code> 流程（屬 Conftest 頁）</li>
<li>Kyverno YAML policy 語法跟 mutate / generate / verifyImages（屬 Kyverno 頁）</li>
<li>Styra DAS 商業 license / SKU 對照、Nirmata Enterprise 對照</li>
<li>WASM-compiled Rego policy 的 edge deployment 細節</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 OPA 的關係（對照啟示）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/solarwinds-2020-sunburst/" data-link-title="7.R7.2.1 SolarWinds 2020：更新鏈被濫用" data-link-desc="合法更新流程遭植入後，攻擊者如何長期潛伏與橫向擴散">SolarWinds 2020 Sunburst</a></td>
          <td>OPA admission policy 在 K8s 擋住未簽章 image deploy、配合 cosign signature verify 補 supply chain 信任鏈、policy 集中不分散到各 deployment</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/log4shell-cve-2021-44228-component-chain/" data-link-title="7.R7.2.7 Log4Shell 2021：共用元件風險與修補鏈" data-link-desc="共用元件漏洞如何同步影響多服務，並迫使團隊建立依賴治理 workflow">Log4Shell CVE-2021-44228</a></td>
          <td>OPA admission 配合 <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> scan result 擋住已知 vulnerable image deploy、policy 走「critical CVE = deny」</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/cases/failure-credential-rotation-without-scope/" data-link-title="7.C9 反例：憑證輪替未分 Scope" data-link-desc="憑證輪替若未分域分批，容易造成跨系統連鎖中斷。">Failure: Credential Rotation Without Scope</a></td>
          <td>OPA 控制 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a> dynamic credential issuance policy、scope 判斷集中不分散到應用層各自 if-else</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">7.12 供應鏈完整性 (section)</a></td>
          <td>OPA 是 admission gate 的核心工具、跟 SLSA provenance / cosign signature 組合做 policy enforcement、不是看一兩個欄位放行</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/security-as-risk-routing-system/" data-link-title="7.15 資安作為風險路由系統" data-link-desc="建立資安作為風險路由系統的導讀大綱，串接問題節點、控制面與跨模組交接">Policy as Code Foundations (section)</a></td>
          <td>OPA 對應 policy-as-code 的 <em>decoupled decision + enforcement</em>、跨 enforcement point 共用 policy 是設計核心、不是「再寫一份 K8s policy」</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/security-as-risk-routing-system/" data-link-title="7.15 資安作為風險路由系統" data-link-desc="建立資安作為風險路由系統的導讀大綱，串接問題節點、控制面與跨模組交接">7 章 policy-as-code foundations</a>、<a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">7.12 供應鏈完整性</a></li>
<li>平行（Policy-as-Code 批次）：<a href="/blog/backend/07-security-data-protection/vendors/conftest/" data-link-title="Conftest" data-link-desc="OPA CLI wrapper for static config policy check、Rego policy &#43; 多 parser（Terraform / K8s / Dockerfile / JSON）、CI-time gate">Conftest</a>（CI static check）、<a href="/blog/backend/07-security-data-protection/vendors/kyverno/" data-link-title="Kyverno" data-link-desc="K8s-native policy engine、YAML policy（非 Rego）、五類 rule（Validate / Mutate / Generate / Verify Images / Cleanup）、CNCF Incubating">Kyverno</a>（K8s YAML-native）、<a href="/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &#43; Constraint 兩層、Rego policy &#43; Audit &#43; Mutation">Gatekeeper</a>（OPA K8s integration）</li>
<li>跨類：<a href="/blog/backend/07-security-data-protection/vendors/spire/" data-link-title="SPIRE" data-link-desc="SPIFFE Runtime Environment、attested workload identity、short-lived SVID &#43; Trust Bundle、跨組織 federation">SPIRE</a>（workload identity → OPA authz）、<a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a>（dynamic credential policy）、<a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a>（scan → OPA gate）、<a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a>（decision log → SIEM）</li>
<li>跨模組：<a href="/blog/backend/06-reliability/" data-link-title="模組六：可靠性驗證流程" data-link-desc="用 SRE 領域詞彙建問題節點、以服務級案例庫累積驗證脈絡，先建概念與案例庫再進實作交接">6 reliability</a>（CI pre-deploy gate 接 Conftest）、<a href="/blog/backend/08-incident-response/" data-link-title="模組八：事故處理與復盤" data-link-desc="用 IR 領域詞彙建問題節點、以服務級案例庫累積事故脈絡，先建概念與案例庫再進實作交接">8 incident response</a>（policy violation alert → IR routing）</li>
<li>官方：<a href="https://www.openpolicyagent.org/">Open Policy Agent</a>、<a href="https://www.openpolicyagent.org/docs/latest/policy-language/">Rego Policy Language</a>、<a href="https://www.styra.com/">Styra DAS</a>、<a href="https://github.com/permitio/opal">OPAL</a></li>
</ul>
]]></content:encoded></item><item><title>Akamas</title><link>https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/akamas/</link><pubDate>Fri, 15 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/akamas/</guid><description>&lt;p>Akamas 的核心責任是把 workload、SLO constraint、runtime configuration 與雲端成本放進同一個最佳化迴圈。它適合 Kubernetes、VM、database、runtime 與雲端資源調校，重點在用實驗與約束條件產生 rightsizing、configuration tuning 與 capacity efficiency 建議。&lt;/p>
&lt;h2 id="定位">定位&lt;/h2>
&lt;p>Akamas 適合已經有可量測 workload 與成本壓力的服務。當團隊能說清楚 request rate、latency SLO、error budget、CPU / memory headroom、replica policy 與雲端費用目標，Akamas 可以把這些條件轉成 optimization objective，找出更好的配置組合。&lt;/p>
&lt;p>這個定位讓 Akamas 接到三個主章。它從 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/capacity-planning/" data-link-title="9.6 容量規劃模型" data-link-desc="peak forecast、headroom budget、growth curve、autoscaling sizing">9.6 容量規劃模型&lt;/a> 接收 headroom 與 growth curve，從 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cost-engineering/" data-link-title="9.7 成本邊界與 efficiency" data-link-desc="cost per request、cost curve、降級成本、over-provisioning trade-off">9.7 成本邊界與 efficiency&lt;/a> 接收 cost per request 與 cost curve，從 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/improvement-loop/" data-link-title="9.9 Performance Improvement Loop" data-link-desc="壓測 → profile → fix → re-test → release gate 的閉環">9.9 Performance Improvement Loop&lt;/a> 接收 test、profile、fix、re-test 的閉環。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Akamas 的核心定位是 &lt;em>AI-driven autonomous optimization&lt;/em>、不是 monitoring、不是 cost reporting、也不是手動 rightsizing 工具。它用 ML 在 &lt;em>parameter space&lt;/em> 中找出可同時降 cost 並達到 SLO 的配置組合、目標是把 &lt;em>效能調校&lt;/em> 從 expert-driven 手工活、轉成可重跑的工程實驗。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/vantage/" data-link-title="Vantage" data-link-desc="用 cloud cost reports、Kubernetes cost allocation 與 forecast 建立工程可用的成本可見性">Vantage&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/cloudhealth/" data-link-title="CloudHealth" data-link-desc="用 enterprise FinOps governance、policy 與多雲成本管理支援大型組織的容量成本治理">CloudHealth&lt;/a> 這類 FinOps cost tool 的差異是 &lt;em>動作面&lt;/em>。FinOps tool 看到 &lt;em>cost 已經發生&lt;/em>、把帳單拆 tag、推薦保留方案；Akamas 看 workload 在 SLO 邊界下能不能跑得更便宜、輸出的是 &lt;em>configuration change&lt;/em>、不是 invoice 切片。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/04-observability/" data-link-title="模組四：可觀測性平台" data-link-desc="整理 log、metric、trace、dashboard 與 alert 的後端操作實務">Datadog APM&lt;/a> / Prometheus 這類 observability stack 的差異是 &lt;em>決策面&lt;/em>。APM 告訴你 &lt;em>哪裡慢、哪個 endpoint p99 飆&lt;/em>；Akamas 接 APM / metrics 訊號當輸入、輸出 &lt;em>該怎麼改 JVM heap、HPA target、connection pool&lt;/em> 的 recommendation。Observability 是 &lt;em>看&lt;/em>、Akamas 是 &lt;em>動&lt;/em>。&lt;/p>
&lt;p>跟手動 tuning（SRE 拍腦袋、grid search、A/B configuration test）的差異是 &lt;em>參數空間規模&lt;/em>。Manual tuning 在 3-5 個參數還可控；JVM + container limit + HPA + DB pool + node packing 同時轉動時、組合爆炸、ML-driven search 才能在合理 budget 內收斂。&lt;/p></description><content:encoded><![CDATA[<p>Akamas 的核心責任是把 workload、SLO constraint、runtime configuration 與雲端成本放進同一個最佳化迴圈。它適合 Kubernetes、VM、database、runtime 與雲端資源調校，重點在用實驗與約束條件產生 rightsizing、configuration tuning 與 capacity efficiency 建議。</p>
<h2 id="定位">定位</h2>
<p>Akamas 適合已經有可量測 workload 與成本壓力的服務。當團隊能說清楚 request rate、latency SLO、error budget、CPU / memory headroom、replica policy 與雲端費用目標，Akamas 可以把這些條件轉成 optimization objective，找出更好的配置組合。</p>
<p>這個定位讓 Akamas 接到三個主章。它從 <a href="/blog/backend/09-performance-capacity/capacity-planning/" data-link-title="9.6 容量規劃模型" data-link-desc="peak forecast、headroom budget、growth curve、autoscaling sizing">9.6 容量規劃模型</a> 接收 headroom 與 growth curve，從 <a href="/blog/backend/09-performance-capacity/cost-engineering/" data-link-title="9.7 成本邊界與 efficiency" data-link-desc="cost per request、cost curve、降級成本、over-provisioning trade-off">9.7 成本邊界與 efficiency</a> 接收 cost per request 與 cost curve，從 <a href="/blog/backend/09-performance-capacity/improvement-loop/" data-link-title="9.9 Performance Improvement Loop" data-link-desc="壓測 → profile → fix → re-test → release gate 的閉環">9.9 Performance Improvement Loop</a> 接收 test、profile、fix、re-test 的閉環。</p>
<h2 id="服務定位">服務定位</h2>
<p>Akamas 的核心定位是 <em>AI-driven autonomous optimization</em>、不是 monitoring、不是 cost reporting、也不是手動 rightsizing 工具。它用 ML 在 <em>parameter space</em> 中找出可同時降 cost 並達到 SLO 的配置組合、目標是把 <em>效能調校</em> 從 expert-driven 手工活、轉成可重跑的工程實驗。</p>
<p>跟 <a href="/blog/backend/09-performance-capacity/vendors/vantage/" data-link-title="Vantage" data-link-desc="用 cloud cost reports、Kubernetes cost allocation 與 forecast 建立工程可用的成本可見性">Vantage</a> / <a href="/blog/backend/09-performance-capacity/vendors/cloudhealth/" data-link-title="CloudHealth" data-link-desc="用 enterprise FinOps governance、policy 與多雲成本管理支援大型組織的容量成本治理">CloudHealth</a> 這類 FinOps cost tool 的差異是 <em>動作面</em>。FinOps tool 看到 <em>cost 已經發生</em>、把帳單拆 tag、推薦保留方案；Akamas 看 workload 在 SLO 邊界下能不能跑得更便宜、輸出的是 <em>configuration change</em>、不是 invoice 切片。</p>
<p>跟 <a href="/blog/backend/04-observability/" data-link-title="模組四：可觀測性平台" data-link-desc="整理 log、metric、trace、dashboard 與 alert 的後端操作實務">Datadog APM</a> / Prometheus 這類 observability stack 的差異是 <em>決策面</em>。APM 告訴你 <em>哪裡慢、哪個 endpoint p99 飆</em>；Akamas 接 APM / metrics 訊號當輸入、輸出 <em>該怎麼改 JVM heap、HPA target、connection pool</em> 的 recommendation。Observability 是 <em>看</em>、Akamas 是 <em>動</em>。</p>
<p>跟手動 tuning（SRE 拍腦袋、grid search、A/B configuration test）的差異是 <em>參數空間規模</em>。Manual tuning 在 3-5 個參數還可控；JVM + container limit + HPA + DB pool + node packing 同時轉動時、組合爆炸、ML-driven search 才能在合理 budget 內收斂。</p>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Akamas optimization study 是否健康、最少看四件事：</p>
<ul>
<li><strong>Agent / collector 部署完整度</strong>：哪些 target（JVM / container / K8s / DB）裝了 Akamas agent 或接到 metrics source、metrics window 是否涵蓋 representative peak、是否漏 tail latency 與 GC pause</li>
<li><strong>Target system 邊界定義</strong>：optimization 是針對單一 service / 一組 microservice / 整個 K8s cluster、tunable parameter list 是否經 service owner 審核、不在 list 內的參數是否會被間接影響</li>
<li><strong>Optimization goal 對得上 business outcome</strong>：goal 是「降 cost 30%」還是「同 SLO 下 cost minimize」、是否同時聲明 latency / error budget / throughput 的下界、避免 ML 為達 cost target 把 latency 推到邊緣</li>
<li><strong>Safety bound 緊 / 鬆的取捨</strong>：bound 太緊收斂不到方案、bound 太鬆 production validation 會出事、是否有 staging tenant 跑完再 promote、autopilot 範圍是否限定 non-critical workload</li>
</ul>
<p>四項任一缺、就是 <a href="/blog/backend/09-performance-capacity/improvement-loop/" data-link-title="9.9 Performance Improvement Loop" data-link-desc="壓測 → profile → fix → re-test → release gate 的閉環">9.9 Performance Improvement Loop</a> 邊界的待補項目、不是 Akamas 設定問題。</p>
<h2 id="適用場景">適用場景</h2>
<p>Kubernetes rightsizing 是 Akamas 的主要入口。多服務平台常見問題是 requests / limits、HPA target、replica floor、node pool 與 runtime 參數互相牽動；Akamas 的價值是把這些參數放進同一個優化空間，而非逐項手動調整。</p>
<p>Runtime 與 database tuning 適合需要穩定 SLO 的服務。JVM heap、Go runtime、PostgreSQL、MongoDB、Elasticsearch 或 Spark workload 會同時受配置、資料形狀與流量尖峰影響；optimization tool 可以用可重跑實驗保留調校證據。</p>
<p>FinOps 與 SRE 協作適合用 Akamas 建立共同語言。FinOps 關心浪費與預算，SRE 關心 latency、error rate 與可靠性；Akamas 類工具把節省幅度、性能風險與回退條件放在同一份 recommendation 裡，降低跨團隊溝通成本。</p>
<h2 id="選型判準">選型判準</h2>
<table>
  <thead>
      <tr>
          <th>判準</th>
          <th>Akamas 的價值</th>
          <th>需要補的能力</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>優化目標</td>
          <td>把 cost、latency、throughput 與 SLO 一起建模</td>
          <td>明確 business objective 與風險上限</td>
      </tr>
      <tr>
          <td>參數空間</td>
          <td>支援 runtime、container、database 與雲端配置</td>
          <td>服務 owner 對參數語意的審核</td>
      </tr>
      <tr>
          <td>執行模式</td>
          <td>支援 human approval、pipeline 與自動化調校</td>
          <td>rollout guardrail、變更紀錄與回退</td>
      </tr>
      <tr>
          <td>證據保存</td>
          <td>recommendation 可以回寫實驗、約束與預期效益</td>
          <td>production validation 與長期 drift 追蹤</td>
      </tr>
  </tbody>
</table>
<p>優化目標價值來自約束透明。成本降低只有在 latency、availability 與 error budget 邊界內才成立，因此 Akamas 頁面要先問目標函數與 guardrail，再談節省幅度。</p>
<p>參數空間價值來自跨層調校。單看 CPU request 可能會誤判，因為 GC、DB connection、thread pool、replica policy 與 node packing 會一起改變 cost per request。</p>
<p>執行模式價值來自可控自動化。Human-in-the-loop 適合早期導入，pipeline mode 適合 release gate，autopilot 適合 guardrail、rollback 與 owner model 已成熟的環境。</p>
<h2 id="跟其他工具的取捨">跟其他工具的取捨</h2>
<p>Akamas 和 Vantage 的主要差異是控制面。Vantage 偏 cost visibility、allocation、forecast 與報表；Akamas 偏把效能約束放進 configuration optimization，適合需要直接調整 capacity 與 runtime 參數的場景。</p>
<p>Akamas 和 CloudHealth 的主要差異是操作層級。CloudHealth 偏 enterprise FinOps governance、policy、showback / chargeback 與多雲管理；Akamas 偏 service-level optimization 與工程調校閉環。</p>
<p>Akamas 和 AWS Cost Explorer 的主要差異是範圍與自動化。Cost Explorer 是 AWS-native 成本分析入口；Akamas 可以把成本訊號跟 workload、SLO 與配置實驗接起來，適合需要跨層優化的服務。</p>
<h2 id="操作成本">操作成本</h2>
<p>Akamas 的主要成本是 optimization model 建立。團隊要定義目標、約束、可調參數、測試窗口、流量代表性與成功門檻，並讓 service owner 審核每個 recommendation 的業務風險。</p>
<p>導入成本會隨自動化程度上升。早期可以用 approval workflow 接 recommendation；進入 pipeline 或 autopilot 後，要補 change window、deploy marker、rollback、SLO guardrail、audit log 與 incident handoff。</p>
<p>資料品質會直接影響結果可信度。Metric 延遲、缺少 tail latency、成本 tag 錯誤、workload window 偏差或測試環境差異，都會讓 recommendation 的 confidence 下降。</p>
<h2 id="evidence-package">Evidence Package</h2>
<p>Akamas 結果應回寫到 optimization evidence package。最小欄位包括 optimization goal、constraint、tunable parameters、workload window、baseline cost、baseline performance、recommended configuration、expected saving、risk note、validation result 與 owner。</p>
<table>
  <thead>
      <tr>
          <th>欄位</th>
          <th>Akamas 證據來源</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Source</td>
          <td>optimization report、experiment result、recommendation</td>
      </tr>
      <tr>
          <td>Time range</td>
          <td>workload sample、test window、production validation</td>
      </tr>
      <tr>
          <td>Query link</td>
          <td>APM / metrics / cost dashboard / Akamas report</td>
      </tr>
      <tr>
          <td>Data quality</td>
          <td>workload representativeness、metric freshness、tag coverage</td>
      </tr>
      <tr>
          <td>Confidence</td>
          <td>SLO guardrail、repeatability、rollback readiness</td>
      </tr>
      <tr>
          <td>Known gap</td>
          <td>未覆蓋 cohort、未納入下游 quota、測試環境差異</td>
      </tr>
  </tbody>
</table>
<p>Evidence package 的核心用途是讓成本調校可以被審查。Akamas recommendation 要能回答「節省來自哪個配置變更、哪個 SLO 保護這次變更、哪個訊號觸發回退」。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Akamas（AI optimization）</th>
          <th>FinOps tool（Vantage / CloudHealth）</th>
          <th>APM（Datadog / Prometheus）</th>
          <th>Manual tuning（SRE / 性能工程師）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>主要動作</td>
          <td>產出 configuration change recommend</td>
          <td>拆帳單、報表、保留方案推薦</td>
          <td>顯示瓶頸位置與 metric</td>
          <td>拍腦袋 / grid search / A/B test</td>
      </tr>
      <tr>
          <td>決策訊號</td>
          <td>workload + SLO + cost 同模型</td>
          <td>帳單 + tag</td>
          <td>latency / saturation / error metric</td>
          <td>經驗 + ad-hoc benchmark</td>
      </tr>
      <tr>
          <td>適用參數空間</td>
          <td>多參數（JVM + container + HPA + DB）</td>
          <td>N/A（不動參數）</td>
          <td>N/A（不動參數）</td>
          <td>3-5 個參數還可控</td>
      </tr>
      <tr>
          <td>自動化程度</td>
          <td>human approval / pipeline / autopilot</td>
          <td>recommendation + dashboard、不自動執行</td>
          <td>alert + dashboard</td>
          <td>全人工</td>
      </tr>
      <tr>
          <td>風險邊界</td>
          <td>靠 safety bound + staging validation</td>
          <td>低（只動 commitment、不動 runtime）</td>
          <td>低（觀察、不動）</td>
          <td>靠人盯、容易遺漏 cross-parameter</td>
      </tr>
      <tr>
          <td>何時不適用</td>
          <td>參數空間小 / SLO 未明確 / metric 不全</td>
          <td>需要動 runtime 才能省的場景</td>
          <td>不解決「改什麼」、只解決「在哪裡」</td>
          <td>參數爆炸時 ROI 太差</td>
      </tr>
  </tbody>
</table>
<p>選 Akamas 的核心訴求是 <em>參數空間大 + workload 可重跑 + cost 壓力夠高、值得投入 optimization study setup 成本</em>。小規模 / 參數少 / SLO 不明、直接走 manual tuning 更快；只想看帳單拆解、走 FinOps tool；只想知道哪裡慢、走 APM。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Optimization study 的三要素</strong>：goal（目標函數、常見 <code>minimize cost subject to p99 latency &lt; X, error rate &lt; Y</code>）、parameter list（哪些 knob 可動、各自合法區間）、safety bound（哪些 metric 不能越界、越界即 reject candidate）。study setup 是 Akamas 最重的人力投入、value 來自 <em>把隱性調校 know-how 寫成可重跑配置</em>、不是 ML 本身。</p>
<p><strong>Live experiment vs offline study</strong>：offline study 用 staging 環境跑代表性 workload、安全但與 production 流量結構有偏差；live experiment 在 production 上小範圍試 candidate（例如 single canary pod）、訊號真實但需要嚴格 safety bound 與 rollback。多數團隊先 offline 找候選 region、再 live 收斂 — 不要一開始就 production autopilot。</p>
<p><strong>跟 K8s VPA / HPA 互補不互斥</strong>：HPA 處理 <em>replica 數量</em>、VPA 處理 <em>單 pod request / limit</em>、Akamas 處理 <em>參數組合 + 跨層協同</em>（含 JVM heap、HPA target、replica floor、node pool selection）。三者並用時要明確分工 — Akamas 不該跟 VPA 同時調 request，否則彼此推翻；常見作法是 Akamas 設 <em>baseline configuration</em>、VPA / HPA 在 baseline 上做即時微調。</p>
<p><strong>跟 observability stack integration</strong>：Akamas 接 Datadog / Prometheus / New Relic / Dynatrace 取 metrics、接 Kubernetes API 取 workload state、接 cloud billing API 取 cost。integration 品質直接決定 recommendation 信度 — metric 缺 tail latency 或 cost tag 不準、ML 會找到 <em>看起來省、實際出事</em> 的配置。對應 <a href="/blog/backend/09-performance-capacity/performance-observability/" data-link-title="9.8 效能可觀測性" data-link-desc="saturation metric、USE / RED method、cost dashboard">9.4 Performance Observability</a> 的訊號治理。</p>
<p><strong>安全邊界 — 不該全 autopilot production</strong>：critical workload（payment / auth / DB primary）即使 SLO bound 寫清楚也不該 autopilot、recommendation 要走 human approval + change window；non-critical workload（batch job / dev cluster / internal tool）autopilot 可接受。ML black-box 是 production safety 的本質風險、不是設定問題。</p>
<p><strong>ML 黑箱可解釋性</strong>：Akamas recommendation 給出 <em>why this configuration</em> 的 sensitivity analysis（哪個參數影響最大、哪個參數對 cost / latency 是 trade-off curve），但根因解釋仍弱於人類性能工程師的 mental model。Production 採用前、service owner 要能用自己的 domain knowledge 對 recommendation 做 sanity check、不是純靠 ML score 拍板。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Optimization goal 對不上 business outcome</strong>：goal 寫「降 cost 30%」但沒寫 latency / error budget 下界 — ML 把 cost 壓到 SLO 邊緣、production 上線就 incident、回頭補 safety bound + business KPI alignment</li>
<li><strong>Safety bound 太鬆 / 太緊</strong>：太鬆 candidate 過 staging 但 production validation 出事、太緊 study 跑不出有意義方案 — bound 應綁 production-observed p99 / error rate baseline + 20% 緩衝、不是拍數字</li>
<li><strong>ML black-box 沒辦法解釋</strong>：service owner 看不懂為何 recommendation 改某個 obscure JVM flag — 跑 sensitivity analysis、不接受 <em>無 domain rationale</em> 的 recommendation、視為 candidate 而非 final</li>
<li><strong>參數空間 leak 到 list 外</strong>：Akamas 改 JVM heap 但間接讓 GC 行為變、撞到沒納入的 thread pool — 補 cross-parameter dependency 到 list、或縮小 study scope</li>
<li><strong>Workload window 不代表 production</strong>：staging 跑 50% 流量、ML 找到的方案在 100% peak hour 出事 — workload sample 必須涵蓋 representative peak、不是平均值</li>
<li><strong>Autopilot 推到 critical service</strong>：non-critical workload 試出甜頭、團隊把 autopilot 推到 payment service、incident 後 rollback 困難 — autopilot 範圍要寫進政策、critical service 永遠 human approval</li>
<li><strong>Recommendation 跟 VPA 互推</strong>：Akamas 設 request = X、VPA 立刻調回 Y、循環 — Akamas baseline 跟 VPA scope 要分層、不要在同一個 dimension 兩個 controller 同時動</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>Akamas 目前在 09 案例庫中適合作為 <a href="/blog/backend/09-performance-capacity/cost-engineering/" data-link-title="9.7 成本邊界與 efficiency" data-link-desc="cost per request、cost curve、降級成本、over-provisioning trade-off">9.7 成本邊界與 efficiency</a> 的工具承接點。它可回寫到 <a href="/blog/backend/09-performance-capacity/cases/zomato-tidb-to-dynamodb-migration/" data-link-title="9.C20 Zomato：從 TiDB 遷移到 DynamoDB、吞吐 4 倍、延遲降 90%、成本減 50%" data-link-desc="Zomato 帳單系統從 TiDB 遷移到 DynamoDB、吞吐 2K→8K RPM、延遲降 90%、成本減 50%">9.C20 Zomato TiDB → DynamoDB 遷移</a> 的成本下降 50% 取捨、<a href="/blog/backend/09-performance-capacity/cases/riot-games-eks-multi-cluster/" data-link-title="9.C12 Riot Games：246 個 EKS cluster 的多遊戲多地區治理" data-link-desc="Riot Games 從 Mesos 遷移到 EKS、用 246 個 cluster 跨遊戲跨地區治理、年省 1000 萬美金">9.C12 Riot Games 246 EKS cluster</a> 的年省 1000 萬美金的 Kubernetes capacity 調校、<a href="/blog/backend/09-performance-capacity/cases/capcom-gaming-dynamodb-eks/" data-link-title="9.C19 Capcom：Resident Evil / Monster Hunter 在 DynamoDB &#43; EKS 上的遊戲後端" data-link-desc="Capcom 把 Resident Evil、Street Fighter、Monster Hunter 遊戲後端跑在 DynamoDB &#43; EKS、單一秒位數延遲、營運成本降 30%">9.C19 Capcom 遊戲後端</a> 的營運成本下降 30%、以及 <a href="/blog/backend/09-performance-capacity/cases/gr8-tech-ai-predicted-betting-peak/" data-link-title="9.C2 GR8 Tech：AI 預測式自動擴容下的體育博彩高峰" data-link-desc="AI 預測 &#43; EKS 自動擴容怎麼在 25ms p95 下承載 54000 TPS 體育博彩峰值流量">9.C2 GR8 Tech 體育博彩</a> 的需求降低時成本下降 25% 彈性曲線。</p>
<p>這些案例的重點是優化條件。Akamas 頁引用案例時，應把「某公司節省成本」轉成 workload window、SLO constraint、調整參數、驗證方式與回退條件 — 例如 Zomato 的 4x throughput / 90% latency 改善是同時優化目標、不是只看成本欄位。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/09-performance-capacity/capacity-planning/" data-link-title="9.6 容量規劃模型" data-link-desc="peak forecast、headroom budget、growth curve、autoscaling sizing">9.6 容量規劃模型</a></li>
<li>上游：<a href="/blog/backend/09-performance-capacity/cost-engineering/" data-link-title="9.7 成本邊界與 efficiency" data-link-desc="cost per request、cost curve、降級成本、over-provisioning trade-off">9.7 成本邊界與 efficiency</a></li>
<li>上游：<a href="/blog/backend/09-performance-capacity/improvement-loop/" data-link-title="9.9 Performance Improvement Loop" data-link-desc="壓測 → profile → fix → re-test → release gate 的閉環">9.9 Performance Improvement Loop</a></li>
<li>平行：<a href="/blog/backend/09-performance-capacity/vendors/vantage/" data-link-title="Vantage" data-link-desc="用 cloud cost reports、Kubernetes cost allocation 與 forecast 建立工程可用的成本可見性">Vantage</a></li>
<li>官方：<a href="https://docs.akamas.io/akamas-docs/getting-started/introduction-to-akamas">Akamas documentation</a></li>
</ul>
]]></content:encoded></item><item><title>GoReplay</title><link>https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/goreplay/</link><pubDate>Fri, 15 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/goreplay/</guid><description>&lt;p>GoReplay 的核心責任是捕捉 production HTTP traffic，並把真實請求形狀重播到 staging、shadow environment 或新版本。它適合驗證 synthetic load 難以建模的 endpoint mix、header、payload size、burst pattern 與 long-tail 行為，重點在把 production reality 轉成可控 replay artifact。&lt;/p>
&lt;h2 id="定位">定位&lt;/h2>
&lt;p>GoReplay 適合在 synthetic workload 可信度偏低時使用。當 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/workload-modeling/" data-link-title="9.2 Workload Modeling" data-link-desc="把 production traffic shape 翻成可重播的壓測模型">9.2 Workload Modeling&lt;/a> 很難準確描述使用者路徑、payload 分布或 endpoint mix，GoReplay 可以從 production traffic 擷取真實樣本，再用 rate limit、filter、rewrite 與 output target 控制重播範圍。&lt;/p>
&lt;p>這個定位讓 GoReplay 接到 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/production-validation/" data-link-title="9.10 Production-Side 驗證" data-link-desc="shadow traffic、dark launch、canary、production-like load test">9.10 Production-Side 驗證&lt;/a> 的 shadow traffic。它的價值在於保留 production 請求形狀；它的風險在於 PII、credential、side effect、下游容量與 capture host overhead 都要被治理。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/k6/" data-link-title="k6" data-link-desc="用 scriptable scenario 建立 API、protocol 與 CI 友善壓測的效能工程工具">k6&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/jmeter/" data-link-title="Apache JMeter" data-link-desc="用 GUI、plugin 與多 protocol sampler 承接企業壓測資產的效能工程工具">JMeter&lt;/a> 的 synthetic load 設計 mindset 完全不同。Scripted load 假設 &lt;em>測試者能描述使用者行為&lt;/em> — 寫 script、設 rate、跑 scenario；GoReplay 假設 &lt;em>production 才是 source of truth&lt;/em> — endpoint mix、header 分布、payload size、burst pattern 都從真實 traffic 抽樣、不靠人為建模。對 long-tail 行為（少見 endpoint、巨大 payload、特殊 header 組合）這個差異決定了 capacity 規劃的真實度。&lt;/p>
&lt;h2 id="最短判讀路徑">最短判讀路徑&lt;/h2>
&lt;p>判斷 GoReplay deployment 是否健康、最少看四件事：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Capture mode&lt;/strong>：用 &lt;code>raw&lt;/code> (libpcap-based)、&lt;code>pcap-file&lt;/code>（離線 replay 已存檔的 pcap）、&lt;code>file&lt;/code>（GoReplay 原生 gor format）哪一種？raw 對 production host 有 CPU / network overhead、pcap-file 適合事後 replay、file 適合 long-running capture buffer&lt;/li>
&lt;li>&lt;strong>Replay target&lt;/strong>：打到 staging full-stack、shadow service、還是 isolated sandbox？POST / PUT / DELETE 是否導到 dry-run path 或 idempotent mock？webhook / payment / notification 是否被攔截？&lt;/li>
&lt;li>&lt;strong>Rate adjustment&lt;/strong>：用原始 production rate replay，還是 2x / 10x / 0.1x？capacity 規劃通常需要 &lt;em>speed up&lt;/em> 來測未來流量、debug 通常需要 &lt;em>slow down&lt;/em> 跟單一請求追查&lt;/li>
&lt;li>&lt;strong>Middleware filter&lt;/strong>：PII / token / cookie / credential redaction 在哪一段做（capture 前、capture 後、replay 前）？是否走 GoReplay middleware binary（stdin / stdout pipeline）統一處理&lt;/li>
&lt;/ul>
&lt;h2 id="適用場景">適用場景&lt;/h2>
&lt;p>架構遷移驗證適合 GoReplay。DB、cache、search、API gateway 或 framework 重寫時，可以把真實 HTTP traffic replay 到新路徑，觀察 latency、error、resource saturation 與 response diff。&lt;/p></description><content:encoded><![CDATA[<p>GoReplay 的核心責任是捕捉 production HTTP traffic，並把真實請求形狀重播到 staging、shadow environment 或新版本。它適合驗證 synthetic load 難以建模的 endpoint mix、header、payload size、burst pattern 與 long-tail 行為，重點在把 production reality 轉成可控 replay artifact。</p>
<h2 id="定位">定位</h2>
<p>GoReplay 適合在 synthetic workload 可信度偏低時使用。當 <a href="/blog/backend/09-performance-capacity/workload-modeling/" data-link-title="9.2 Workload Modeling" data-link-desc="把 production traffic shape 翻成可重播的壓測模型">9.2 Workload Modeling</a> 很難準確描述使用者路徑、payload 分布或 endpoint mix，GoReplay 可以從 production traffic 擷取真實樣本，再用 rate limit、filter、rewrite 與 output target 控制重播範圍。</p>
<p>這個定位讓 GoReplay 接到 <a href="/blog/backend/09-performance-capacity/production-validation/" data-link-title="9.10 Production-Side 驗證" data-link-desc="shadow traffic、dark launch、canary、production-like load test">9.10 Production-Side 驗證</a> 的 shadow traffic。它的價值在於保留 production 請求形狀；它的風險在於 PII、credential、side effect、下游容量與 capture host overhead 都要被治理。</p>
<p>跟 <a href="/blog/backend/09-performance-capacity/vendors/k6/" data-link-title="k6" data-link-desc="用 scriptable scenario 建立 API、protocol 與 CI 友善壓測的效能工程工具">k6</a> / <a href="/blog/backend/09-performance-capacity/vendors/jmeter/" data-link-title="Apache JMeter" data-link-desc="用 GUI、plugin 與多 protocol sampler 承接企業壓測資產的效能工程工具">JMeter</a> 的 synthetic load 設計 mindset 完全不同。Scripted load 假設 <em>測試者能描述使用者行為</em> — 寫 script、設 rate、跑 scenario；GoReplay 假設 <em>production 才是 source of truth</em> — endpoint mix、header 分布、payload size、burst pattern 都從真實 traffic 抽樣、不靠人為建模。對 long-tail 行為（少見 endpoint、巨大 payload、特殊 header 組合）這個差異決定了 capacity 規劃的真實度。</p>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 GoReplay deployment 是否健康、最少看四件事：</p>
<ul>
<li><strong>Capture mode</strong>：用 <code>raw</code> (libpcap-based)、<code>pcap-file</code>（離線 replay 已存檔的 pcap）、<code>file</code>（GoReplay 原生 gor format）哪一種？raw 對 production host 有 CPU / network overhead、pcap-file 適合事後 replay、file 適合 long-running capture buffer</li>
<li><strong>Replay target</strong>：打到 staging full-stack、shadow service、還是 isolated sandbox？POST / PUT / DELETE 是否導到 dry-run path 或 idempotent mock？webhook / payment / notification 是否被攔截？</li>
<li><strong>Rate adjustment</strong>：用原始 production rate replay，還是 2x / 10x / 0.1x？capacity 規劃通常需要 <em>speed up</em> 來測未來流量、debug 通常需要 <em>slow down</em> 跟單一請求追查</li>
<li><strong>Middleware filter</strong>：PII / token / cookie / credential redaction 在哪一段做（capture 前、capture 後、replay 前）？是否走 GoReplay middleware binary（stdin / stdout pipeline）統一處理</li>
</ul>
<h2 id="適用場景">適用場景</h2>
<p>架構遷移驗證適合 GoReplay。DB、cache、search、API gateway 或 framework 重寫時，可以把真實 HTTP traffic replay 到新路徑，觀察 latency、error、resource saturation 與 response diff。</p>
<p>Long-tail workload 校正適合 GoReplay。Synthetic scenario 通常覆蓋主路徑，GoReplay 可以揭露少見 endpoint、特殊 header、巨大 payload、冷門 tenant 與尖峰 cohort。</p>
<p>事故後修補驗證適合 GoReplay。若事故由特定請求形狀觸發，capture sample 可以在修補環境重播，確認 latency、error 或 resource usage 是否回到可接受範圍。</p>
<h2 id="選型判準">選型判準</h2>
<table>
  <thead>
      <tr>
          <th>判準</th>
          <th>GoReplay 的價值</th>
          <th>需要補的能力</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>真實 traffic</td>
          <td>endpoint mix、payload、header 分布接近 production</td>
          <td>PII / credential 遮罩與權限治理</td>
      </tr>
      <tr>
          <td>HTTP replay</td>
          <td>對 HTTP API 路徑直接有效</td>
          <td>非 HTTP protocol 與加密流量處理</td>
      </tr>
      <tr>
          <td>Filter / rewrite</td>
          <td>可控制 host、path、header、rate</td>
          <td>side effect 隔離與 sandbox target</td>
      </tr>
      <tr>
          <td>Capture artifact</td>
          <td>可保存樣本做回歸驗證</td>
          <td>retention、存取控制與樣本代表性</td>
      </tr>
  </tbody>
</table>
<p>真實 traffic 價值來自分布保真。它能捕捉 synthetic script 容易漏掉的 query parameter、header、payload size 與 endpoint mix，但 capture sample 也會帶入 production 資料治理責任。</p>
<p>Filter / rewrite 價值來自安全邊界。Replay 前要改寫 target、移除 credential、遮罩 PII、限制 rate，並把寫入類請求導到 sandbox 或 dry-run path。</p>
<h2 id="跟其他方式的取捨">跟其他方式的取捨</h2>
<p>GoReplay 和 k6 / Gatling / Locust 的主要差異是流量來源。GoReplay 取 production sample，保真度高；scripted load test 取人工模型，可控性高。</p>
<p>GoReplay 和 service mesh mirroring 的主要差異是部署位置。GoReplay 在 host / network capture 層工作，適合沒有 mesh 的服務；service mesh mirroring 在 sidecar / proxy 層工作，適合已經落地 mesh 的平台。</p>
<p>GoReplay 和 AWS VPC Traffic Mirroring 的主要差異是應用語意。GoReplay 對 HTTP replay 更直接；VPC Traffic Mirroring 在網路層複製封包，侵入性低但應用層 rewrite、遮罩與 replay 控制需要額外處理。</p>
<h3 id="核心取捨表">核心取捨表</h3>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>GoReplay</th>
          <th>k6 / JMeter (synthetic)</th>
          <th>AWS VPC Traffic Mirroring</th>
          <th>Service Mesh Mirroring</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>流量來源</td>
          <td>Production sniff（real shape）</td>
          <td>Scripted scenario（builder&rsquo;s model）</td>
          <td>VPC 網路層封包複製</td>
          <td>Sidecar / proxy 層複製</td>
      </tr>
      <tr>
          <td>工作層級</td>
          <td>HTTP / L7（capture host）</td>
          <td>HTTP / L7（client-side script）</td>
          <td>L3-L4（packet level）</td>
          <td>L7（sidecar in-mesh）</td>
      </tr>
      <tr>
          <td>Rate adjust</td>
          <td>原生支援（0.1x - 10x）</td>
          <td>scenario 內 ramp / arrival rate</td>
          <td>全量、無 rate control</td>
          <td>mesh policy 控制</td>
      </tr>
      <tr>
          <td>Replay 控制</td>
          <td>filter / rewrite / middleware binary</td>
          <td>程式內 logic 完整可控</td>
          <td>需自寫 application-level rewriter</td>
          <td>mesh-level routing rule</td>
      </tr>
      <tr>
          <td>Long-tail 覆蓋</td>
          <td>強（real distribution）</td>
          <td>弱（取決於 scenario design）</td>
          <td>強（real distribution）但需後處理</td>
          <td>強（in-mesh real traffic）</td>
      </tr>
      <tr>
          <td>PII / 安全成本</td>
          <td>高（middleware 自己寫 redaction）</td>
          <td>低（fixture 由人控制）</td>
          <td>高（packet-level 難語意化遮罩）</td>
          <td>中（mesh policy 可協助）</td>
      </tr>
      <tr>
          <td>部署條件</td>
          <td>host agent + libpcap，需有權限 sniff interface</td>
          <td>無（client / load generator 機台即可）</td>
          <td>AWS-only、ENI mirroring 配額</td>
          <td>已落地 mesh（Istio / Linkerd）</td>
      </tr>
  </tbody>
</table>
<p>選 GoReplay 的核心訴求：<em>HTTP 應用層 replay + production shape 保真 + 沒落地 mesh</em>；若已用 mesh、優先看 mesh 內建 mirroring；若要跨 protocol（gRPC / 自家 binary）GoReplay 開源版受限、需考慮 Pro 版或 mesh 方案。</p>
<h2 id="操作成本">操作成本</h2>
<p>GoReplay 的主要成本是資料安全。Production request 可能包含 token、cookie、PII、payment payload、internal IDs 與 tenant 資料，capture、保存、重播與刪除都要有明確 owner。</p>
<p>Replay 成本來自下游副作用。POST、PUT、DELETE、webhook、email、payment、notification 與 queue publish 都要導到 sandbox、mock 或 idempotent dry-run，避免 replay 造成重複交易或通知。</p>
<p>Capture 成本來自主機資源。高流量服務上的 capture agent 會消耗 CPU、network 與 disk，正式啟用前要先量測 overhead，並設定 sampling、rate limit 與 stop condition。</p>
<h2 id="evidence-package">Evidence Package</h2>
<p>GoReplay 結果應回寫到 evidence package。最小欄位包括 capture source、capture time range、filter / rewrite rule、sample size、replay rate、target environment、data masking status、p95 / p99、error rate、resource saturation、known gap 與 owner。</p>
<table>
  <thead>
      <tr>
          <th>欄位</th>
          <th>GoReplay 證據來源</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Source</td>
          <td>capture command、sample hash、replay command</td>
      </tr>
      <tr>
          <td>Time range</td>
          <td>capture start / end、replay start / end</td>
      </tr>
      <tr>
          <td>Query link</td>
          <td>APM / metrics / logs / diff 查詢連結</td>
      </tr>
      <tr>
          <td>Data quality</td>
          <td>sample representativeness、masking status</td>
      </tr>
      <tr>
          <td>Confidence</td>
          <td>replay rate、target parity、capture coverage</td>
      </tr>
      <tr>
          <td>Known gap</td>
          <td>未捕捉 protocol、資料遮罩限制、sandbox 差異</td>
      </tr>
  </tbody>
</table>
<p>Evidence package 的核心用途是讓 replay 結論可審查。Reviewer 要能知道樣本來自哪段 production、經過哪些 filter、打到哪個 target，以及哪些 side effect 被 mock 或隔離。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Capture to file（pcap-like artifact）</strong>：用 <code>--output-file</code> 把 capture 寫成 GoReplay 原生 gor file（或讀 pcap）、之後用 <code>--input-file</code> 重複 replay。這個模式讓 <em>capture window</em> 跟 <em>replay run</em> 解耦 — capture 一次，可在不同 staging branch / 不同 rate / 不同 target 重播多次。對 regression 驗證跟「事故當時的 traffic shape」回放特別關鍵、但 file artifact 也成為 PII 儲存物、retention 跟存取控制要跟 production log 同級。</p>
<p><strong>Replay with rate adjustment（10x speed）</strong>：<code>--input-file-replay-speed 10</code>（gor format）或加 <code>--input-file-loop</code> 反覆播放。10x speed 對 capacity headroom 驗證直接有用 — 用真實 traffic shape 模擬「未來流量翻 10 倍」、避開 scripted scenario 自帶的人為偏差。反向用法 0.1x 跟 isolated request replay 適合排錯特定 endpoint 的 long-tail latency。注意 10x 會把下游 DB / cache / external API 同樣放大，sandbox target 容量要先評估。</p>
<p><strong>Middleware filter（PII redaction）</strong>：GoReplay middleware 是獨立 binary、用 stdin / stdout 跟 GoReplay process 串接、可寫任何語言。典型責任：JSON body 解析、Authorization / Cookie / Set-Cookie header strip、Email / phone / card number regex 遮罩、cross-request session ID rewriting（讓 staging 不撞 production session）。middleware 邏輯本身需要 code review、寫進版控、staging 測過再放到 production capture host。</p>
<p><strong>Pro version（GoReplay Pro - binary protocols）</strong>：開源版聚焦 HTTP/1.x；GoReplay Pro 支援 binary protocol（自家 protocol、protobuf-over-TCP、部分 gRPC pattern）跟 enterprise 維護 SLA。判斷點：若服務是純 HTTP REST 開源版夠用、若有 gRPC 或自家 binary 且不在 mesh 內、要評估 Pro 或改走 service mesh mirroring。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Capture loss / sample 不完整</strong>：libpcap 在高流量下會 drop packet、<code>gor stat</code> 的 capture stats 顯示 drop &gt; 1% 就不可信 — 加 capture host CPU、改用 PF_RING / AF_PACKET、或縮 capture filter 範圍（只 capture target port + sampling）</li>
<li><strong>TCP reassembly 失敗 / replay 結果亂碼</strong>：跨 packet 的 HTTP body 沒被正確組裝、常見於 MTU / TCP segment offload 設定異常 — 確認 capture interface 沒開 TSO / GRO、或用 application-level capture（HEC-style sidecar）取代 packet capture</li>
<li><strong>PII / secret 漏 redact 進 staging</strong>：middleware 規則沒覆蓋新加的 header / 新的 body schema — 建立 redaction allowlist（只放行已知 schema）而非 denylist、每次 schema 變更同步更新 middleware、staging 入口加 secret scanner 做 last-mile 攔截</li>
<li><strong>Replay 觸發下游真實副作用</strong>：POST / PUT 沒導 sandbox、webhook 真的打出去、payment 真的扣款 — replay target 預設 <em>deny all write</em>、白名單放行特定 idempotent endpoint、其餘走 mock 或 dry-run flag</li>
<li><strong>Replay rate 拖垮 capture host</strong>：同機 capture + replay、CPU / NIC 互相搶 — capture host 只負責 sniff + write to file、replay 機器獨立、用 gor file 解耦</li>
<li><strong>長時間 capture 寫爆 disk</strong>：未設 rotation 或 size limit — <code>--output-file</code> 加 size / time rotation、定期 archive 到 S3 + 過期刪除</li>
<li><strong>Staging 容量比 production 小、放大流量打爆</strong>：10x replay 沒先估下游 — capacity 規劃前先用 1x 暖機、觀察下游 saturation、再 ramp 到目標倍率</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>GoReplay 適合回寫 migration 與 production validation 案例。它可接 <a href="/blog/backend/09-performance-capacity/cases/tixcraft-ticketing-flash-sale-spike/" data-link-title="9.C15 拓元 Tixcraft：售票搶購的瞬間爆量架構" data-link-desc="拓元用 DynamoDB 當寫入緩衝 &#43; 傳統伺服器當慢速消費者、承受 100K&#43; 同時選位 &#43; 30 秒從 6 台擴到 800 台">9.C15 Tixcraft 售票壓測</a> 的 production-shaped load、<a href="/blog/backend/09-performance-capacity/cases/seatgeek-virtual-waiting-room/" data-link-title="9.C16 SeatGeek：DynamoDB &#43; Lambda 打造的虛擬等候室" data-link-desc="SeatGeek 用 DynamoDB 4 張表 &#43; Lambda Bouncer 實作 flash-sale 限流排隊機制、取代第三方 waiting room 服務">9.C16 SeatGeek waiting room</a> 的 cutover 前 replay、<a href="/blog/backend/09-performance-capacity/cases/netflix-aurora-consolidation/" data-link-title="9.C23 Netflix：把關聯式 DB 統一到 Aurora、效能 &#43;75%、成本 -28%" data-link-desc="Netflix 把多套關聯式 DB 統一到 Aurora、效能提升 75%、成本下降 28%、串流數十億小時">9.C23 Netflix Aurora consolidation</a> 這類資料庫整併前的 query pattern 驗證、<a href="/blog/backend/09-performance-capacity/cases/zomato-tidb-to-dynamodb-migration/" data-link-title="9.C20 Zomato：從 TiDB 遷移到 DynamoDB、吞吐 4 倍、延遲降 90%、成本減 50%" data-link-desc="Zomato 帳單系統從 TiDB 遷移到 DynamoDB、吞吐 2K→8K RPM、延遲降 90%、成本減 50%">9.C20 Zomato TiDB → DynamoDB</a> 跨 DB 遷移的請求 pattern 重播，以及 <a href="/blog/backend/09-performance-capacity/cases/microsoft-365-cosmos-db-analytics/" data-link-title="9.C30 Microsoft 365：從 MongoDB 遷移到 Cosmos DB 的分析平台" data-link-desc="Microsoft 365 把使用分析平台從 MongoDB 遷移到 Cosmos DB、planet-scale 全球分散式分析">9.C30 Microsoft 365 MongoDB → Cosmos DB</a> 的全球分析平台遷移 query 驗證。</p>
<p>這些案例的重點是 production request shape。GoReplay 頁引用案例時，要把 case 轉成 capture window、filter、rewrite、target isolation、rate limit 與 diff / saturation metric — 例如 Zomato 遷 DB 時、replay 必須先 mask PII + 改寫 SQL 方言、不能直接把 TiDB query 打進 DynamoDB SDK。</p>
<p>Capacity 規劃用 real workload model 是這些案例的共通對照啟示。Tixcraft 的售票 spike、SeatGeek 的 waiting room cutover、Netflix 的 Aurora 整併、Microsoft 365 的全球 query 分布 — 共通點是 <em>scripted scenario 無法事先列舉所有 endpoint 跟 payload 組合</em>。GoReplay 的回應是把「使用者行為建模」這個工作丟回給 production traffic 本身、規劃者只負責決定 capture window、replay rate 跟 target boundary，不再試圖窮舉 scenario。這個 mindset 才是 GoReplay 跟 <a href="/blog/backend/09-performance-capacity/vendors/k6/" data-link-title="k6" data-link-desc="用 scriptable scenario 建立 API、protocol 與 CI 友善壓測的效能工程工具">k6</a> / <a href="/blog/backend/09-performance-capacity/vendors/jmeter/" data-link-title="Apache JMeter" data-link-desc="用 GUI、plugin 與多 protocol sampler 承接企業壓測資產的效能工程工具">JMeter</a> 在 capacity 規劃流程中的真正分工點。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/09-performance-capacity/workload-modeling/" data-link-title="9.2 Workload Modeling" data-link-desc="把 production traffic shape 翻成可重播的壓測模型">9.2 Workload Modeling</a></li>
<li>上游：<a href="/blog/backend/09-performance-capacity/production-validation/" data-link-title="9.10 Production-Side 驗證" data-link-desc="shadow traffic、dark launch、canary、production-like load test">9.10 Production-Side 驗證</a></li>
<li>平行：<a href="/blog/backend/09-performance-capacity/vendors/service-mesh-mirroring/" data-link-title="Service Mesh Mirroring" data-link-desc="用 sidecar / proxy 層 mirror production traffic 到新版本或 shadow service 的 production validation 方式">Service Mesh Mirroring</a></li>
<li>平行：<a href="/blog/backend/09-performance-capacity/vendors/aws-vpc-traffic-mirroring/" data-link-title="AWS VPC Traffic Mirroring" data-link-desc="用 VPC 網路層封包鏡像觀察 production traffic 的低侵入 production validation 方式">AWS VPC Traffic Mirroring</a></li>
<li>知識卡：<a href="/blog/backend/knowledge-cards/shadow-traffic/" data-link-title="Shadow Traffic" data-link-desc="把 production traffic 複製到新版本驗證、但不返回結果給用戶的測試模式">Shadow Traffic</a></li>
<li>官方：<a href="https://docs.goreplay.org/">GoReplay documentation</a></li>
</ul>
]]></content:encoded></item><item><title>Kyverno</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/kyverno/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/kyverno/</guid><description>&lt;p>Kyverno 是 K8s-native 的 policy engine、CNCF Incubating（2024 升級）、設計 mindset 把 &lt;em>policy 寫成 YAML&lt;/em> 而不是引入新語言（vs &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/opa/" data-link-title="Open Policy Agent (OPA)" data-link-desc="CNCF general-purpose policy engine、Rego Datalog-like 語言、decoupled decision &amp;#43; enforcement、跨 K8s / API / Terraform / SQL 統一 policy">OPA&lt;/a> 的 Rego、&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &amp;#43; Constraint 兩層、Rego policy &amp;#43; Audit &amp;#43; Mutation">Gatekeeper&lt;/a> 也用 Rego）。它的核心不是「更輕量的 OPA」、而是 &lt;em>K8s 專用 policy engine&lt;/em> — 把 Validate / Mutate / Generate / Verify Images / Cleanup 五類動作做成 first-class rule type、跟 K8s admission webhook + GitOps + cosign / Sigstore ecosystem 深度整合。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Kyverno 的定位是 &lt;em>K8s admission controller-shaped policy engine、policy 用 YAML 表達&lt;/em>。底層是 dynamic admission webhook + background controller、頂層 CRD 包含 &lt;em>ClusterPolicy&lt;/em>（cluster 範圍）/ &lt;em>Policy&lt;/em>（namespace 範圍）/ &lt;em>PolicyException&lt;/em>（明確例外）/ &lt;em>ClusterCleanupPolicy&lt;/em>（過期 resource 清理）/ &lt;em>PolicyReport&lt;/em>（CIS / NIST 等審計輸出）。Nirmata 是 Kyverno 商業版、補 policy library / multi-cluster management / audit dashboard / 24x7 support。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/opa/" data-link-title="Open Policy Agent (OPA)" data-link-desc="CNCF general-purpose policy engine、Rego Datalog-like 語言、decoupled decision &amp;#43; enforcement、跨 K8s / API / Terraform / SQL 統一 policy">OPA&lt;/a> 比、Kyverno 走 &lt;em>narrow + opinionated&lt;/em> — OPA 是 general-purpose policy engine（K8s / API gateway / Terraform / 自家服務都能用、語言是 Rego）、Kyverno &lt;em>K8s-only + YAML&lt;/em>、學習成本對 K8s admin 接近零。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &amp;#43; Constraint 兩層、Rego policy &amp;#43; Audit &amp;#43; Mutation">Gatekeeper&lt;/a> 比、Gatekeeper 也是 K8s admission controller 但底層用 OPA + Rego、ConstraintTemplate / Constraint 兩層 CRD；Kyverno 不用 Rego、policy 就是 YAML rule list。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &amp;#43; Secret &amp;#43; License &amp;#43; SBOM、Apache 2.0、CI 友善">Trivy&lt;/a> 的 misconfig scan 比、Trivy 是 &lt;em>scan static manifest&lt;/em>、Kyverno 是 &lt;em>admission gate + background scan&lt;/em>、定位互補不衝突。&lt;/p></description><content:encoded><![CDATA[<p>Kyverno 是 K8s-native 的 policy engine、CNCF Incubating（2024 升級）、設計 mindset 把 <em>policy 寫成 YAML</em> 而不是引入新語言（vs <a href="/blog/backend/07-security-data-protection/vendors/opa/" data-link-title="Open Policy Agent (OPA)" data-link-desc="CNCF general-purpose policy engine、Rego Datalog-like 語言、decoupled decision &#43; enforcement、跨 K8s / API / Terraform / SQL 統一 policy">OPA</a> 的 Rego、<a href="/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &#43; Constraint 兩層、Rego policy &#43; Audit &#43; Mutation">Gatekeeper</a> 也用 Rego）。它的核心不是「更輕量的 OPA」、而是 <em>K8s 專用 policy engine</em> — 把 Validate / Mutate / Generate / Verify Images / Cleanup 五類動作做成 first-class rule type、跟 K8s admission webhook + GitOps + cosign / Sigstore ecosystem 深度整合。</p>
<h2 id="服務定位">服務定位</h2>
<p>Kyverno 的定位是 <em>K8s admission controller-shaped policy engine、policy 用 YAML 表達</em>。底層是 dynamic admission webhook + background controller、頂層 CRD 包含 <em>ClusterPolicy</em>（cluster 範圍）/ <em>Policy</em>（namespace 範圍）/ <em>PolicyException</em>（明確例外）/ <em>ClusterCleanupPolicy</em>（過期 resource 清理）/ <em>PolicyReport</em>（CIS / NIST 等審計輸出）。Nirmata 是 Kyverno 商業版、補 policy library / multi-cluster management / audit dashboard / 24x7 support。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/opa/" data-link-title="Open Policy Agent (OPA)" data-link-desc="CNCF general-purpose policy engine、Rego Datalog-like 語言、decoupled decision &#43; enforcement、跨 K8s / API / Terraform / SQL 統一 policy">OPA</a> 比、Kyverno 走 <em>narrow + opinionated</em> — OPA 是 general-purpose policy engine（K8s / API gateway / Terraform / 自家服務都能用、語言是 Rego）、Kyverno <em>K8s-only + YAML</em>、學習成本對 K8s admin 接近零。跟 <a href="/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &#43; Constraint 兩層、Rego policy &#43; Audit &#43; Mutation">Gatekeeper</a> 比、Gatekeeper 也是 K8s admission controller 但底層用 OPA + Rego、ConstraintTemplate / Constraint 兩層 CRD；Kyverno 不用 Rego、policy 就是 YAML rule list。跟 <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> 的 misconfig scan 比、Trivy 是 <em>scan static manifest</em>、Kyverno 是 <em>admission gate + background scan</em>、定位互補不衝突。</p>
<p>關鍵張力：<em>YAML policy 的表達力上限</em> ↔ <em>跨平台統一 policy 的訴求</em>。Kyverno YAML rule 對 90% K8s 場景夠用、但需要跨 K8s / API gateway / Terraform 統一 policy decision 時、Rego 的表達力跟可移植性勝出。要看清楚 policy <em>邊界是否就在 K8s 內</em>。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>Kyverno 在 K8s 治理 stack 中承擔哪一段（admission gate / mutation / generation / image verify / cleanup）、跟 <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> scan / <a href="/blog/backend/07-security-data-protection/vendors/syft-grype/" data-link-title="Syft &#43; Grype" data-link-desc="Anchore 開源姐妹工具：Syft 產 SBOM (CycloneDX / SPDX) &#43; Grype scan 漏洞、Unix philosophy、cosign attestation 整合">SBOM Tools</a> / Sigstore cosign 怎麼分工</li>
<li>ClusterPolicy / Policy 的 ownership 設計（platform team 還是 app team 寫、誰 review、PolicyException 怎麼治理）</li>
<li>Validate / Mutate / Generate / Verify Images / Cleanup 五類 rule 的使用邊界跟陷阱</li>
<li>何時用 Kyverno、何時走 OPA / Gatekeeper / K8s native ValidatingAdmissionPolicy 的取捨</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Kyverno deployment 是否健康、最少看四件事：</p>
<ul>
<li><strong>Policy 是否走 GitOps</strong>：ClusterPolicy / Policy 是否在 Git 版控、走 ArgoCD / Flux sync、policy change 是否經 PR review、staging cluster 跑過 audit mode 才 promote 到 enforce</li>
<li><strong>Mode 配置</strong>：每條 policy 是 <em>Audit</em>（只記、不擋）還是 <em>Enforce</em>（擋 admission）、新規則是否先 audit 觀察 24-48hr 再 enforce、Background scan 是否開（補 admission 不到的 historical drift）</li>
<li><strong>Verify Images 啟用度</strong>：production cluster 是否要求 image 必須通過 cosign signature verify、SBOM attestation 是否驗、policy 是否包含 keyless verify（Fulcio + Rekor）</li>
<li><strong>PolicyException 治理</strong>：例外是否走 PR 申請 + 到期日 + owner、跟 <a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">Detection Coverage and Signal Governance</a> 的 exception governance 對齊</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">7.12 供應鏈完整性</a> 邊界的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>ClusterPolicy / Policy 結構</strong>：Kyverno policy 是 K8s CRD、結構 <code>spec.rules[]</code> 一條條 rule、每條 rule 有 <code>match</code>（套用對象、kind / namespace / label / name）+ <code>exclude</code>（明確排除）+ rule body（<code>validate</code> / <code>mutate</code> / <code>generate</code> / <code>verifyImages</code> / <code>cleanup</code> 五選一）。ClusterPolicy 套整個 cluster、Policy 套單一 namespace、app team 通常只能改自家 namespace 的 Policy、平台 team 控 ClusterPolicy。</p>
<p><strong>Validate rule</strong>：admission 階段檢查 manifest 是否符合條件、不符合就拒絕。最常見場景 — 禁止 <code>latest</code> tag、要求所有 pod 有 resource limit、禁止 privileged container、要求 specific label。寫法是 <code>validate.pattern</code> 或 <code>validate.deny</code>（後者支援更複雜的 boolean expression）、output 是 admission webhook reject。Validate 是 <em>K8s policy as code</em> 的入門場景、80% 的 ClusterPolicy 都是 Validate rule。</p>
<p><strong>Mutate rule</strong>：admission 階段修改 manifest、把缺的欄位補上或改成符合的值。常見場景 — 自動注入 sidecar（service mesh proxy / log forwarder）、自動加 resource limit default、自動加 label（cost center / owner）、自動把 imagePullPolicy 改成 <code>Always</code>。Mutate 是 OPA / Gatekeeper 做不到的（兩者都偏 Validate-only）、是 Kyverno 的 <em>K8s-specific 強項</em>。陷阱是 mutate 變更後 GitOps diff 會永遠不一致、要在 ArgoCD ignoreDifferences 上對齊。</p>
<p><strong>Generate rule</strong>：cluster event（namespace 建立、resource 變動）觸發、自動建立 <em>關聯 resource</em>。最常見場景 — 新 namespace 自動建 default NetworkPolicy（deny-all egress 起手）、自動建 ResourceQuota / LimitRange、自動 copy ConfigMap / Secret 到新 namespace。Generate 是把 <em>security default</em> 從文件層落到 runtime layer、避免 app team 忘記設 NetworkPolicy 就把整個 cluster 暴露。Generate 也是 OPA / Gatekeeper 做不到、Kyverno 獨有。</p>
<p><strong>Verify Images rule</strong>：admission 階段驗證 container image 的簽章 / SBOM attestation / in-toto provenance。實作底層 <a href="https://docs.sigstore.dev/">Sigstore</a> cosign — keyless 簽章驗 Fulcio CA + Rekor transparency log、key-based 驗 public key、attestation 驗 SLSA provenance / SBOM。production 場景 — internal registry image 必須 cosign 簽 + 來自 trusted CI runner、external image 必須在 allowlist。對應 <a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/solarwinds-2020-sunburst/" data-link-title="7.R7.2.1 SolarWinds 2020：更新鏈被濫用" data-link-desc="合法更新流程遭植入後，攻擊者如何長期潛伏與橫向擴散">SolarWinds 2020 Sunburst</a> 的 supply chain attack 防禦邊界。</p>
<p><strong>Cleanup policy</strong>：ClusterCleanupPolicy / CleanupPolicy 是 K8s 1.27+ 引入、Kyverno 1.10+ 支援、按 cron 跑、清掉符合條件的 resource。常見場景 — 過 30 天的 completed Job、過 7 天的 failed Pod、ephemeral namespace（PR preview env）超過 TTL 自動刪。Cleanup 補的是 K8s 沒有 <em>resource lifecycle policy</em> 的洞、TTL controller 只覆蓋 Job / Pod 子集。</p>
<p><strong>Background scan</strong>：除了 admission 攔截 <em>新 resource</em>、Kyverno 定期掃描 <em>已存在 resource</em> 是否違反 policy、結果寫入 PolicyReport CRD。意義是補 <em>歷史 drift</em> — policy 是後來加的、已 deploy 的 resource 不會被 admission 攔到、background scan 才會找出來。production 一定要開、不開等於 policy 只防新犯不抓舊案。</p>
<p><strong>ValidatingAdmissionPolicy (VAP) 整合</strong>：K8s 1.30+ 內建 CEL-based admission policy、不需要 admission webhook（VAP 由 kube-apiserver 直接 enforce、延遲低、不會因為 Kyverno pod 掛掉就讓 admission 失敗）。Kyverno 1.11+ 可以從 ClusterPolicy <em>生成</em> VAP、把簡單 Validate rule 卸載給 K8s native engine、複雜 rule（Mutate / Generate / Verify Images）留在 Kyverno。長期趨勢 — K8s native VAP 會吃掉 Kyverno <em>Validate-only</em> 的場景、Mutate / Generate / Verify Images 仍是 Kyverno 護城河。</p>
<p><strong>GitOps 整合</strong>：ClusterPolicy / Policy 是普通 K8s CRD、走 ArgoCD / Flux sync 沒任何特殊性。staging cluster 跑 Audit mode 24-48hr 看 PolicyReport 有多少違規 → tune rule 或加 PolicyException → 確認沒誤殺再 promote 到 production cluster 的 Enforce mode。對應 <a href="/blog/backend/07-security-data-protection/blue-team/detection-engineering-lifecycle/" data-link-title="7.B5 Detection Engineering Lifecycle" data-link-desc="把偵測規則視為可維護資產，建立從來源、測試、調校到退場的完整生命週期">Detection Engineering Lifecycle</a> 的 propose → staging → promote pattern。</p>
<p><strong>Policy Reporter</strong>：OSS dashboard（不是 Kyverno 內建、是社群專案）、把 PolicyReport CRD 視覺化、給 platform team / app team 看 cluster 違規概況。Nirmata 商業版有更完整的 multi-cluster dashboard + 歷史 trend + compliance mapping（CIS / NIST / PCI）。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Kyverno</th>
          <th>OPA + Gatekeeper</th>
          <th>OPA standalone</th>
          <th>Conftest</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Policy 語言</td>
          <td>YAML（patterns / deny / preconditions）</td>
          <td>Rego（DSL、表達力強）</td>
          <td>Rego</td>
          <td>Rego</td>
      </tr>
      <tr>
          <td>覆蓋範圍</td>
          <td>K8s only</td>
          <td>K8s only</td>
          <td>K8s / API / Terraform / 任意 JSON 輸入</td>
          <td>CI-time static file（Terraform / Docker）</td>
      </tr>
      <tr>
          <td>Rule 類型</td>
          <td>Validate / Mutate / Generate / Verify Images / Cleanup</td>
          <td>Validate-only（Mutate 是 experimental）</td>
          <td>由 host application 決定</td>
          <td>Validate（CI-time）</td>
      </tr>
      <tr>
          <td>部署形態</td>
          <td>K8s admission webhook + controller</td>
          <td>K8s admission webhook（Gatekeeper 是 OPA 包）</td>
          <td>sidecar / library / standalone server</td>
          <td>CLI（CI pipeline）</td>
      </tr>
      <tr>
          <td>學習曲線</td>
          <td>緩 — K8s admin 已熟 YAML</td>
          <td>陡 — 要學 Rego</td>
          <td>陡 — 要學 Rego + host integration</td>
          <td>中 — Rego 但範圍小</td>
      </tr>
      <tr>
          <td>Image signature</td>
          <td>內建 Verify Images（cosign + Sigstore）</td>
          <td>需自己接 cosign CLI</td>
          <td>需自己接</td>
          <td>不適用</td>
      </tr>
      <tr>
          <td>Background scan</td>
          <td>內建</td>
          <td>gator audit（弱）</td>
          <td>不適用</td>
          <td>不適用</td>
      </tr>
      <tr>
          <td>跨 platform 一致</td>
          <td>弱 — K8s only</td>
          <td>弱 — K8s only</td>
          <td>強 — 同份 Rego 跑 K8s / API / Terraform</td>
          <td>強 — CI 跑同份 Rego</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>K8s-heavy + 想用 YAML + 需 Mutate / Generate / Image</td>
          <td>K8s + 已有 Rego 投資 + Validate-only</td>
          <td>跨 K8s / API / Terraform 統一 policy</td>
          <td>CI-time pre-merge 檢查</td>
      </tr>
      <tr>
          <td>退場成本</td>
          <td>中 — YAML rule 跟 K8s CRD 綁</td>
          <td>中 — Rego 可移植到 OPA standalone</td>
          <td>低 — Rego 跨平台</td>
          <td>低</td>
      </tr>
  </tbody>
</table>
<p>選 Kyverno 的核心訴求：<em>K8s-only 場景 + 不想學 Rego + 需要 Mutate / Generate / Verify Images 的 K8s-specific 能力</em>。團隊已投資 Rego ecosystem、或 policy 邊界跨 K8s + Terraform + API gateway、走 OPA / Gatekeeper 更合適。CI-time pre-merge 檢查走 Conftest 補位。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Verify Images 進階 — cosign keyless + SBOM attestation</strong>：production-grade image trust 不只驗 signature、要驗 <em>who signed it from where with what build process</em>。keyless 模式驗 Fulcio CA-issued 短期憑證 + Rekor transparency log entry、確認簽章來自 trusted CI runner 的 OIDC identity（例如 <code>https://github.com/myorg/myrepo/.github/workflows/release.yaml@refs/tags/v*</code>）。SBOM attestation 用 <code>verifyImages.attestations</code> 驗 in-toto envelope、確認 image 帶 SLSA provenance + SBOM（<a href="/blog/backend/07-security-data-protection/vendors/syft-grype/" data-link-title="Syft &#43; Grype" data-link-desc="Anchore 開源姐妹工具：Syft 產 SBOM (CycloneDX / SPDX) &#43; Grype scan 漏洞、Unix philosophy、cosign attestation 整合">CycloneDX / SPDX</a>）。對應 <a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/xz-backdoor-2024-open-source-supply-chain/" data-link-title="7.R7.2.4 XZ Backdoor 2024：開源供應鏈長期滲透" data-link-desc="開源維護鏈遭滲透後，為何會直接影響廣泛 Linux 發行流程">XZ Backdoor 2024</a> 的 lesson：maintainer takeover 也能簽 image、要靠 build provenance attestation 看出 build process 跟過去不一致。</p>
<p><strong>Mutate policy 跟 GitOps 的張力</strong>：Mutate 自動補欄位、ArgoCD / Flux 會永遠看到 live state 跟 Git state diff。處理方式有三 — <em>ignoreDifferences</em> on specific fields（ArgoCD <code>spec.ignoreDifferences</code>、Flux <code>spec.patches</code>）、<em>把 mutate 改成 validate + 在 PR template 補預設</em>（成本高但 GitOps diff 乾淨）、<em>Mutate at create only</em>（用 <code>mutate.mutateExistingOnPolicyUpdate: false</code>、只在 admission 動、不重複 mutate existing resource）。</p>
<p><strong>Generate policy 跟 multi-tenant security default</strong>：新 namespace 一建立、Generate rule 自動建 default-deny NetworkPolicy + ResourceQuota + LimitRange + 必要 RoleBinding。意義是 <em>security default 從 README 落到 runtime</em>、app team 開新 namespace 不會忘記設安全邊界。陷阱是 generated resource 的 ownership — 預設 Kyverno owns、app team 修改會被 reconcile 回去；要讓 app team 改、用 <code>synchronize: false</code>。</p>
<p><strong>Nirmata Enterprise</strong>：商業版補三件事 — <em>Policy Library</em>（CIS / NIST / PCI / SOC 2 預製 policy pack）、<em>Multi-cluster Management</em>（中央 console 推 policy 到多 cluster + audit dashboard + drift detection）、<em>Policy Reporter Plus</em>（trend + compliance mapping + JIRA / Slack integration）。對大企業多 cluster + 合規驅動的場景值得評估、中小 deployment OSS Kyverno + 社群 Policy Reporter 夠用。</p>
<p><strong>PolicyException 治理</strong>：Kyverno 1.9+ 引入 PolicyException CRD、讓特定 resource 明確繞過特定 policy、避免「app team 為了 deploy 直接把 policy 改寬」。Exception 走 PR + 到期日 + owner、跟 <a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">Detection Coverage and Signal Governance</a> 的 exception lifecycle 對齊 — 例外不是黑箱、是 <em>暫時性、有 owner、有 review 日期</em>。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Policy 改了沒生效</strong>：admission webhook 沒 ready、或 policy 寫在錯的 namespace（Policy CRD 是 namespace-scoped、放錯 namespace 不會作用）— <code>kubectl get clusterpolicies</code> 看 ready 狀態、<code>kubectl describe</code> 看 events</li>
<li><strong>Admission 卡住 / Pod 起不來</strong>：Kyverno webhook 掛掉、failurePolicy 設 <code>Fail</code> 結果整個 cluster 不能 deploy — production 對 critical workload 設 <code>failurePolicy: Ignore</code> + 監控 Kyverno controller availability、不要讓 policy engine 變成 cluster-wide SPOF</li>
<li><strong>Mutate 後 ArgoCD 永遠 OutOfSync</strong>：mutate 改的欄位沒在 ArgoCD <code>ignoreDifferences</code> 排除 — 對應加 <code>spec.ignoreDifferences[*].jsonPointers</code> 或 <code>.jqPathExpressions</code>、不然每次 sync 都跳 diff</li>
<li><strong>Verify Images 全部失敗</strong>：cluster 沒對外網路、Fulcio / Rekor 拉不到、或 image 真的沒簽 — 先 audit mode 跑 + 看 PolicyReport 統計 unsigned image 比例、確認預期路徑（內部 image 簽 / 外部 image allowlist）後才 enforce</li>
<li><strong>Background scan 跑爆 controller</strong>：cluster 太大、scan interval 太短 — 調整 <code>backgroundScan: false</code> for 高頻變動 policy、或拉長 scan interval、或 Nirmata 用分散式 scan</li>
<li><strong>PolicyException 變成漏洞</strong>：例外沒到期日、owner 離職、規則永久繞過 — Exception CRD 補 metadata（owner / expiry / ticket）+ 定期 audit 過期 Exception</li>
<li><strong>VAP migration 不一致</strong>：Kyverno 生成的 VAP 跟原 ClusterPolicy 行為有差（CEL 不支援部分 Kyverno feature）— 對 critical rule 保留 Kyverno 不 migrate、只把簡單 Validate 卸載</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>跨 K8s + API gateway + Terraform 統一 policy</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/opa/" data-link-title="Open Policy Agent (OPA)" data-link-desc="CNCF general-purpose policy engine、Rego Datalog-like 語言、decoupled decision &#43; enforcement、跨 K8s / API / Terraform / SQL 統一 policy">OPA standalone</a></td>
      </tr>
      <tr>
          <td>K8s only 但團隊已投資 Rego</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &#43; Constraint 兩層、Rego policy &#43; Audit &#43; Mutation">Gatekeeper</a></td>
      </tr>
      <tr>
          <td>CI-time pre-merge 檢查 Terraform / Dockerfile</td>
          <td>Conftest（OPA 系列、CLI-based）</td>
      </tr>
      <tr>
          <td>Image 漏洞 / misconfig scan（scan, not gate）</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> / <a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk</a></td>
      </tr>
      <tr>
          <td>SBOM 生成 / 管理</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/syft-grype/" data-link-title="Syft &#43; Grype" data-link-desc="Anchore 開源姐妹工具：Syft 產 SBOM (CycloneDX / SPDX) &#43; Grype scan 漏洞、Unix philosophy、cosign attestation 整合">SBOM Tools</a></td>
      </tr>
      <tr>
          <td>Image signing pipeline</td>
          <td>Sigstore cosign（CI 簽、Kyverno 驗）</td>
      </tr>
      <tr>
          <td>K8s 1.30+ 簡單 Validate-only 場景</td>
          <td>K8s native ValidatingAdmissionPolicy（CEL、kube-apiserver 內建）</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Kyverno policy 完整 YAML reference、JMESPath 進階用法</li>
<li>Sigstore cosign CLI 操作、Fulcio / Rekor 部署</li>
<li>Nirmata Enterprise 詳細功能跟 pricing</li>
<li>K8s ValidatingAdmissionPolicy CEL 語法 reference</li>
<li>跟 service mesh（Istio / Linkerd）整合的 sidecar injection 細節</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 Kyverno 的關係（對照啟示）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/solarwinds-2020-sunburst/" data-link-title="7.R7.2.1 SolarWinds 2020：更新鏈被濫用" data-link-desc="合法更新流程遭植入後，攻擊者如何長期潛伏與橫向擴散">SolarWinds 2020 Sunburst</a></td>
          <td>Kyverno Verify Images policy 強制 production cluster 只 deploy 已 cosign 簽章 + Rekor transparency log entry 的 image、未簽 / 來源異常 image 在 admission 階段擋掉</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/log4shell-cve-2021-44228-component-chain/" data-link-title="7.R7.2.7 Log4Shell 2021：共用元件風險與修補鏈" data-link-desc="共用元件漏洞如何同步影響多服務，並迫使團隊建立依賴治理 workflow">Log4Shell CVE-2021-44228</a></td>
          <td>Kyverno admission policy 配 <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> scan 結果 — image 帶 vulnerability label 超過閾值就擋 deploy、補 CI scan 沒攔到的舊 image</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/xz-backdoor-2024-open-source-supply-chain/" data-link-title="7.R7.2.4 XZ Backdoor 2024：開源供應鏈長期滲透" data-link-desc="開源維護鏈遭滲透後，為何會直接影響廣泛 Linux 發行流程">XZ Backdoor 2024</a></td>
          <td>Kyverno Verify Images + SBOM attestation 補位 — maintainer takeover 也能簽 image、但缺乏 SLSA build provenance attestation 會被 Kyverno admission 擋住</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">7.12 供應鏈完整性 (section)</a></td>
          <td>Kyverno 是 <em>K8s admission gate</em> 的 K8s-specific 落實工具、跟 CI-time SBOM 生成 + cosign 簽章 + Rekor transparency log 組成 supply chain trust chain 的 runtime enforcement 段</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/blue-team/detection-engineering-lifecycle/" data-link-title="7.B5 Detection Engineering Lifecycle" data-link-desc="把偵測規則視為可維護資產，建立從來源、測試、調校到退場的完整生命週期">Detection Engineering Lifecycle (section)</a></td>
          <td>ClusterPolicy / Policy 走 propose → staging audit mode → tune → promote enforce mode 的工程 lifecycle、PolicyException 是 lifecycle 一部分、不是黑箱繞過</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">7.12 供應鏈完整性</a>、<a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">Detection Coverage and Signal Governance</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/opa/" data-link-title="Open Policy Agent (OPA)" data-link-desc="CNCF general-purpose policy engine、Rego Datalog-like 語言、decoupled decision &#43; enforcement、跨 K8s / API / Terraform / SQL 統一 policy">OPA</a>、<a href="/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &#43; Constraint 兩層、Rego policy &#43; Audit &#43; Mutation">Gatekeeper</a></li>
<li>下游：<a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a>（scan + label）、<a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk</a>（vuln 資訊源）、<a href="/blog/backend/07-security-data-protection/vendors/syft-grype/" data-link-title="Syft &#43; Grype" data-link-desc="Anchore 開源姐妹工具：Syft 產 SBOM (CycloneDX / SPDX) &#43; Grype scan 漏洞、Unix philosophy、cosign attestation 整合">SBOM Tools</a>（attestation 來源）</li>
<li>跨類：Sigstore cosign（CI 簽、Kyverno 驗）、ArgoCD / Flux（GitOps sync policy 本身）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（policy violation → IR routing）</li>
<li>官方：<a href="https://kyverno.io/docs/">Kyverno Documentation</a>、<a href="https://docs.sigstore.dev/">Sigstore Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>Service Mesh Mirroring</title><link>https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/service-mesh-mirroring/</link><pubDate>Fri, 15 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/service-mesh-mirroring/</guid><description>&lt;p>Service mesh mirroring 的核心責任是在 proxy 層複製 production traffic 到 shadow service，讓新版本接受真實請求形狀，同時把使用者回應留在原本路徑。它適合已經落地 Istio、Linkerd 或類似 mesh 的平台，重點在用 routing policy 控制 mirror ratio、target、隔離與觀測。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/goreplay/" data-link-title="GoReplay" data-link-desc="用 production HTTP traffic capture 與 replay 驗證真實請求形狀的效能工程工具">GoReplay&lt;/a> 比、Service Mesh Mirroring 在 &lt;em>proxy / sidecar&lt;/em> 層、是 K8s mesh-native 的 L7 HTTP request mirror、不需要 application 或 host 端 capture binary；GoReplay 在 &lt;em>application host&lt;/em> 層、適合無 mesh 的環境或要 capture artifact 離線 replay。跟 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/aws-vpc-traffic-mirroring/" data-link-title="AWS VPC Traffic Mirroring" data-link-desc="用 VPC 網路層封包鏡像觀察 production traffic 的低侵入 production validation 方式">AWS VPC Traffic Mirroring&lt;/a> 比、Service Mesh Mirroring 在 L7（HTTP route / header / subset 可控）、VPC Traffic Mirroring 在 L3-L4 packet 層、見度更底層但缺 application 語意。三者組合常見於 K8s + 多 cloud 混合環境。&lt;/p>
&lt;h2 id="最短判讀路徑">最短判讀路徑&lt;/h2>
&lt;p>判斷 Service Mesh Mirroring 部署是否健康、最少看四件事：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Mesh implementation 對齊&lt;/strong>：用哪套 mesh（Istio / Linkerd / Envoy gateway / Consul Connect）、control plane 版本、sidecar injection coverage、跨 namespace policy 邊界是否清楚&lt;/li>
&lt;li>&lt;strong>VirtualService mirror config&lt;/strong>：mirror destination 是否限制在同 namespace / 同 cluster、mirror_percent 是否從 1% 漸進、route / header filter 是否排除 write-heavy 或 PII path&lt;/li>
&lt;li>&lt;strong>Target service capacity&lt;/strong>：shadow target deployment 是否有獨立 HPA、跟 primary 同 node pool 還是隔離、DB / cache / external API 是否導 mock 或 sandbox、不會 share connection pool 造成 primary 飽和&lt;/li>
&lt;li>&lt;strong>Response handling&lt;/strong>：mirrored response 是 fire-and-forget（Istio 預設）還是有 logging、shadow 端是否能辨識 mirrored request（&lt;code>X-Envoy-Internal&lt;/code> / custom header）、side effect（payment / notification / webhook）是否走 dry-run&lt;/li>
&lt;/ul>
&lt;p>四件事任一缺失、就是 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/production-validation/" data-link-title="9.10 Production-Side 驗證" data-link-desc="shadow traffic、dark launch、canary、production-like load test">9.10 Production-Side 驗證&lt;/a> shadow traffic 治理的待補項目。&lt;/p></description><content:encoded><![CDATA[<p>Service mesh mirroring 的核心責任是在 proxy 層複製 production traffic 到 shadow service，讓新版本接受真實請求形狀，同時把使用者回應留在原本路徑。它適合已經落地 Istio、Linkerd 或類似 mesh 的平台，重點在用 routing policy 控制 mirror ratio、target、隔離與觀測。</p>
<p>跟 <a href="/blog/backend/09-performance-capacity/vendors/goreplay/" data-link-title="GoReplay" data-link-desc="用 production HTTP traffic capture 與 replay 驗證真實請求形狀的效能工程工具">GoReplay</a> 比、Service Mesh Mirroring 在 <em>proxy / sidecar</em> 層、是 K8s mesh-native 的 L7 HTTP request mirror、不需要 application 或 host 端 capture binary；GoReplay 在 <em>application host</em> 層、適合無 mesh 的環境或要 capture artifact 離線 replay。跟 <a href="/blog/backend/09-performance-capacity/vendors/aws-vpc-traffic-mirroring/" data-link-title="AWS VPC Traffic Mirroring" data-link-desc="用 VPC 網路層封包鏡像觀察 production traffic 的低侵入 production validation 方式">AWS VPC Traffic Mirroring</a> 比、Service Mesh Mirroring 在 L7（HTTP route / header / subset 可控）、VPC Traffic Mirroring 在 L3-L4 packet 層、見度更底層但缺 application 語意。三者組合常見於 K8s + 多 cloud 混合環境。</p>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Service Mesh Mirroring 部署是否健康、最少看四件事：</p>
<ul>
<li><strong>Mesh implementation 對齊</strong>：用哪套 mesh（Istio / Linkerd / Envoy gateway / Consul Connect）、control plane 版本、sidecar injection coverage、跨 namespace policy 邊界是否清楚</li>
<li><strong>VirtualService mirror config</strong>：mirror destination 是否限制在同 namespace / 同 cluster、mirror_percent 是否從 1% 漸進、route / header filter 是否排除 write-heavy 或 PII path</li>
<li><strong>Target service capacity</strong>：shadow target deployment 是否有獨立 HPA、跟 primary 同 node pool 還是隔離、DB / cache / external API 是否導 mock 或 sandbox、不會 share connection pool 造成 primary 飽和</li>
<li><strong>Response handling</strong>：mirrored response 是 fire-and-forget（Istio 預設）還是有 logging、shadow 端是否能辨識 mirrored request（<code>X-Envoy-Internal</code> / custom header）、side effect（payment / notification / webhook）是否走 dry-run</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/09-performance-capacity/production-validation/" data-link-title="9.10 Production-Side 驗證" data-link-desc="shadow traffic、dark launch、canary、production-like load test">9.10 Production-Side 驗證</a> shadow traffic 治理的待補項目。</p>
<h2 id="定位">定位</h2>
<p>Service mesh mirroring 適合平台已經有 proxy control plane 的團隊。當 service-to-service traffic 都經過 sidecar 或 gateway，mirror policy 可以把部分 production request 複製到新版本，不需要在 application code 中加 capture / replay 邏輯。</p>
<p>這個定位讓 service mesh mirroring 接到 <a href="/blog/backend/09-performance-capacity/production-validation/" data-link-title="9.10 Production-Side 驗證" data-link-desc="shadow traffic、dark launch、canary、production-like load test">9.10 Production-Side 驗證</a> 的 shadow traffic 與 canary perf check。它比 host capture 更貼近 service routing，但也依賴 mesh 的觀測、policy、資源隔離與治理能力。</p>
<h2 id="適用場景">適用場景</h2>
<p>新版本 shadow validation 適合 service mesh mirroring。平台可以把 1%、5% 或特定 route 的流量 mirror 到 shadow deployment，觀察新版本 CPU、memory、latency、DB read 與 error。</p>
<p>Service-to-service migration 適合 service mesh mirroring。當下游服務準備換 runtime、framework、DB client 或 cache client，mirror 可以讓新路徑吃到 production upstream pattern。</p>
<p>多 region / 多 version 對照適合 service mesh mirroring。Mesh policy 能按 namespace、host、route、header 或 subset 控制 mirror target，讓平台在小 blast radius 下收集 production-shaped evidence。</p>
<h2 id="選型判準">選型判準</h2>
<table>
  <thead>
      <tr>
          <th>判準</th>
          <th>Service mesh mirroring 的價值</th>
          <th>需要補的能力</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Proxy 層控制</td>
          <td>mirror policy 不侵入 application code</td>
          <td>mesh control plane 治理與變更審核</td>
      </tr>
      <tr>
          <td>Service routing</td>
          <td>可按 host、route、subset 控制 target</td>
          <td>route 命名、ownership、policy drift</td>
      </tr>
      <tr>
          <td>Mesh observability</td>
          <td>request metric、trace、service graph 可對照</td>
          <td>shadow target 的獨立 dashboard</td>
      </tr>
      <tr>
          <td>漸進比例</td>
          <td>mirror ratio 可逐步放大</td>
          <td>下游容量與 stop condition</td>
      </tr>
  </tbody>
</table>
<p>Proxy 層控制價值來自一致性。當所有 service 都走 mesh，mirror policy 可以用同一套控制面管理，避免每個 application 自行實作 replay。</p>
<p>Mesh observability 價值來自對照能力。Shadow service 的 latency、error、resource saturation 與 dependency call 可以直接跟 primary path 對比，但 dashboard 要清楚標記 mirrored traffic，避免混入正式 SLO。</p>
<h2 id="跟其他方式的取捨">跟其他方式的取捨</h2>
<p>Service mesh mirroring 和 GoReplay 的主要差異是控制面。Service mesh mirroring 依賴既有 proxy / mesh，適合服務間流量；GoReplay 適合 HTTP capture artifact、離線 replay 與沒有 mesh 的環境。</p>
<p>Service mesh mirroring 和 AWS VPC Traffic Mirroring 的主要差異是語意層級。Mesh 在 L7 routing 層，能按 route、host、header 與 subset 控制；VPC mirroring 在網路層，能見度更底層但應用語意控制較少。</p>
<p>Service mesh mirroring 和 canary 的主要差異是使用者影響。Mirrored request 的回應不回給使用者，適合 capacity / correctness observation；canary 會讓真實使用者走新版本，適合最終放量。</p>
<h2 id="操作成本">操作成本</h2>
<p>Service mesh mirroring 的主要成本是下游容量。Shadow traffic 雖然不回應使用者，但仍會消耗 shadow service、DB、cache、third-party mock、queue 與 observability pipeline 的資源。</p>
<p>Policy 成本來自控制面治理。Mirror rule、route、subset、namespace、owner 與 rollout window 都要可審查；錯誤的 mirror policy 可能把過大比例流量導到未準備好的 target。</p>
<p>Side effect 成本來自 application 行為。Shadow service 要能辨識 mirrored request，並把 write、external API call、notification、payment 與 queue publish 導到 sandbox、mock 或 dry-run。</p>
<h2 id="evidence-package">Evidence Package</h2>
<p>Service mesh mirroring 結果應回寫到 evidence package。最小欄位包括 mesh policy version、source service、route、mirror ratio、target subset、time range、shadow target resource、data / side effect isolation、p95 / p99、error rate、dependency saturation、known gap 與 owner。</p>
<table>
  <thead>
      <tr>
          <th>欄位</th>
          <th>Service mesh mirroring 證據來源</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Source</td>
          <td>mesh policy、route config、deployment version</td>
      </tr>
      <tr>
          <td>Time range</td>
          <td>mirror start / end</td>
      </tr>
      <tr>
          <td>Query link</td>
          <td>service graph、metrics、trace、logs</td>
      </tr>
      <tr>
          <td>Data quality</td>
          <td>mirror ratio、route coverage、header filter</td>
      </tr>
      <tr>
          <td>Confidence</td>
          <td>target parity、dependency isolation</td>
      </tr>
      <tr>
          <td>Known gap</td>
          <td>未 mirror route、side effect mock、mesh overhead</td>
      </tr>
  </tbody>
</table>
<p>Evidence package 的核心用途是讓 mirror 實驗可關閉。Reviewer 要能看到 mirror policy 何時啟動、何時停止、覆蓋哪些 route、消耗哪些下游資源，以及 shadow target 是否接近 production。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Istio VirtualService mirror / mirror_percent</strong>：Istio 用 <code>VirtualService</code> 的 <code>mirror</code> 欄位指定 shadow destination、<code>mirrorPercentage</code>（v1.7+；舊版 <code>mirror_percent</code>）控制比例。production 操作慣例是從 1% 起步、每 30-60min 觀察 shadow target latency / error / saturation 再放大、達到 100% 後維持一週收 evidence 才 promote。route-level config 比 mesh-wide policy 安全、blast radius 限定在指定 host / path。</p>
<p><strong>Linkerd traffic split</strong>：Linkerd 用 SMI <code>TrafficSplit</code> CRD 或 native <code>HTTPRoute</code> 分流、走 <em>active-active</em> shadow 模式而非 fire-and-forget。Linkerd mirror 預設較輕量、proxy overhead 比 Istio 低、適合資源敏感的 K8s cluster；但 L7 policy 表達力不如 Istio EnvoyFilter。</p>
<p><strong>Envoy MirrorPolicy</strong>：直接寫 Envoy config（不透過 Istio control plane）時、<code>route.RouteAction.request_mirror_policies</code> 是底層 primitive。多 cluster 邊緣 gateway（Contour / Emissary-Ingress / Gloo）都是這層的 abstraction、適合不想引入 full Istio 但要 mirror 能力的場景。</p>
<p><strong>跟 Argo Rollouts canary 整合 — shadow deployment</strong>：Argo Rollouts 的 <code>analysis</code> step 可以接 mesh mirror — <em>shadow stage</em> 先用 mirror 收 evidence、<em>canary stage</em> 才放真實流量。對應 <a href="/blog/backend/09-performance-capacity/production-validation/" data-link-title="9.10 Production-Side 驗證" data-link-desc="shadow traffic、dark launch、canary、production-like load test">9.10 Production-Side 驗證</a> 的「shadow 先於 canary」原則、避免把使用者當小白鼠。</p>
<p><strong>跟 <a href="/blog/backend/04-observability/vendors/datadog/" data-link-title="Datadog" data-link-desc="All-in-one SaaS 觀測平台、APM / Logs / Metrics / RUM / Security">Datadog</a> APM trace correlation</strong>：mirrored request 應該有獨立的 trace tag（<code>env:shadow</code> 或 <code>traffic.mirror:true</code>）、讓 Datadog APM / <a href="/blog/backend/04-observability/" data-link-title="模組四：可觀測性平台" data-link-desc="整理 log、metric、trace、dashboard 與 alert 的後端操作實務">observability stack</a> 能 filter 出 shadow path 的 p95 / error rate、不混入 primary SLO dashboard。trace propagation header 要保留、否則 distributed trace 斷在 mesh 邊界。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Mirror target capacity 不足 / shadow service OOM</strong>：shadow deployment 沒獨立 HPA、跟 primary 共用 node pool — 拆 node pool、shadow 設獨立 resource request、mirror_percent 從 1% 起步</li>
<li><strong>Mirrored response 漏處理（fire-and-forget 副作用）</strong>：Istio 預設丟棄 mirrored response、shadow 端的 error 沒被 collect — shadow service 自己 emit metric / log、不依賴 mirror response、加 <code>X-Shadow-Request</code> header 讓 shadow 端可辨識並走 dry-run 路徑</li>
<li><strong>PII / sensitive data 進 staging</strong>：mirrored request 帶真實 user token / payment info 打到 staging — header / body filter 走 EnvoyFilter 做 PII redaction、或在 mesh 邊界跑 <a href="/blog/backend/07-security-data-protection/" data-link-title="模組七：資安與資料保護" data-link-desc="以問題驅動方式擴充資安知識網：先定義服務環節問題，再以案例作為觸發式參考">data masking proxy</a> 再 mirror</li>
<li><strong>Side effect 真的發生（payment double charge / notification 真寄）</strong>：shadow service 沒辨識 mirrored request 就走正式邏輯 — 強制 shadow 端用 sandbox credential、external API client 走 mock / dry-run mode、write 改 read-only replica</li>
<li><strong>Mesh control plane 飽和 / mirror policy drift</strong>：mirror rule 散落各 namespace 沒 owner、policy version 不一致 — 走 GitOps（Argo CD / Flux）+ policy as code、定期 audit <code>kubectl get virtualservice -A</code></li>
<li><strong>Cross-cluster mirror blast radius 失控</strong>：mirror destination 指向其他 cluster 導致跨 cluster 流量爆增 — mirror destination 限 same-cluster、跨 cluster 要走獨立的 gateway 並設 quota</li>
<li><strong>Shadow trace 混進 SLO dashboard</strong>：APM 沒分 primary / shadow tag、p95 看起來變差但其實是 shadow 拖累 — trace tag <code>env:shadow</code> 強制、observability dashboard filter</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>無 mesh 環境 / 要 capture artifact 離線重播</td>
          <td><a href="/blog/backend/09-performance-capacity/vendors/goreplay/" data-link-title="GoReplay" data-link-desc="用 production HTTP traffic capture 與 replay 驗證真實請求形狀的效能工程工具">GoReplay</a></td>
      </tr>
      <tr>
          <td>L3-L4 packet 層分析（IDS / network forensic）</td>
          <td><a href="/blog/backend/09-performance-capacity/vendors/aws-vpc-traffic-mirroring/" data-link-title="AWS VPC Traffic Mirroring" data-link-desc="用 VPC 網路層封包鏡像觀察 production traffic 的低侵入 production validation 方式">AWS VPC Traffic Mirroring</a></td>
      </tr>
      <tr>
          <td>合成負載 / load test 而非 production mirror</td>
          <td><a href="/blog/backend/09-performance-capacity/vendors/k6/" data-link-title="k6" data-link-desc="用 scriptable scenario 建立 API、protocol 與 CI 友善壓測的效能工程工具">k6</a> / <a href="/blog/backend/09-performance-capacity/vendors/gatling/" data-link-title="Gatling" data-link-desc="用 JVM DSL、simulation 與 injection profile 表達複雜 scenario 的效能工程工具">Gatling</a></td>
      </tr>
      <tr>
          <td>Production-side 整體治理</td>
          <td><a href="/blog/backend/09-performance-capacity/production-validation/" data-link-title="9.10 Production-Side 驗證" data-link-desc="shadow traffic、dark launch、canary、production-like load test">9.10 Production-Side 驗證</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Istio / Linkerd / Envoy 完整 install / 升級 / control plane HA 細節</li>
<li>Service mesh 安全模型（mTLS / SPIFFE / authorization policy）— 屬 <a href="/blog/backend/07-security-data-protection/" data-link-title="模組七：資安與資料保護" data-link-desc="以問題驅動方式擴充資安知識網：先定義服務環節問題，再以案例作為觸發式參考">7 security</a> 邊界</li>
<li>Mesh-level retry / timeout / circuit breaker 等 resilience pattern</li>
<li>Multi-cluster mesh federation（Istio multi-primary、Linkerd multicluster）</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>Service mesh mirroring 適合回寫平台遷移與新版本 shadow validation 案例。它可接 <a href="/blog/backend/05-deployment-platform/cases/miro-managed-eks-migration/" data-link-title="5.C5 Miro：Managed EKS 遷移" data-link-desc="從自維運平台轉向 managed EKS 的組織與技術協同案例。">Miro managed EKS migration</a>、<a href="/blog/backend/05-deployment-platform/cases/tradeshift-self-managed-k8s-to-eks/" data-link-title="5.C1 Tradeshift：self-managed Kubernetes 遷移到 EKS" data-link-desc="零停機平台遷移的分段策略案例。">Tradeshift self-managed K8s to EKS</a>、<a href="/blog/backend/09-performance-capacity/cases/fanduel-dual-peak-betting-streaming/" data-link-title="9.C28 FanDuel：體育直播 &#43; 投注的雙重峰值" data-link-desc="FanDuel 3.5M MAU、Super Bowl 期間擴容 5-10 倍、用 AWS Local Zones &#43; Wavelength &#43; Outposts 處理 20&#43; 州的雙重峰值">9.C28 FanDuel 雙峰 workload</a> 的逐步驗證需求、<a href="/blog/backend/09-performance-capacity/cases/riot-games-eks-multi-cluster/" data-link-title="9.C12 Riot Games：246 個 EKS cluster 的多遊戲多地區治理" data-link-desc="Riot Games 從 Mesos 遷移到 EKS、用 246 個 cluster 跨遊戲跨地區治理、年省 1000 萬美金">9.C12 Riot Games 246 EKS cluster</a> 的 single-tenant per game 跨 cluster 流量 shadow，以及 <a href="/blog/backend/09-performance-capacity/cases/lyft-microservice-eight-x-peak/" data-link-title="9.C7 Lyft：100&#43; 微服務在 8 倍峰值下的 Auto Scaling" data-link-desc="Lyft 用 AWS Auto Scaling 跨 100&#43; 個微服務承載 8 倍峰值流量、跨 200&#43; 城市">9.C7 Lyft 100+ 微服務</a> 跨服務的 mirror 範圍治理。</p>
<p>這些案例的重點是 routing policy 與 blast radius。Service mesh mirroring 頁引用案例時，要把 case 轉成 route、mirror ratio、target subset、dependency isolation 與 abort condition — 例如 Riot Games 的 single-tenant 模式下、mirror policy 必須限制在 <em>同遊戲</em> cluster 內、不能跨 game 否則 blast radius 失控。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/09-performance-capacity/production-validation/" data-link-title="9.10 Production-Side 驗證" data-link-desc="shadow traffic、dark launch、canary、production-like load test">9.10 Production-Side 驗證</a></li>
<li>上游：<a href="/blog/backend/05-deployment-platform/traffic-config-control-plane-boundary/" data-link-title="5.7 Traffic、Config 與 Control Plane Boundary" data-link-desc="說明流量、設定、secret、service discovery 與管理面如何分責任與回退。">5.6 Traffic, Config and Control Plane Boundary</a></li>
<li>平行：<a href="/blog/backend/09-performance-capacity/vendors/goreplay/" data-link-title="GoReplay" data-link-desc="用 production HTTP traffic capture 與 replay 驗證真實請求形狀的效能工程工具">GoReplay</a></li>
<li>平行：<a href="/blog/backend/09-performance-capacity/vendors/aws-vpc-traffic-mirroring/" data-link-title="AWS VPC Traffic Mirroring" data-link-desc="用 VPC 網路層封包鏡像觀察 production traffic 的低侵入 production validation 方式">AWS VPC Traffic Mirroring</a></li>
<li>知識卡：<a href="/blog/backend/knowledge-cards/shadow-traffic/" data-link-title="Shadow Traffic" data-link-desc="把 production traffic 複製到新版本驗證、但不返回結果給用戶的測試模式">Shadow Traffic</a></li>
</ul>
]]></content:encoded></item><item><title>Vantage</title><link>https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/vantage/</link><pubDate>Fri, 15 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/vantage/</guid><description>&lt;p>Vantage 是 &lt;em>modern multi-cloud FinOps SaaS&lt;/em>、2020 年由 Heroku ex-founder 創立。它的核心責任是把雲端帳單轉成工程團隊能追蹤的 cost report、allocation、forecast 與 efficiency metric。它跟 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/cloudhealth/" data-link-title="CloudHealth" data-link-desc="用 enterprise FinOps governance、policy 與多雲成本管理支援大型組織的容量成本治理">CloudHealth&lt;/a>、Apptio Cloudability、&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/aws-cost-explorer/" data-link-title="AWS Cost Explorer" data-link-desc="用 AWS-native 成本與用量分析建立 account、service、tag 與 usage type 的成本判讀入口">AWS Cost Explorer&lt;/a> 同層、但賣點是 &lt;em>developer-friendly UI + 直覺定價 + 多雲 connector 一鍵啟用&lt;/em> — 適合工程團隊自助而非走 FinOps 部門申請的組織。&lt;/p>
&lt;p>它適合多 account、多 provider、Kubernetes 與 shared infrastructure 成本需要分攤到 service、team、namespace、label 或 resource 的組織。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Vantage 的差異在 &lt;em>使用者體驗與切入角度&lt;/em>、指標本身跟同類工具相近。CloudHealth / Apptio 是傳統 enterprise FinOps platform、面向 procurement、CFO、FinOps governance team；Vantage 把入口換成工程團隊 — 報表能直接 share URL、UI 接近 observability dashboard、connector 走 self-service onboarding 而非 SOW + professional service。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/cloudhealth/" data-link-title="CloudHealth" data-link-desc="用 enterprise FinOps governance、policy 與多雲成本管理支援大型組織的容量成本治理">CloudHealth&lt;/a> 比、Vantage &lt;em>淺但快上手&lt;/em>、適合 100 - 1000 人工程組織自助 FinOps；CloudHealth 走 enterprise governance、policy engine、approval workflow 更深、適合 5000+ 員工跨 BU 治理。跟 Apptio Cloudability 比、定位類似 CloudHealth、但 Apptio 把成本接到 TBM（Technology Business Management）frame、適合需要把 IT 成本對到 business service / product P&amp;amp;L 的組織。跟 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/aws-cost-explorer/" data-link-title="AWS Cost Explorer" data-link-desc="用 AWS-native 成本與用量分析建立 account、service、tag 與 usage type 的成本判讀入口">AWS Cost Explorer&lt;/a> 比、Cost Explorer 是 AWS-only 入口、免費但只有 AWS、跨 provider / Kubernetes / SaaS spend 看不到；Vantage 把 AWS + GCP + Azure + Snowflake + Databricks + Datadog + Fastly 等串成單一視圖。&lt;/p>
&lt;p>關鍵張力：&lt;em>modern SaaS 速度&lt;/em> ↔ &lt;em>enterprise governance 深度&lt;/em> 是 Vantage 的核心定位 trade-off。要 procurement-grade workflow、approval chain、custom data warehouse export 走 CloudHealth / Apptio；要工程 owner 直接打開 dashboard 看 cost trend、5 分鐘加新 connector 走 Vantage。&lt;/p></description><content:encoded><![CDATA[<p>Vantage 是 <em>modern multi-cloud FinOps SaaS</em>、2020 年由 Heroku ex-founder 創立。它的核心責任是把雲端帳單轉成工程團隊能追蹤的 cost report、allocation、forecast 與 efficiency metric。它跟 <a href="/blog/backend/09-performance-capacity/vendors/cloudhealth/" data-link-title="CloudHealth" data-link-desc="用 enterprise FinOps governance、policy 與多雲成本管理支援大型組織的容量成本治理">CloudHealth</a>、Apptio Cloudability、<a href="/blog/backend/09-performance-capacity/vendors/aws-cost-explorer/" data-link-title="AWS Cost Explorer" data-link-desc="用 AWS-native 成本與用量分析建立 account、service、tag 與 usage type 的成本判讀入口">AWS Cost Explorer</a> 同層、但賣點是 <em>developer-friendly UI + 直覺定價 + 多雲 connector 一鍵啟用</em> — 適合工程團隊自助而非走 FinOps 部門申請的組織。</p>
<p>它適合多 account、多 provider、Kubernetes 與 shared infrastructure 成本需要分攤到 service、team、namespace、label 或 resource 的組織。</p>
<h2 id="服務定位">服務定位</h2>
<p>Vantage 的差異在 <em>使用者體驗與切入角度</em>、指標本身跟同類工具相近。CloudHealth / Apptio 是傳統 enterprise FinOps platform、面向 procurement、CFO、FinOps governance team；Vantage 把入口換成工程團隊 — 報表能直接 share URL、UI 接近 observability dashboard、connector 走 self-service onboarding 而非 SOW + professional service。</p>
<p>跟 <a href="/blog/backend/09-performance-capacity/vendors/cloudhealth/" data-link-title="CloudHealth" data-link-desc="用 enterprise FinOps governance、policy 與多雲成本管理支援大型組織的容量成本治理">CloudHealth</a> 比、Vantage <em>淺但快上手</em>、適合 100 - 1000 人工程組織自助 FinOps；CloudHealth 走 enterprise governance、policy engine、approval workflow 更深、適合 5000+ 員工跨 BU 治理。跟 Apptio Cloudability 比、定位類似 CloudHealth、但 Apptio 把成本接到 TBM（Technology Business Management）frame、適合需要把 IT 成本對到 business service / product P&amp;L 的組織。跟 <a href="/blog/backend/09-performance-capacity/vendors/aws-cost-explorer/" data-link-title="AWS Cost Explorer" data-link-desc="用 AWS-native 成本與用量分析建立 account、service、tag 與 usage type 的成本判讀入口">AWS Cost Explorer</a> 比、Cost Explorer 是 AWS-only 入口、免費但只有 AWS、跨 provider / Kubernetes / SaaS spend 看不到；Vantage 把 AWS + GCP + Azure + Snowflake + Databricks + Datadog + Fastly 等串成單一視圖。</p>
<p>關鍵張力：<em>modern SaaS 速度</em> ↔ <em>enterprise governance 深度</em> 是 Vantage 的核心定位 trade-off。要 procurement-grade workflow、approval chain、custom data warehouse export 走 CloudHealth / Apptio；要工程 owner 直接打開 dashboard 看 cost trend、5 分鐘加新 connector 走 Vantage。</p>
<h2 id="定位">定位</h2>
<p>Vantage 適合把 cost attribution 帶進容量規劃流程。當團隊已經能用 workload model 描述流量，下一步要知道每個 workload、namespace、database、cache、region 與 account 對成本曲線的影響，Vantage 可以把雲端費用整理成可查詢、可分組、可預測的報表。</p>
<p>這個定位讓 Vantage 接到三個主章。它從 <a href="/blog/backend/09-performance-capacity/cost-engineering/" data-link-title="9.7 成本邊界與 efficiency" data-link-desc="cost per request、cost curve、降級成本、over-provisioning trade-off">9.7 成本邊界與 efficiency</a> 接收 cost per request 與 over-provision waste，從 <a href="/blog/backend/09-performance-capacity/performance-observability/" data-link-title="9.8 效能可觀測性" data-link-desc="saturation metric、USE / RED method、cost dashboard">9.8 效能可觀測性</a> 接收 dashboard 與 ownership 訊號，從 <a href="/blog/backend/04-observability/cost-attribution/" data-link-title="4.15 Cost Attribution / Chargeback" data-link-desc="把 observability 成本拆到團隊、產品、環境維度">04 可觀測性成本歸因</a> 接收 tag、label 與 attribution vocabulary。</p>
<h2 id="適用場景">適用場景</h2>
<p>Showback 與 chargeback 是 Vantage 的主要入口。當平台成本散在 shared Kubernetes cluster、managed database、network egress、storage 與 support plan 裡，Cost Reports 可以把費用依 team、service、environment 或 business unit 切開，讓討論從總帳單轉成 owner action。</p>
<p>Kubernetes 成本分析適合用 Vantage 補足平台可見性。Namespace、label、service、pod、CPU、RAM、storage 與 GPU 維度能讓團隊看到 idle cost、resource efficiency 與 rightsizing recommendation，特別適合多租戶平台。</p>
<p>Forecast 與 anomaly review 適合日常成本治理。每月 forecast、cost trend、unexpected spike 與 budget drift 可以接到 engineering review，讓容量調整、release、marketing event 與成本變化在同一個時間軸上被討論。</p>
<h2 id="選型判準">選型判準</h2>
<table>
  <thead>
      <tr>
          <th>判準</th>
          <th>Vantage 的價值</th>
          <th>需要補的能力</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Cost allocation</td>
          <td>依 provider、account、resource、Kubernetes label 分攤</td>
          <td>tag / label policy、owner taxonomy</td>
      </tr>
      <tr>
          <td>Kubernetes 成本</td>
          <td>namespace、service、label 與 pod-level efficiency</td>
          <td>agent rollout、cluster mapping</td>
      </tr>
      <tr>
          <td>Forecast</td>
          <td>成本趨勢與月末預測可接 review 節奏</td>
          <td>事件註記、release marker、業務日曆</td>
      </tr>
      <tr>
          <td>工程入口</td>
          <td>報表可讓 service owner 直接查詢與追蹤</td>
          <td>action workflow、remediation ownership</td>
      </tr>
  </tbody>
</table>
<p>Cost allocation 價值來自 owner 明確。總帳單只能告訴組織花了多少錢；service-level report 才能讓工程團隊知道哪個 workload、region、database 或 network path 改變了成本。</p>
<p>Kubernetes 成本價值來自 shared cluster 拆分。多租戶平台常把多個服務塞進同一組 node pool；Vantage 類工具把 pod lifecycle 與底層基礎設施成本接起來，讓 namespace 或 label 變成成本討論單位。</p>
<p>Forecast 價值來自提前介入。成本 review 如果只看月底結果，容量浪費和異常用量已經發生；forecast 和 anomaly 讓團隊在月中就能調整 resource request、replica、reserved capacity 或 release plan。</p>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Vantage deployment 是否健康、最少看四件事：</p>
<ul>
<li><strong>Multi-cloud connector coverage</strong>：AWS / GCP / Azure / Snowflake / Datadog / Fastly 等 connector 是否都接上 — 缺一個就有成本盲區、缺了 Snowflake 反而比缺了 AWS 痛（query cost 沒人看）</li>
<li><strong>Cost Report 設計</strong>：是否依 service / team / environment / business unit 切出可 share 的 saved report、URL 是否進 wiki / Slack canonical 位置、誰每週看</li>
<li><strong>Anomaly Detection 設定</strong>：threshold 跟 baseline 是否 tune 過、false positive rate、anomaly 出現後是否有 owner 接、不是只進 email spam</li>
<li><strong>Report sharing 機制</strong>：cost report 是否走 read-only URL share 給工程 owner、不是把每個工程師都拉進 Vantage account；team 是否有 cost retrospective 節奏</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/09-performance-capacity/cost-engineering/" data-link-title="9.7 成本邊界與 efficiency" data-link-desc="cost per request、cost curve、降級成本、over-provisioning trade-off">9.7 成本邊界與 efficiency</a> 邊界的待補項目。</p>
<h2 id="跟其他工具的取捨">跟其他工具的取捨</h2>
<p>Vantage 和 Akamas 的主要差異是決策深度。Vantage 讓團隊看清成本、分攤責任與找出浪費；Akamas 更進一步把 workload constraint 與 configuration tuning 接成 optimization loop。</p>
<p>Vantage 和 CloudHealth 的主要差異是組織重心。Vantage 偏工程團隊可直接使用的 cost reports、Kubernetes 成本與 resource-level 分析；CloudHealth 偏 enterprise FinOps governance、policy 與大組織流程。</p>
<p>Vantage 和 AWS Cost Explorer 的主要差異是範圍。AWS Cost Explorer 是 AWS-native 入口；Vantage 適合跨 provider、Kubernetes 與多 workspace 的成本視圖。</p>
<h3 id="核心取捨表">核心取捨表</h3>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Vantage</th>
          <th>CloudHealth</th>
          <th>Apptio Cloudability</th>
          <th>AWS Cost Explorer</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>使用者重心</td>
          <td>工程 owner 自助</td>
          <td>FinOps / procurement team</td>
          <td>FinOps + business / product owner</td>
          <td>AWS account holder</td>
      </tr>
      <tr>
          <td>多雲覆蓋</td>
          <td>AWS + GCP + Azure + 主要 SaaS connector</td>
          <td>AWS + GCP + Azure 完整 + policy engine</td>
          <td>AWS + GCP + Azure + on-prem (TBM frame)</td>
          <td>AWS only</td>
      </tr>
      <tr>
          <td>Onboarding 速度</td>
          <td>快 — connector self-service、分鐘級</td>
          <td>慢 — SOW + professional service</td>
          <td>慢 — TBM mapping + implementation</td>
          <td>即用（AWS-native）</td>
      </tr>
      <tr>
          <td>報表分享</td>
          <td>強 — URL share、read-only viewer 免費</td>
          <td>中 — 走 RBAC、外部分享受限</td>
          <td>中 — 走 TBM portal</td>
          <td>弱 — 限 AWS console viewer</td>
      </tr>
      <tr>
          <td>Kubernetes cost</td>
          <td>強 — namespace / label / pod-level 內建</td>
          <td>中 — 整合需配置</td>
          <td>中</td>
          <td>弱</td>
      </tr>
      <tr>
          <td>Anomaly detection</td>
          <td>內建、threshold 可調</td>
          <td>內建 + policy 觸發</td>
          <td>內建</td>
          <td>基本（AWS Cost Anomaly Detection）</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>100-1000 人工程組織、cloud-native</td>
          <td>5000+ 員工跨 BU enterprise governance</td>
          <td>把 IT cost 對到 product P&amp;L 的組織</td>
          <td>純 AWS、預算敏感、初期治理</td>
      </tr>
      <tr>
          <td>退場成本</td>
          <td>低-中 — report 為主、無深度 lock-in</td>
          <td>高 — policy / approval workflow 量多</td>
          <td>高 — TBM mapping 跟 business 整合</td>
          <td>零 — 本就免費內建</td>
      </tr>
  </tbody>
</table>
<p>選 Vantage 的核心訴求：<em>工程團隊自助 FinOps + 跨雲跨 SaaS 一張視圖 + UI / 報表 share 走 modern observability 體驗</em>、且不需要 enterprise approval workflow / TBM business mapping。需要重 governance 走 CloudHealth、需要 IT-to-business cost mapping 走 Apptio、純 AWS 預算敏感先用 Cost Explorer。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Cost Report builder</strong>：Vantage 的核心 primitive、走 <em>filter + group by + time range</em> 的 declarative model — 例如 <code>provider:aws AND service:ec2 AND tag:team=payments group by region</code>。Saved report 變團隊 canonical view、URL 可貼 wiki / Slack；scheduled report 走 email / Slack notification。實務上 <em>每個 service owner 都該有一張 saved report</em>、不是 FinOps team 中央集中看。</p>
<p><strong>Anomaly Detection</strong>：依 cost trend 統計 baseline、超過 threshold 觸發 anomaly。痛點是 <em>false positive</em>：deploy 新 service、月底 invoice timing、provider 計費延遲都會觸發。Tune 方向是 <em>排除 known event</em>（new connector 接入後 7 天 grace period）+ <em>調 sensitivity per service</em>（payment 可容忍 5% drift、ML training cluster 容忍 50%）。對應 <a href="/blog/backend/09-performance-capacity/cost-engineering/" data-link-title="9.7 成本邊界與 efficiency" data-link-desc="cost per request、cost curve、降級成本、over-provisioning trade-off">9.7 成本邊界與 efficiency</a> 的 anomaly governance frame。</p>
<p><strong>Resource ROI / efficiency metric</strong>：Vantage 把 cost 跟 utilization metric 對齊、算 <em>cost per unit</em>（cost / request、cost / GB stored、cost / GPU-hour）。意義是把 cost report 從 <em>absolute spend</em> 升級到 <em>efficiency frontier</em>、能識別 overprovision 跟 underutilization。需要 metric source 接上（Datadog / Prometheus / CloudWatch）、純帳單 data 算不出 ROI。</p>
<p><strong>Datadog / Slack integration</strong>：cost anomaly + scheduled report 推到 Slack channel、跟 incident channel 共用；Datadog 接成 metric source 後可在 Datadog dashboard 看 cost trend 跟 latency / error rate side-by-side、適合做 <em>cost-aware SLO review</em>。</p>
<p><strong>Vantage Network（vendor benchmark）</strong>：匿名化彙整 Vantage 客戶的 unit cost benchmark（每 GB S3 storage、每 RDS instance hour、每 Snowflake credit）、讓客戶看自己跟同產業比是貴是便宜。價值在 <em>negotiation leverage</em> — 跟 AWS / Snowflake 談 EDP / 多年合約時、benchmark 是議價素材。注意是匿名 aggregate、不是 vendor 個別揭露。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Multi-cloud tag drift</strong>：AWS 用 <code>team</code>、GCP 用 <code>Team</code>、Azure 用 <code>Team-Name</code>、Vantage report group by 後出現大量 <code>untagged</code> — 在 Vantage <em>Virtual Tag</em>（rule-based tag normalization）統一 mapping、或源頭走 tag policy enforcement（<a href="https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_tag-policies.html">AWS Organizations tag policy</a>、GCP organization policy）</li>
<li><strong>Anomaly false positive 過多 / SOC-like alert fatigue</strong>：threshold 設太緊、month-end billing delay 沒排除 — 拉大 baseline window、加 grace period for new resource、per-service tune sensitivity</li>
<li><strong>Cost spike root cause 不明</strong>：總帳單漲了但 group by service / region / tag 都看不出來 — 切到 <em>Resource Report</em>（最細粒度、看 instance / volume / snapshot 個別 cost）找 outlier、或開 Vantage <em>Cost Diffs</em>（兩個 time window 對比 delta breakdown）</li>
<li><strong>Kubernetes cost agent 資料缺</strong>：agent 沒裝 / cluster role 權限不足 / metric server 沒啟用、namespace breakdown 全空 — 走 Vantage Kubernetes onboarding checklist 補 agent + RBAC + metric server、確認資料 24hr 內出現</li>
<li><strong>Connector 接上但資料沒進來</strong>：跨 account assume role 失敗、CUR（Cost and Usage Report）export 沒開、Snowflake account usage 權限缺 — 在 Vantage connector page 看 sync status 跟 error log、不是盲猜</li>
<li><strong>Report share URL 被外人猜到</strong>：read-only URL 預設 <em>unauthenticated</em>、share 給 contractor 後沒 revoke — 改用 <em>Authentication-required share</em> 或定期 rotate URL、敏感成本數字（payment processor cost / customer-specific dedicated infra）走 internal-only</li>
<li><strong>Forecast 不準 / 跟實際差太多</strong>：base period 太短 / 有 one-off event（migration backfill、disaster recovery test）、forecast model 抓不到 seasonality — 拉長 base period、標記 one-off event 排除、或改走 manual override forecast 給特定 service</li>
</ul>
<h2 id="操作成本">操作成本</h2>
<p>Vantage 的主要成本是 cost taxonomy 維護。Tag、label、account、workspace、cluster、namespace 與 service owner 要有穩定規則，Cost Reports 才能被工程團隊信任。</p>
<p>Kubernetes agent 導入需要平台協作。Cluster 權限、資料上傳、node / pod mapping、provider cost delay 與 double counting 防護，都需要平台團隊與 FinOps 團隊一起定義。</p>
<p>Remediation 成本在報表之後才開始。找到 idle cost、overprovisioned workload 或 unexpected egress 只是第一步，後續要有 ticket、owner、驗證、rollback 與 saving confirmation。</p>
<h2 id="evidence-package">Evidence Package</h2>
<p>Vantage 結果應回寫到 cost attribution evidence package。最小欄位包括 report name、filter、grouping、time range、provider、owner dimension、baseline cost、forecast、anomaly、efficiency metric、action item 與 owner。</p>
<table>
  <thead>
      <tr>
          <th>欄位</th>
          <th>Vantage 證據來源</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Source</td>
          <td>Cost Report、Kubernetes Efficiency Report、Resource Report</td>
      </tr>
      <tr>
          <td>Time range</td>
          <td>report window、billing period、forecast period</td>
      </tr>
      <tr>
          <td>Query link</td>
          <td>Vantage report URL、cloud billing query、dashboard</td>
      </tr>
      <tr>
          <td>Data quality</td>
          <td>tag coverage、agent freshness、provider data delay</td>
      </tr>
      <tr>
          <td>Confidence</td>
          <td>owner mapping、double counting check、trend repeatability</td>
      </tr>
      <tr>
          <td>Known gap</td>
          <td>未標記 resource、shared cost allocation rule、資料延遲</td>
      </tr>
  </tbody>
</table>
<p>Evidence package 的核心用途是把成本問題交給正確 owner。Vantage report 要能回答「誰的 workload 產生成本、成本從何時開始改變、哪個維度最能解釋變化」。</p>
<h2 id="案例回寫">案例回寫</h2>
<p>Vantage 目前適合作為 <a href="/blog/backend/09-performance-capacity/cost-engineering/" data-link-title="9.7 成本邊界與 efficiency" data-link-desc="cost per request、cost curve、降級成本、over-provisioning trade-off">9.7 成本邊界與 efficiency</a> 與 <a href="/blog/backend/04-observability/cost-attribution/" data-link-title="4.15 Cost Attribution / Chargeback" data-link-desc="把 observability 成本拆到團隊、產品、環境維度">04 cost attribution</a> 的工具承接點。它可回寫到 <a href="/blog/backend/09-performance-capacity/cases/riot-games-eks-multi-cluster/" data-link-title="9.C12 Riot Games：246 個 EKS cluster 的多遊戲多地區治理" data-link-desc="Riot Games 從 Mesos 遷移到 EKS、用 246 個 cluster 跨遊戲跨地區治理、年省 1000 萬美金">9.C12 Riot Games 246 EKS cluster</a> 的多 cluster 成本歸屬與年省 1000 萬美金驗證、<a href="/blog/backend/09-performance-capacity/cases/netflix-aurora-consolidation/" data-link-title="9.C23 Netflix：把關聯式 DB 統一到 Aurora、效能 &#43;75%、成本 -28%" data-link-desc="Netflix 把多套關聯式 DB 統一到 Aurora、效能提升 75%、成本下降 28%、串流數十億小時">9.C23 Netflix Aurora consolidation</a> 的 28% 成本下降跨 DB 整併、<a href="/blog/backend/09-performance-capacity/cases/bookmyshow-indian-ticketing-platform/" data-link-title="9.C17 BookMyShow：印度年售 2 億張票的資料架構現代化" data-link-desc="BookMyShow 從 15 年自建 analytics 遷移到 AWS modern data architecture、4 個月完成、分析成本下降 80%">9.C17 BookMyShow modern data architecture</a> 的儲存 90% / 分析 80% 成本下降，以及 <a href="/blog/backend/09-performance-capacity/cases/zomato-tidb-to-dynamodb-migration/" data-link-title="9.C20 Zomato：從 TiDB 遷移到 DynamoDB、吞吐 4 倍、延遲降 90%、成本減 50%" data-link-desc="Zomato 帳單系統從 TiDB 遷移到 DynamoDB、吞吐 2K→8K RPM、延遲降 90%、成本減 50%">9.C20 Zomato</a> 的 on-demand cost model 50% 降幅。</p>
<p>這些案例的重點是成本歸屬。Vantage 頁引用案例時，要把 report filter、owner dimension、成本變化、action item 與驗證結果寫清楚 — 例如 Netflix 的 28% 下降需要拆到 DB tier、replication topology 與 read replica 比例，避免停在帳單 dashboard 截圖。</p>
<p>Vantage 的客戶輪廓偏 <em>modern startup 與 mid-market</em> — 工程組織 100-1000 人、cloud-native first、沒有獨立 FinOps team、由 platform / SRE 兼任成本治理。這類組織的痛點是 <em>誰看 cost report、誰調 anomaly、誰負責 saving validation</em> 的工程節奏沒建立、governance policy 本身反而不缺。引用 Riot Games / Netflix / BookMyShow / Zomato 案例時、重點是把這些 enterprise-scale 的 attribution 機制轉譯成 mid-market 可執行的 weekly review 節奏、而非照搬全部 governance overhead。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/09-performance-capacity/cost-engineering/" data-link-title="9.7 成本邊界與 efficiency" data-link-desc="cost per request、cost curve、降級成本、over-provisioning trade-off">9.7 成本邊界與 efficiency</a></li>
<li>上游：<a href="/blog/backend/09-performance-capacity/performance-observability/" data-link-title="9.8 效能可觀測性" data-link-desc="saturation metric、USE / RED method、cost dashboard">9.8 效能可觀測性</a></li>
<li>跨模組：<a href="/blog/backend/04-observability/cost-attribution/" data-link-title="4.15 Cost Attribution / Chargeback" data-link-desc="把 observability 成本拆到團隊、產品、環境維度">04 可觀測性成本歸因</a></li>
<li>平行：<a href="/blog/backend/09-performance-capacity/vendors/cloudhealth/" data-link-title="CloudHealth" data-link-desc="用 enterprise FinOps governance、policy 與多雲成本管理支援大型組織的容量成本治理">CloudHealth</a>、<a href="/blog/backend/09-performance-capacity/vendors/aws-cost-explorer/" data-link-title="AWS Cost Explorer" data-link-desc="用 AWS-native 成本與用量分析建立 account、service、tag 與 usage type 的成本判讀入口">AWS Cost Explorer</a></li>
<li>官方：<a href="https://docs.vantage.sh/cost_reports">Vantage Cost Reports</a></li>
</ul>
]]></content:encoded></item><item><title>OPA Gatekeeper</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/gatekeeper/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/gatekeeper/</guid><description>&lt;p>OPA Gatekeeper 是 OPA 官方在 Kubernetes admission 層的落實、把 OPA 的 general-purpose policy engine 適配成 K8s-native admission controller。它跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/opa/" data-link-title="Open Policy Agent (OPA)" data-link-desc="CNCF general-purpose policy engine、Rego Datalog-like 語言、decoupled decision &amp;#43; enforcement、跨 K8s / API / Terraform / SQL 統一 policy">OPA&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/kyverno/" data-link-title="Kyverno" data-link-desc="K8s-native policy engine、YAML policy（非 Rego）、五類 rule（Validate / Mutate / Generate / Verify Images / Cleanup）、CNCF Incubating">Kyverno&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/conftest/" data-link-title="Conftest" data-link-desc="OPA CLI wrapper for static config policy check、Rego policy &amp;#43; 多 parser（Terraform / K8s / Dockerfile / JSON）、CI-time gate">Conftest&lt;/a> 的差異不在「policy 能不能寫」、而在 &lt;em>對接面 + 抽象層次 + 工具鏈定位&lt;/em> — Gatekeeper 是 OPA 在 K8s admission 的 first-class 落實、ConstraintTemplate + Constraint 兩層抽象把 Rego policy 變成 K8s CRD、Audit 補位 background scan、Mutation 2024 起進 stable。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Gatekeeper 的核心定位是 &lt;em>Rego policy 在 K8s admission 層的 K8s-native 包裝&lt;/em>、不是另一個 policy engine。底層仍是 OPA、Rego 是同一套語言；上層加了兩個 K8s-specific 抽象 — &lt;em>ConstraintTemplate&lt;/em>（Rego policy + parameter schema 的 CRD 定義）跟 &lt;em>Constraint&lt;/em>（Template 的 instance、指定 match scope 與 parameter）。意義是同一份 Rego policy 寫一次、在不同 cluster / 不同 namespace 給不同 Constraint instance、不用改 Rego 本體。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/opa/" data-link-title="Open Policy Agent (OPA)" data-link-desc="CNCF general-purpose policy engine、Rego Datalog-like 語言、decoupled decision &amp;#43; enforcement、跨 K8s / API / Terraform / SQL 統一 policy">OPA&lt;/a>（純 sidecar）比、Gatekeeper 走 &lt;em>K8s-native + 兩層抽象&lt;/em>、犧牲 OPA 純 sidecar 的跨平台彈性（OPA 可同時管 K8s admission + API gateway + Terraform plan）、換來 K8s 內部 CRD + RBAC + GitOps 的一致體驗。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/kyverno/" data-link-title="Kyverno" data-link-desc="K8s-native policy engine、YAML policy（非 Rego）、五類 rule（Validate / Mutate / Generate / Verify Images / Cleanup）、CNCF Incubating">Kyverno&lt;/a> 比、Gatekeeper 走 &lt;em>Rego DSL&lt;/em>、Kyverno 走 &lt;em>YAML pattern matching&lt;/em> — team 已投資 OPA / Rego（API gateway / Terraform 已用 Rego）就走 Gatekeeper、純 K8s shop + 沒 Rego 包袱直接用 Kyverno 較省學習成本。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/conftest/" data-link-title="Conftest" data-link-desc="OPA CLI wrapper for static config policy check、Rego policy &amp;#43; 多 parser（Terraform / K8s / Dockerfile / JSON）、CI-time gate">Conftest&lt;/a> 比、Conftest 是 &lt;em>CI-time static config check&lt;/em>、Gatekeeper 是 &lt;em>runtime admission + audit&lt;/em>、兩者互補不互斥（CI 用 Conftest 擋 PR、admission 用 Gatekeeper 擋 deploy）。&lt;/p></description><content:encoded><![CDATA[<p>OPA Gatekeeper 是 OPA 官方在 Kubernetes admission 層的落實、把 OPA 的 general-purpose policy engine 適配成 K8s-native admission controller。它跟 <a href="/blog/backend/07-security-data-protection/vendors/opa/" data-link-title="Open Policy Agent (OPA)" data-link-desc="CNCF general-purpose policy engine、Rego Datalog-like 語言、decoupled decision &#43; enforcement、跨 K8s / API / Terraform / SQL 統一 policy">OPA</a> / <a href="/blog/backend/07-security-data-protection/vendors/kyverno/" data-link-title="Kyverno" data-link-desc="K8s-native policy engine、YAML policy（非 Rego）、五類 rule（Validate / Mutate / Generate / Verify Images / Cleanup）、CNCF Incubating">Kyverno</a> / <a href="/blog/backend/07-security-data-protection/vendors/conftest/" data-link-title="Conftest" data-link-desc="OPA CLI wrapper for static config policy check、Rego policy &#43; 多 parser（Terraform / K8s / Dockerfile / JSON）、CI-time gate">Conftest</a> 的差異不在「policy 能不能寫」、而在 <em>對接面 + 抽象層次 + 工具鏈定位</em> — Gatekeeper 是 OPA 在 K8s admission 的 first-class 落實、ConstraintTemplate + Constraint 兩層抽象把 Rego policy 變成 K8s CRD、Audit 補位 background scan、Mutation 2024 起進 stable。</p>
<h2 id="服務定位">服務定位</h2>
<p>Gatekeeper 的核心定位是 <em>Rego policy 在 K8s admission 層的 K8s-native 包裝</em>、不是另一個 policy engine。底層仍是 OPA、Rego 是同一套語言；上層加了兩個 K8s-specific 抽象 — <em>ConstraintTemplate</em>（Rego policy + parameter schema 的 CRD 定義）跟 <em>Constraint</em>（Template 的 instance、指定 match scope 與 parameter）。意義是同一份 Rego policy 寫一次、在不同 cluster / 不同 namespace 給不同 Constraint instance、不用改 Rego 本體。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/opa/" data-link-title="Open Policy Agent (OPA)" data-link-desc="CNCF general-purpose policy engine、Rego Datalog-like 語言、decoupled decision &#43; enforcement、跨 K8s / API / Terraform / SQL 統一 policy">OPA</a>（純 sidecar）比、Gatekeeper 走 <em>K8s-native + 兩層抽象</em>、犧牲 OPA 純 sidecar 的跨平台彈性（OPA 可同時管 K8s admission + API gateway + Terraform plan）、換來 K8s 內部 CRD + RBAC + GitOps 的一致體驗。跟 <a href="/blog/backend/07-security-data-protection/vendors/kyverno/" data-link-title="Kyverno" data-link-desc="K8s-native policy engine、YAML policy（非 Rego）、五類 rule（Validate / Mutate / Generate / Verify Images / Cleanup）、CNCF Incubating">Kyverno</a> 比、Gatekeeper 走 <em>Rego DSL</em>、Kyverno 走 <em>YAML pattern matching</em> — team 已投資 OPA / Rego（API gateway / Terraform 已用 Rego）就走 Gatekeeper、純 K8s shop + 沒 Rego 包袱直接用 Kyverno 較省學習成本。跟 <a href="/blog/backend/07-security-data-protection/vendors/conftest/" data-link-title="Conftest" data-link-desc="OPA CLI wrapper for static config policy check、Rego policy &#43; 多 parser（Terraform / K8s / Dockerfile / JSON）、CI-time gate">Conftest</a> 比、Conftest 是 <em>CI-time static config check</em>、Gatekeeper 是 <em>runtime admission + audit</em>、兩者互補不互斥（CI 用 Conftest 擋 PR、admission 用 Gatekeeper 擋 deploy）。</p>
<p>關鍵張力：<em>Rego 學習曲線</em> ↔ <em>跨平台 policy 一致性</em> 是 Gatekeeper 跟 Kyverno 最大的選擇分水嶺。純 K8s 場景 Kyverno YAML 寫起來快、但同樣的 image signature 規則若要在 Terraform plan / CI / admission 三處 enforce、Rego 寫一次跨三處比 YAML / Cue / Sentinel 多種語言混用乾淨。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>Gatekeeper 在 cluster policy stack 中承擔哪一段（admission validation / audit / mutation）、哪些要外接（<a href="/blog/backend/07-security-data-protection/vendors/opa/" data-link-title="Open Policy Agent (OPA)" data-link-desc="CNCF general-purpose policy engine、Rego Datalog-like 語言、decoupled decision &#43; enforcement、跨 K8s / API / Terraform / SQL 統一 policy">OPA</a> 純 sidecar 管非 K8s 對象、<a href="/blog/backend/07-security-data-protection/vendors/conftest/" data-link-title="Conftest" data-link-desc="OPA CLI wrapper for static config policy check、Rego policy &#43; 多 parser（Terraform / K8s / Dockerfile / JSON）、CI-time gate">Conftest</a> 補 CI-time）</li>
<li>ConstraintTemplate 跟 Constraint 兩層怎麼切（Template 由 platform team 維護、Constraint 給 app team 在 namespace 內 instantiate）</li>
<li>Audit / Mutation / External Data Provider 何時開、開了之後 cost 與 failure mode</li>
<li>何時用 Gatekeeper、何時改 Kyverno 或退回純 OPA 的取捨</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Gatekeeper deployment 是否健康、最少看四件事：</p>
<ul>
<li><strong>ConstraintTemplate 的 ownership</strong>：誰寫 Rego、誰 review、Template 是否走 Git（PR review + Gator CLI unit test）、是否有共用 library 避免每個 Template 重寫 K8s helper</li>
<li><strong>Audit coverage</strong>：除了 admission 攔截、Audit 是否定期 scan 已存在 resource（pre-Gatekeeper 部署的 legacy resource 違規）、<code>auditFromCache</code> 是否開、audit interval 是否合理（預設 60s、production 通常拉到 5-10min 避 API server 壓力）</li>
<li><strong>Failure mode 治理</strong>：Constraint <code>enforcementAction</code> 是 <code>deny</code> / <code>warn</code> / <code>dryrun</code>、Webhook failurePolicy 是 <code>Fail</code> / <code>Ignore</code>、<code>Fail</code> + Gatekeeper pod down 會擋全 cluster deploy</li>
<li><strong>跟 GitOps 的對接</strong>：ConstraintTemplate / Constraint 是否走 ArgoCD / Flux 部署、policy change 是否經 staging cluster 驗證、emergency exception 流程是否定義</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">Detection Coverage and Signal Governance</a> 在 admission 層的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>ConstraintTemplate（CT）— Rego policy + CRD 定義</strong>：CT 是 Gatekeeper 的核心抽象、由 Rego policy + parameter schema（OpenAPI v3）兩段組成。Template 寫好 apply 到 cluster 後、Gatekeeper 會生成同名 CRD（例 <code>K8sRequiredLabels</code>）、app team 就能用該 CRD 寫 Constraint。Template 由 platform team 維護、不該每個 app team 自己寫 Rego — 集中維護才能保證 helper / convention / unit test 一致。</p>
<p><strong>Constraint — Template 的 instance + match scope</strong>：Constraint 指定三件事 — <em>該套用哪個 Template</em>（kind）、<em>套用範圍</em>（match：kinds / namespaces / labelSelector / excludedNamespaces）、<em>parameter 值</em>（spec.parameters、對應 Template 的 schema）。同一個 Template 可以有多個 Constraint instance（production / staging 不同 threshold、不同 namespace 不同 required label set）。這層抽象的意義是 <em>policy logic 跟 environment-specific configuration 分開</em>。</p>
<p><strong>Audit — background scan 已存在 resource</strong>：除了 admission webhook 在 create / update 時攔、Audit controller 定期（預設 60s）掃整個 cluster 找違規 resource、結果寫到 Constraint status 的 <code>violations</code> 欄位。意義是 <em>legacy resource 在你 install Gatekeeper 之前就在那、admission 不會觸發、Audit 才會抓到</em>。<code>auditFromCache: true</code> 用 Gatekeeper 自己的 informer cache 不打 API server、適合大 cluster。</p>
<p><strong>Mutation — 2024+ stable</strong>：早期 Gatekeeper 只有 Validation、Mutation 在 v3.10+ 進 beta、2024 隨 v3.14+ 進 stable。Mutation 走獨立 CRD（<code>Assign</code> / <code>AssignMetadata</code> / <code>ModifySet</code>）、不走 ConstraintTemplate。常見用法：注入 <code>securityContext.runAsNonRoot: true</code>、補 default resource limit、加 organization label。Mutation 跟 Validation 都開的話、Mutation 先跑、Validation 看 mutated 後的結果。</p>
<p><strong>Sync Resources — cross-resource lookup</strong>：Rego policy 若要查 <em>別的 resource</em>（例：擋 Service 用了不存在的 Namespace）、要先 declare <code>Config</code> CRD 把該 resource type 加進 Gatekeeper 的 sync list、Gatekeeper 才會在 cache 裡有那個 resource 供 Rego 查。沒 sync 的 resource 不能跨 reference、是常見踩雷點。</p>
<p><strong>External Data Provider — query 外部 API 做 decision</strong>：Gatekeeper v3.10+ 引入 External Data Provider、Rego 可以 call 外部 HTTPS endpoint 取 runtime data 做 policy decision。典型用法：query image scan service（例 <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> server）確認 image 沒 CVE、query SBOM attestation service 確認 supply chain 完整、query custom IAM 確認 namespace owner 有權建立該 resource。要設 timeout + cache、外部 service down 不能擋全 cluster admission。</p>
<p><strong>Gator CLI — policy unit test</strong>：Gator 是 Gatekeeper 官方 CLI、本機跑 Template + Constraint 對 mock K8s manifest、不需 cluster。CI pipeline 跑 <code>gator test</code> 對每個 Template 跑 fixture、policy change 出 PR 時自動驗證 — 避免 production deploy 才發現 Template Rego bug 擋全 cluster。</p>
<p><strong>跟 GitOps 整合</strong>：ConstraintTemplate / Constraint / Mutation / Config CRD 都是純 YAML、走 ArgoCD / Flux 部署是標準作法。實務 layout：<code>gatekeeper-system</code> namespace 裝 Gatekeeper、<code>gatekeeper-policies</code> repo 放 Template 跟 baseline Constraint（platform team owned）、各 app namespace 的 Constraint instance 可以由 app team 在自己 repo 管理（透過 ArgoCD AppProject 限制 Constraint kind）。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>OPA Gatekeeper</th>
          <th>Kyverno</th>
          <th>OPA 純 sidecar</th>
          <th>Conftest</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>對接面</td>
          <td>K8s admission + Audit（K8s-only）</td>
          <td>K8s admission + Audit（K8s-only）</td>
          <td>任意 — API gateway / Terraform / K8s</td>
          <td>CI-time（static config check）</td>
      </tr>
      <tr>
          <td>Policy 語言</td>
          <td>Rego（OPA 同一套）</td>
          <td>YAML pattern matching（K8s-native）</td>
          <td>Rego</td>
          <td>Rego（OPA 同一套）</td>
      </tr>
      <tr>
          <td>抽象層次</td>
          <td>ConstraintTemplate + Constraint 兩層</td>
          <td>ClusterPolicy / Policy（單層）</td>
          <td>OPA policy bundle（無 K8s-specific 抽象）</td>
          <td>conftest test file（無 cluster 概念）</td>
      </tr>
      <tr>
          <td>Mutation</td>
          <td>支援（v3.14+ stable）</td>
          <td>支援（first-class、Kyverno 強項）</td>
          <td>不支援（需自寫 admission webhook）</td>
          <td>不適用</td>
      </tr>
      <tr>
          <td>Cross-resource</td>
          <td>Sync Resources（要 declare）</td>
          <td>Context API（內建）</td>
          <td>看自己 sidecar 怎麼寫</td>
          <td>看 CI 怎麼 load</td>
      </tr>
      <tr>
          <td>外部 data</td>
          <td>External Data Provider（v3.10+）</td>
          <td>Context API（image registry / ConfigMap）</td>
          <td>看自己 sidecar 怎麼寫</td>
          <td>不適用（純 static）</td>
      </tr>
      <tr>
          <td>學習曲線</td>
          <td>Rego 陡 + 兩層抽象多概念</td>
          <td>YAML 直觀、K8s-native idiom</td>
          <td>Rego 陡 + 自管 deployment</td>
          <td>Rego 陡 + CI integration</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>team 已投資 Rego / OPA、跨 K8s + 其他平台一致</td>
          <td>純 K8s shop、無 Rego 包袱、Mutation 是重點</td>
          <td>跨 K8s + API + Terraform 一致 policy 管理面</td>
          <td>PR 階段擋 manifest / IaC config</td>
      </tr>
      <tr>
          <td>退場成本</td>
          <td>高 — Template / Constraint / Rego 量多</td>
          <td>中 — YAML 較可移植</td>
          <td>中 — Rego 可搬到 Gatekeeper</td>
          <td>低</td>
      </tr>
  </tbody>
</table>
<p>選 Gatekeeper 的核心訴求：<em>team 已用 Rego（API gateway / Terraform plan / CI 已 OPA）+ 想把 same policy 延伸到 K8s admission + 看重 OPA ecosystem 一致性</em>。純 K8s shop 沒 Rego 包袱、又特別需要 Mutation 場景密集（PSP 廢除後重建、跨 namespace 統一 sidecar 注入）直接走 Kyverno 更省學習成本。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Rego idioms for K8s admission</strong>：K8s admission review 物件結構是 <code>input.review.object</code>、Template 的 <code>violation</code> rule 走 <code>violation[{&quot;msg&quot;: msg}] { ... }</code> 形式。常見 idiom：<code>match.kinds</code> 跟 <code>match.namespaceSelector</code> 在 Constraint 層處理 scope、Rego 內只寫 <em>policy logic</em>；K8s helper（label 取值、container loop、init container 排除）抽到 shared library Template；錯誤訊息要帶 <code>input.review.object.metadata.name</code> 幫 app team 定位是哪個 resource 被擋。</p>
<p><strong>External Data Provider 的 production 治理</strong>：Provider 是獨立 service、Gatekeeper webhook 透過 HTTPS call、cache 在 Gatekeeper 內。要設 timeout（預設 3s、過時 ConstraintTemplate <code>failurePolicy</code> 決定 fail-open / fail-closed）、cache TTL、Provider 自身的 readiness / liveness。Provider down 不該擋全 cluster — 用 <code>failurePolicy: Ignore</code> 對 External Data Provider 例外、但記錄 metric alert。對應 <a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/xz-backdoor-2024-open-source-supply-chain/" data-link-title="7.R7.2.4 XZ Backdoor 2024：開源供應鏈長期滲透" data-link-desc="開源維護鏈遭滲透後，為何會直接影響廣泛 Linux 發行流程">XZ Backdoor 2024</a> 的 SBOM attestation 查詢場景。</p>
<p><strong>Gator CLI 在 CI 的 pipeline 設計</strong>：<code>gator test</code> 對 fixture 跑、<code>gator verify</code> 跑 Template 自帶 test suite、<code>gator expand</code> 預覽 Mutation 結果。PR 流程：Template change → <code>gator verify</code> 跑 unit test → kind cluster 起 Gatekeeper apply Template + sample violation manifest → confirm 擋下來才 merge。</p>
<p><strong>跟 Styra DAS / Nirmata 整合</strong>：Gatekeeper OSS 本身沒 central management UI、多 cluster deployment 看 violation status 要自己拼。Styra DAS 是 OPA 商業 control plane、可以 push Template / Constraint 到多 cluster Gatekeeper、彙整 audit violation、做 policy impact analysis。Nirmata 走類似路線。OSS-only deployment 通常用 ArgoCD ApplicationSet + Prometheus exporter（gatekeeper-policy-manager / Open Policy Agent metrics）拼。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Gatekeeper webhook timeout / 擋全 cluster admission</strong>：Rego policy 寫了 expensive operation（大量 cross-resource lookup、External Data Provider call without cache）— webhook timeout 預設 3s、超過就走 failurePolicy；改寫 Rego 用 indexed lookup、External Data Provider 加 cache、<code>failurePolicy: Ignore</code> for non-critical Template</li>
<li><strong>新 Template apply 後 admission 整個壞</strong>：Rego syntax / logic bug、production 才發現 — PR 必跑 <code>gator verify</code> + staging cluster 24-48hr soak、Constraint 先用 <code>enforcementAction: dryrun</code> 觀察 violation count 才切 <code>deny</code></li>
<li><strong>Audit 跑很慢 / API server 壓力大</strong>：cluster resource 量大、Audit interval 預設 60s 太頻繁 — 拉長到 5-10min、<code>auditFromCache: true</code> 用 informer 不打 API server、大 cluster 開 <code>auditChunkSize</code> 分批處理</li>
<li><strong>legacy resource 不擋</strong>：admission webhook 只攔 create / update、<code>kubectl apply</code> 沒改動 spec 不觸發 — 用 Audit 抓 violation、配合手動 migration plan、不要期待 admission 自動修</li>
<li><strong>Mutation 跟 Validation 衝突</strong>：Mutation 加了 label、Validation 又擋說 label 不該存在 — Mutation 先跑、Validation 看 mutated 結果；設計 policy 時要對齊兩端、不能各自寫</li>
<li><strong>Sync 沒 declare、cross-resource policy 看不到對象</strong>：Rego <code>data.inventory.namespace[&quot;foo&quot;].v1.Pod</code> 回 undefined — <code>Config</code> CRD 加 sync targets、確認 Gatekeeper pod restart 後 cache 載入</li>
<li><strong>External Data Provider down 擋全 cluster</strong>：Provider service 自己掛、<code>failurePolicy: Fail</code> 整個 admission 壞 — Provider 走 <code>failurePolicy: Ignore</code> + metric alert、Provider 自身 HA 部署、cache TTL 拉長</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>純 K8s + 無 Rego 包袱 + Mutation 重點</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/kyverno/" data-link-title="Kyverno" data-link-desc="K8s-native policy engine、YAML policy（非 Rego）、五類 rule（Validate / Mutate / Generate / Verify Images / Cleanup）、CNCF Incubating">Kyverno</a></td>
      </tr>
      <tr>
          <td>跨 K8s + API gateway + Terraform</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/opa/" data-link-title="Open Policy Agent (OPA)" data-link-desc="CNCF general-purpose policy engine、Rego Datalog-like 語言、decoupled decision &#43; enforcement、跨 K8s / API / Terraform / SQL 統一 policy">OPA</a>（純 sidecar）</td>
      </tr>
      <tr>
          <td>CI-time / PR 階段擋 manifest</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/conftest/" data-link-title="Conftest" data-link-desc="OPA CLI wrapper for static config policy check、Rego policy &#43; 多 parser（Terraform / K8s / Dockerfile / JSON）、CI-time gate">Conftest</a></td>
      </tr>
      <tr>
          <td>Image scan 結果作為 policy 來源</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a>（feed External Data Provider）</td>
      </tr>
      <tr>
          <td>Runtime threat detection（syscall）</td>
          <td>Falco / Cilium Tetragon（屬 runtime detection、不在 admission 層）</td>
      </tr>
      <tr>
          <td>Multi-cluster policy 集中管理</td>
          <td>Styra DAS / Nirmata（OPA / Gatekeeper 商業 control plane）</td>
      </tr>
      <tr>
          <td>偵測 / SIEM</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> 或同類 SIEM</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Rego 完整語法 reference（unification、comprehension、partial evaluation）</li>
<li>Gatekeeper helm chart / installation 細節（看官方 docs）</li>
<li>Open Policy Agent 在 service mesh / API gateway 的 sidecar 部署模式（看 <a href="/blog/backend/07-security-data-protection/vendors/opa/" data-link-title="Open Policy Agent (OPA)" data-link-desc="CNCF general-purpose policy engine、Rego Datalog-like 語言、decoupled decision &#43; enforcement、跨 K8s / API / Terraform / SQL 統一 policy">OPA</a> 頁）</li>
<li>Pod Security Admission（K8s 內建、跟 Gatekeeper 互補但不是 Gatekeeper 一部分）</li>
<li>Multi-cluster policy bundle 的 OCI registry 分發（屬 <a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">7.12 供應鏈完整性</a> 邊界）</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>Gatekeeper 在 07 案例庫沒有直接 vendor-level 事件、但 supply chain 跟 admission policy 相關 case 都是 Gatekeeper 落實位置的對照：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 Gatekeeper 的關係（對照啟示）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/solarwinds-2020-sunburst/" data-link-title="7.R7.2.1 SolarWinds 2020：更新鏈被濫用" data-link-desc="合法更新流程遭植入後，攻擊者如何長期潛伏與橫向擴散">SolarWinds 2020 Sunburst</a></td>
          <td>ConstraintTemplate 配 cosign image signature verify、擋未簽 / 簽章不符 image 進 cluster；Audit 補位掃既有 deployment 找未簽 image</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/log4shell-cve-2021-44228-component-chain/" data-link-title="7.R7.2.7 Log4Shell 2021：共用元件風險與修補鏈" data-link-desc="共用元件漏洞如何同步影響多服務，並迫使團隊建立依賴治理 workflow">Log4Shell CVE-2021-44228</a></td>
          <td>Gatekeeper External Data Provider 接 <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> server、admission 階段查 image 是否有 critical CVE 直接擋</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/xz-backdoor-2024-open-source-supply-chain/" data-link-title="7.R7.2.4 XZ Backdoor 2024：開源供應鏈長期滲透" data-link-desc="開源維護鏈遭滲透後，為何會直接影響廣泛 Linux 發行流程">XZ Backdoor 2024</a></td>
          <td>External Data Provider 可 query SBOM attestation 服務做 policy decision、不只看 image hash 而看 component provenance 鏈</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">7.12 供應鏈完整性 (section)</a></td>
          <td>Gatekeeper 是 OPA ecosystem 在 K8s admission 的官方落實、artifact trust gate 從 CI（Conftest）延伸到 runtime（Gatekeeper）的閉環</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">7.12 供應鏈完整性與 Artifact Trust</a>、<a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">7.13 偵測覆蓋率與訊號治理</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/opa/" data-link-title="Open Policy Agent (OPA)" data-link-desc="CNCF general-purpose policy engine、Rego Datalog-like 語言、decoupled decision &#43; enforcement、跨 K8s / API / Terraform / SQL 統一 policy">OPA</a>、<a href="/blog/backend/07-security-data-protection/vendors/kyverno/" data-link-title="Kyverno" data-link-desc="K8s-native policy engine、YAML policy（非 Rego）、五類 rule（Validate / Mutate / Generate / Verify Images / Cleanup）、CNCF Incubating">Kyverno</a>、<a href="/blog/backend/07-security-data-protection/vendors/conftest/" data-link-title="Conftest" data-link-desc="OPA CLI wrapper for static config policy check、Rego policy &#43; 多 parser（Terraform / K8s / Dockerfile / JSON）、CI-time gate">Conftest</a></li>
<li>下游：<a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a>（image scan 結果 feed External Data Provider）、<a href="/blog/backend/07-security-data-protection/vendors/spire/" data-link-title="SPIRE" data-link-desc="SPIFFE Runtime Environment、attested workload identity、short-lived SVID &#43; Trust Bundle、跨組織 federation">SPIRE</a>（workload identity 跟 admission policy 互補）</li>
<li>跨類：<a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a>（admission violation event 進 SIEM correlation）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（policy violation → IR routing）</li>
<li>官方：<a href="https://open-policy-agent.github.io/gatekeeper/">OPA Gatekeeper Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>AWS VPC Traffic Mirroring</title><link>https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/aws-vpc-traffic-mirroring/</link><pubDate>Fri, 15 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/aws-vpc-traffic-mirroring/</guid><description>&lt;p>AWS VPC Traffic Mirroring 的核心責任是在 VPC 網路層複製 ENI traffic，讓團隊用低 application 侵入方式觀察 production flow。它適合封包級診斷、網路安全分析、流量樣本收集與部分 replay 前置資料蒐集，重點在明確定義 mirror source、filter、target、加密邊界與保存責任。&lt;/p>
&lt;h2 id="定位">定位&lt;/h2>
&lt;p>AWS VPC Traffic Mirroring 適合需要網路層能見度的 AWS workload。當 application code、service mesh 或 host capture 都不適合改動時，VPC 層 mirror 可以從 ENI 複製封包到 analysis appliance、IDS、packet capture 或自管處理服務。&lt;/p>
&lt;p>這個定位讓 AWS VPC Traffic Mirroring 接到 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/production-validation/" data-link-title="9.10 Production-Side 驗證" data-link-desc="shadow traffic、dark launch、canary、production-like load test">9.10 Production-Side 驗證&lt;/a> 的 shadow traffic 前置觀測。它偏封包觀察與樣本收集，若要做應用層 replay、filter、rewrite 或 side effect 隔離，通常還需要 GoReplay、proxy、custom processor 或測試環境配合。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/goreplay/" data-link-title="GoReplay" data-link-desc="用 production HTTP traffic capture 與 replay 驗證真實請求形狀的效能工程工具">GoReplay&lt;/a> 比、VPC Traffic Mirroring 走 &lt;em>無侵入 L3 packet copy&lt;/em>、GoReplay 走 &lt;em>application-level HTTP capture / rewrite&lt;/em>；跟 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/service-mesh-mirroring/" data-link-title="Service Mesh Mirroring" data-link-desc="用 sidecar / proxy 層 mirror production traffic 到新版本或 shadow service 的 production validation 方式">Service Mesh Mirroring&lt;/a> 比、VPC Mirror 在 ENI 層、Mesh Mirror 在 K8s pod 層；跟 AWS Network Firewall 比、Firewall 是 &lt;em>inline 阻擋&lt;/em>、Mirror 是 &lt;em>side-channel 觀察&lt;/em>、兩者目的不同但 packet path 相近。&lt;/p>
&lt;h2 id="最短判讀路徑">最短判讀路徑&lt;/h2>
&lt;p>判斷 VPC Traffic Mirroring deployment 是否健康、最少看四件事：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Source ENI selection&lt;/strong>：哪些 ENI 被 mirror（per-instance / per-subnet / 用 tag 自動選）、是否覆蓋瓶頸路徑上的關鍵節點（ALB target / NAT Gateway / RDS proxy / cross-AZ ENI）、漏掉哪個 ENI 就是 evidence 盲區&lt;/li>
&lt;li>&lt;strong>Filter rule 收斂&lt;/strong>：mirror filter 用 protocol / port / CIDR / direction 限定、避免「全 ENI 全 traffic」這種失控設定；filter 太寬會把 cross-AZ cost + target 處理量直接炸上去&lt;/li>
&lt;li>&lt;strong>Target NLB capacity&lt;/strong>：mirror target 是 ENI 或 NLB、target capacity（NLB flow / bandwidth）跟 source 流量比例要對得起來、target overload 會 drop 封包讓 evidence 失真&lt;/li>
&lt;li>&lt;strong>Sampling rate / packet length truncation&lt;/strong>：高流量服務不必 1:1 mirror、要設 &lt;code>packet_length&lt;/code> 截斷（只取 header）跟 mirror session ratio；忘設 sampling 等於整條 production 流量複製兩份、AWS bill 月底會出事&lt;/li>
&lt;/ul>
&lt;p>四件事任一缺失、就是 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/production-validation/" data-link-title="9.10 Production-Side 驗證" data-link-desc="shadow traffic、dark launch、canary、production-like load test">9.10 Production-Side 驗證&lt;/a> 邊界的待補項目。&lt;/p></description><content:encoded><![CDATA[<p>AWS VPC Traffic Mirroring 的核心責任是在 VPC 網路層複製 ENI traffic，讓團隊用低 application 侵入方式觀察 production flow。它適合封包級診斷、網路安全分析、流量樣本收集與部分 replay 前置資料蒐集，重點在明確定義 mirror source、filter、target、加密邊界與保存責任。</p>
<h2 id="定位">定位</h2>
<p>AWS VPC Traffic Mirroring 適合需要網路層能見度的 AWS workload。當 application code、service mesh 或 host capture 都不適合改動時，VPC 層 mirror 可以從 ENI 複製封包到 analysis appliance、IDS、packet capture 或自管處理服務。</p>
<p>這個定位讓 AWS VPC Traffic Mirroring 接到 <a href="/blog/backend/09-performance-capacity/production-validation/" data-link-title="9.10 Production-Side 驗證" data-link-desc="shadow traffic、dark launch、canary、production-like load test">9.10 Production-Side 驗證</a> 的 shadow traffic 前置觀測。它偏封包觀察與樣本收集，若要做應用層 replay、filter、rewrite 或 side effect 隔離，通常還需要 GoReplay、proxy、custom processor 或測試環境配合。</p>
<p>跟 <a href="/blog/backend/09-performance-capacity/vendors/goreplay/" data-link-title="GoReplay" data-link-desc="用 production HTTP traffic capture 與 replay 驗證真實請求形狀的效能工程工具">GoReplay</a> 比、VPC Traffic Mirroring 走 <em>無侵入 L3 packet copy</em>、GoReplay 走 <em>application-level HTTP capture / rewrite</em>；跟 <a href="/blog/backend/09-performance-capacity/vendors/service-mesh-mirroring/" data-link-title="Service Mesh Mirroring" data-link-desc="用 sidecar / proxy 層 mirror production traffic 到新版本或 shadow service 的 production validation 方式">Service Mesh Mirroring</a> 比、VPC Mirror 在 ENI 層、Mesh Mirror 在 K8s pod 層；跟 AWS Network Firewall 比、Firewall 是 <em>inline 阻擋</em>、Mirror 是 <em>side-channel 觀察</em>、兩者目的不同但 packet path 相近。</p>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 VPC Traffic Mirroring deployment 是否健康、最少看四件事：</p>
<ul>
<li><strong>Source ENI selection</strong>：哪些 ENI 被 mirror（per-instance / per-subnet / 用 tag 自動選）、是否覆蓋瓶頸路徑上的關鍵節點（ALB target / NAT Gateway / RDS proxy / cross-AZ ENI）、漏掉哪個 ENI 就是 evidence 盲區</li>
<li><strong>Filter rule 收斂</strong>：mirror filter 用 protocol / port / CIDR / direction 限定、避免「全 ENI 全 traffic」這種失控設定；filter 太寬會把 cross-AZ cost + target 處理量直接炸上去</li>
<li><strong>Target NLB capacity</strong>：mirror target 是 ENI 或 NLB、target capacity（NLB flow / bandwidth）跟 source 流量比例要對得起來、target overload 會 drop 封包讓 evidence 失真</li>
<li><strong>Sampling rate / packet length truncation</strong>：高流量服務不必 1:1 mirror、要設 <code>packet_length</code> 截斷（只取 header）跟 mirror session ratio；忘設 sampling 等於整條 production 流量複製兩份、AWS bill 月底會出事</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/09-performance-capacity/production-validation/" data-link-title="9.10 Production-Side 驗證" data-link-desc="shadow traffic、dark launch、canary、production-like load test">9.10 Production-Side 驗證</a> 邊界的待補項目。</p>
<h2 id="適用場景">適用場景</h2>
<p>網路層瓶頸定位適合 VPC Traffic Mirroring。當 latency、packet loss、TLS handshake、connection reset、NAT、load balancer 或 cross-AZ traffic 是疑點時，封包 mirror 能提供 application metrics 看不到的證據。</p>
<p>低侵入 traffic sampling 適合 VPC Traffic Mirroring。團隊可以在不改 application code 的情況下收集 production flow，作為 workload model、security analysis 或 replay pipeline 的輸入。</p>
<p>受管 AWS 網路環境適合 VPC Traffic Mirroring。當服務主要跑在 EC2 / ENI 可 mirror 的環境中，VPC 原生能力可以讓網路團隊用既有安全與觀測流程管理。</p>
<h2 id="選型判準">選型判準</h2>
<table>
  <thead>
      <tr>
          <th>判準</th>
          <th>AWS VPC Traffic Mirroring 的價值</th>
          <th>需要補的能力</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>網路層鏡像</td>
          <td>application 無侵入、封包級可見</td>
          <td>L7 解碼、filter、rewrite 與 replay</td>
      </tr>
      <tr>
          <td>AWS 原生</td>
          <td>VPC / ENI / filter / target 整合</td>
          <td>AWS 約束、跨帳號與跨 VPC 設計</td>
      </tr>
      <tr>
          <td>安全分析</td>
          <td>可接 IDS、packet analyzer、forensics</td>
          <td>PII / payload 保存與存取控制</td>
      </tr>
      <tr>
          <td>流量樣本</td>
          <td>可支援 workload model 校正</td>
          <td>加密 traffic 處理與樣本代表性</td>
      </tr>
  </tbody>
</table>
<p>網路層鏡像價值來自低侵入。團隊可以在不調整 application 或 service mesh 的情況下取得 flow evidence，但也要承擔 L7 語意不足的限制。</p>
<p>安全分析價值來自封包細節。對容量工程而言，封包證據能幫忙確認 connection、TLS、NAT、load balancer 與跨區流量成本；對資安而言，則能支援 IDS 與 forensic workflow。</p>
<h2 id="跟其他方式的取捨">跟其他方式的取捨</h2>
<p>AWS VPC Traffic Mirroring 和 GoReplay 的主要差異是層級。VPC mirroring 在 L3 / L4 觀察封包；GoReplay 更接近 HTTP application replay，對 request rewrite 與 target control 更直接。</p>
<p>AWS VPC Traffic Mirroring 和 service mesh mirroring 的主要差異是控制範圍。VPC mirroring 由網路層控制，適合低侵入封包觀察；service mesh mirroring 由 L7 route policy 控制，適合服務版本與 route 對照。</p>
<p>AWS VPC Traffic Mirroring 和 synthetic load test 的主要差異是用途。VPC mirroring 提供 production traffic evidence；synthetic load test 提供可控壓力。兩者常搭配：先用 mirror 校正 workload model，再用 k6 / Gatling / Locust 產生可控負載。</p>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>AWS VPC Traffic Mirroring</th>
          <th>GoReplay</th>
          <th>Service Mesh Mirroring</th>
          <th>AWS Network Firewall</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>鏡像層級</td>
          <td>L3 / L4 packet copy</td>
          <td>L7 HTTP capture + replay</td>
          <td>L7 pod-level（Istio / Linkerd）</td>
          <td>L3-L7 inline filter（非 mirror）</td>
      </tr>
      <tr>
          <td>Application 侵入</td>
          <td>無 — ENI 層、code 不改</td>
          <td>中 — 需 sidecar / capture host</td>
          <td>中 — service mesh 必須先佈</td>
          <td>無 — VPC gateway 層</td>
      </tr>
      <tr>
          <td>Replay 能力</td>
          <td>弱 — 需自接 packet replayer</td>
          <td>強 — 內建 request rewrite</td>
          <td>中 — mirror to shadow service</td>
          <td>無</td>
      </tr>
      <tr>
          <td>適用場景</td>
          <td>network forensics / IDS / 容量分析</td>
          <td>HTTP regression / load replay</td>
          <td>K8s service-level shadow test</td>
          <td>inline 阻擋 / IDS / IPS</td>
      </tr>
      <tr>
          <td>加密 payload</td>
          <td>看不到 — TLS 仍密</td>
          <td>看得到 — application 解密後</td>
          <td>看得到 — mesh sidecar 已 TLS terminate</td>
          <td>partial — TLS inspection 需另設</td>
      </tr>
      <tr>
          <td>成本</td>
          <td>per-ENI / cross-AZ traffic</td>
          <td>計算 + 儲存</td>
          <td>mesh overhead + shadow service</td>
          <td>per-GB processed</td>
      </tr>
  </tbody>
</table>
<h2 id="操作成本">操作成本</h2>
<p>AWS VPC Traffic Mirroring 的主要成本是資料治理。Mirror target 可能收到 payload、token、cookie、internal identifiers 與敏感資料，因此保存、查詢、保留期限、存取權與刪除責任要先定義。</p>
<p>網路成本來自複製 traffic。Mirror session 會增加網路流量與 target processing 成本，高流量服務要先估算 mirror ratio、filter、target capacity 與跨 AZ 費用。</p>
<p>加密成本來自 L7 可讀性。TLS traffic 在網路層 mirror 後通常仍是加密封包；若需要 application payload，要搭配解密點、proxy、key 管理或 application-level capture。</p>
<h2 id="evidence-package">Evidence Package</h2>
<p>AWS VPC Traffic Mirroring 結果應回寫到 evidence package。最小欄位包括 mirror source ENI、filter rule、mirror target、session number、time range、sampling / truncation、target capacity、payload handling、packet metrics、known gap 與 owner。</p>
<table>
  <thead>
      <tr>
          <th>欄位</th>
          <th>AWS VPC Traffic Mirroring 證據來源</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Source</td>
          <td>mirror session、filter、target config</td>
      </tr>
      <tr>
          <td>Time range</td>
          <td>mirror start / end</td>
      </tr>
      <tr>
          <td>Query link</td>
          <td>packet analyzer、flow logs、metrics link</td>
      </tr>
      <tr>
          <td>Data quality</td>
          <td>filter coverage、sampling、encryption status</td>
      </tr>
      <tr>
          <td>Confidence</td>
          <td>target capacity、source coverage</td>
      </tr>
      <tr>
          <td>Known gap</td>
          <td>加密 payload、未 mirror ENI、L7 語意不足</td>
      </tr>
  </tbody>
</table>
<p>Evidence package 的核心用途是把網路層觀察接回效能判斷。Reviewer 要能知道 mirror 覆蓋哪些 ENI、哪些封包被 filter、target 是否有 capacity，以及封包證據如何對應到 application latency 或 saturation。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Filter rule 設計</strong>：mirror filter 支援 source CIDR / dest CIDR / protocol / port range / direction（ingress / egress）、rule number 決定 evaluation 順序。production 慣例是 <em>最小覆蓋原則</em> — 先用 <code>port 443 + dest CIDR = ALB target group</code> 限定到關鍵 path、再依需要擴張。filter 寫太寬會把 control-plane heartbeat、health check、internal RPC 全部 mirror 進來、target 處理量瞬間爆掉。</p>
<p><strong>跟 IDS / packet analyzer 整合</strong>：mirror target 接 ENI 後常見的下游堆疊是 <em>Zeek</em>（前 Bro、生成 connection log / protocol log）、<em>Suricata</em>（rule-based IDS / IPS 偵測）、<em>Wireshark / tshark</em>（離線封包分析）。實務上 mirror → NLB → 自管 EC2 跑 Zeek 產 JSON log → 進 <a href="/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &#43; CSPM &#43; CWS &#43; AAP &#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog</a> / Splunk 做 correlation。容量工程關心 connection reset 跟 retransmit、資安關心 protocol anomaly、共用同一份 mirror feed。</p>
<p><strong>Replay 到 staging cluster</strong>：mirror feed 不能直接 replay（沒有 stateful 重組），但可以接 packet replayer（tcpreplay / GoReplay packet mode）把樣本送到 staging。要注意 <em>side effect 隔離</em> — staging 的 DB / external API 不應該真的執行寫入、否則 mirror 變成 production fanout。</p>
<p><strong>Traffic analysis platform 整合</strong>：mirror 取得的 packet evidence 通常進 <a href="/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &#43; CSPM &#43; CWS &#43; AAP &#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Network Performance Monitoring</a> 做 NPM dashboard、或進 Splunk Stream app 做 SIEM correlation。整合的關鍵是 <em>時間軸對齊</em> — packet timestamp、application log、metrics 三者要同步、否則 root cause 拼不回去。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Target NLB capacity 不夠 / drop packet</strong>：mirror traffic 量超過 NLB flow limit、packet 被 silently drop — 拆 mirror session 到多個 target、開 NLB flow log 看 drop reason、必要時改用 Gateway Load Balancer</li>
<li><strong>Filter rule 太寬導致流量爆</strong>：「mirror 所有 traffic」設定上線後 target ENI 跟 cross-AZ bandwidth 雙重炸 — 立刻關掉 session、改用 dest CIDR / port 收斂、加 <code>packet_length</code> 截斷只取 header</li>
<li><strong>Cross-AZ mirror cost 暴增</strong>：source ENI 跟 target 在不同 AZ、每個封包複製都收 cross-AZ traffic 費 — target NLB 部署到每個 AZ、用 AZ-affinity routing、或把 mirror target 限定在 source 同 AZ</li>
<li><strong>TLS payload 看不到</strong>：mirror 拿到加密封包、L7 內容無法分析 — 把解密點移到 ALB / NLB-TLS termination、或在 application 層加 capture（不再用 VPC mirror）</li>
<li><strong>Mirror session 漏掉新 instance</strong>：autoscaling 起新 instance 沒自動加入 mirror — 用 mirror target by tag、Terraform / CloudFormation 把 mirror session 寫進 ASC launch template</li>
<li><strong>Packet timestamp 不對齊 application log</strong>：mirror packet 時間是 source ENI capture 時間、不是 application processing 時間、做 latency 分析會偏差 — 用 packet 5-tuple + request ID 對齊 application log、不要直接相減 timestamp</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>AWS VPC Traffic Mirroring 適合回寫網路與平台層效能案例。它可接 <a href="/blog/backend/09-performance-capacity/cases/gcp-130k-node-gke-cluster/" data-link-title="9.C34 GCP：130,000-node GKE cluster 的工程極限" data-link-desc="Google 用單一 GKE control plane 跑 13 萬個 node、AI workload &#43; 1000 Pods/sec 創建吞吐">9.C34 GCP 130K node GKE cluster</a> 的大規模網路觀測需求（雖在 GCP、但網路證據的層次拆解可類比）、<a href="/blog/backend/09-performance-capacity/cases/wayfair-gcp-burst-capacity/" data-link-title="9.C22 Wayfair：用 GCP 提供 Way Day / Black Friday 的 burst capacity" data-link-desc="Wayfair 22M&#43; 商品 &#43; 16,000&#43; 供應商、用 GCP 補充 on-prem data center 在峰值事件的 burst capacity">9.C22 Wayfair GCP burst capacity</a> 的跨雲容量觀測、<a href="/blog/backend/09-performance-capacity/cases/aws-prime-day-extreme-scale-2025/" data-link-title="9.C1 AWS Prime Day 2025：可預期極端峰值的 dogfood" data-link-desc="Amazon 自家服務在 Prime Day 2025 的峰值數字 — 一年一次可預期峰值的容量設計參考">9.C1 Prime Day readiness</a> 的 pre-event network evidence、<a href="/blog/backend/09-performance-capacity/cases/riot-games-eks-multi-cluster/" data-link-title="9.C12 Riot Games：246 個 EKS cluster 的多遊戲多地區治理" data-link-desc="Riot Games 從 Mesos 遷移到 EKS、用 246 個 cluster 跨遊戲跨地區治理、年省 1000 萬美金">9.C12 Riot Games 246 EKS cluster</a> 跨 cluster 的網路流量觀測、以及 <a href="/blog/backend/09-performance-capacity/cases/genesys-dynamodb-99999-availability/" data-link-title="9.C24 Genesys：用 DynamoDB 在 15 region 跑出 99.999% 可用性" data-link-desc="Genesys 客服平台用 DynamoDB 為預設資料層、跨 15 主 region &#43; 5 衛星 region、達成 12 個月 99.999% 可用性">9.C24 Genesys DynamoDB 15-region</a> 的 99.999% 可用性下封包層 evidence 補強。</p>
<p>這些案例的重點是網路層 evidence。VPC Traffic Mirroring 頁引用案例時，要把 case 轉成 mirror source、filter、target capacity、packet metric、cross-AZ cost 與 L7 correlation — 例如 Riot Games 35ms 延遲門檻下、cross-AZ traffic mirror 本身會增加成本、必須先用 filter 收斂到關鍵 ENI。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/09-performance-capacity/production-validation/" data-link-title="9.10 Production-Side 驗證" data-link-desc="shadow traffic、dark launch、canary、production-like load test">9.10 Production-Side 驗證</a></li>
<li>上游：<a href="/blog/backend/09-performance-capacity/bottleneck-localization/" data-link-title="9.5 瓶頸定位流程" data-link-desc="從 app 到 DB / cache / broker / 第三方 quota 的逐層瓶頸定位">9.5 瓶頸定位流程</a></li>
<li>平行：<a href="/blog/backend/09-performance-capacity/vendors/goreplay/" data-link-title="GoReplay" data-link-desc="用 production HTTP traffic capture 與 replay 驗證真實請求形狀的效能工程工具">GoReplay</a></li>
<li>平行：<a href="/blog/backend/09-performance-capacity/vendors/service-mesh-mirroring/" data-link-title="Service Mesh Mirroring" data-link-desc="用 sidecar / proxy 層 mirror production traffic 到新版本或 shadow service 的 production validation 方式">Service Mesh Mirroring</a></li>
<li>知識卡：<a href="/blog/backend/knowledge-cards/shadow-traffic/" data-link-title="Shadow Traffic" data-link-desc="把 production traffic 複製到新版本驗證、但不返回結果給用戶的測試模式">Shadow Traffic</a></li>
<li>官方：<a href="https://docs.aws.amazon.com/vpc/latest/mirroring/what-is-traffic-mirroring.html">AWS VPC Traffic Mirroring documentation</a></li>
</ul>
]]></content:encoded></item><item><title>CloudHealth</title><link>https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/cloudhealth/</link><pubDate>Fri, 15 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/cloudhealth/</guid><description>&lt;p>CloudHealth 的核心責任是把大型組織的 cloud spend、governance、policy、allocation 與 optimization workflow 放進同一個 FinOps 管理平面。它適合 account、team、business unit、provider 與採購流程複雜的組織，重點在讓成本治理、合規要求與工程 owner 能共用同一套成本事實。2018 年被 VMware 收購、2023 年隨 VMware 進入 Broadcom 旗下；現屬 Broadcom 的 enterprise FinOps 旗艦產品。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>CloudHealth 跟 AWS Cost Explorer / Azure Cost Management 那種單雲原生工具的差異在 &lt;em>跨雲一致 schema + enterprise FinOps operating model&lt;/em>、單雲帳單細節反而是原生工具更深。Cost Explorer 在 AWS-only 場景的 granularity 更深、但跨 Azure / GCP 帳單對齊、成本中心 chargeback、policy 治理就需要 CloudHealth 這類 multi-cloud platform。&lt;/p>
&lt;p>跟 Vantage 比、CloudHealth 走 &lt;em>enterprise governance-first&lt;/em>、Vantage 走 &lt;em>engineering-friendly dashboard-first&lt;/em>。Vantage 對小到中型 cloud-native 團隊更快上手、但 chargeback 流程、policy violation queue、approval workflow 都不是它的主場。跟 Apptio Cloudability（IBM 收購）比、兩者定位最接近、都吃 large enterprise FinOps 市場；CloudHealth 的差異是 VMware / Broadcom ecosystem 整合（vCenter / Tanzu / on-prem hybrid），Cloudability 強在 TBM（Technology Business Management）財務分攤模型成熟度。&lt;/p>
&lt;p>關鍵張力：&lt;em>Broadcom 收購後的 product roadmap 不確定性&lt;/em> ↔ &lt;em>enterprise FinOps ecosystem 深度&lt;/em>。Broadcom 對 VMware portfolio 的價格調整、partner 縮編、support tier 變動 2024-2025 持續發生；客戶要評估 &lt;em>退場成本（chargeback rule + tag taxonomy 量大）vs 短期 license 漲幅&lt;/em>、不是只看當下功能。&lt;/p>
&lt;h2 id="定位">定位&lt;/h2>
&lt;p>CloudHealth 適合 enterprise FinOps 與 cloud governance。當組織需要跨 AWS、Azure、Google Cloud、Kubernetes、shared services 與成本中心建立 showback、chargeback、policy 與 optimization workflow，CloudHealth 類平台可以提供集中式成本管理與治理視角。&lt;/p>
&lt;p>這個定位讓 CloudHealth 接到三個主章。它從 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cost-engineering/" data-link-title="9.7 成本邊界與 efficiency" data-link-desc="cost per request、cost curve、降級成本、over-provisioning trade-off">9.7 成本邊界與 efficiency&lt;/a> 接收 cost curve 與 over-provision waste，從 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/performance-observability/" data-link-title="9.8 效能可觀測性" data-link-desc="saturation metric、USE / RED method、cost dashboard">9.8 效能可觀測性&lt;/a> 接收成本 dashboard 需求，從 &lt;a href="https://tarrragon.github.io/blog/backend/04-observability/cost-attribution/" data-link-title="4.15 Cost Attribution / Chargeback" data-link-desc="把 observability 成本拆到團隊、產品、環境維度">04 可觀測性成本歸因&lt;/a> 接收 owner、tag 與 attribution 規則。&lt;/p>
&lt;h2 id="適用場景">適用場景&lt;/h2>
&lt;p>多雲成本治理是 CloudHealth 的主要入口。大型企業常有不同 cloud provider、不同採購合約、不同 account 結構與不同團隊成熟度；CloudHealth 可以把成本、資產、policy 與權限治理收斂到 FinOps 工作流程。&lt;/p></description><content:encoded><![CDATA[<p>CloudHealth 的核心責任是把大型組織的 cloud spend、governance、policy、allocation 與 optimization workflow 放進同一個 FinOps 管理平面。它適合 account、team、business unit、provider 與採購流程複雜的組織，重點在讓成本治理、合規要求與工程 owner 能共用同一套成本事實。2018 年被 VMware 收購、2023 年隨 VMware 進入 Broadcom 旗下；現屬 Broadcom 的 enterprise FinOps 旗艦產品。</p>
<h2 id="服務定位">服務定位</h2>
<p>CloudHealth 跟 AWS Cost Explorer / Azure Cost Management 那種單雲原生工具的差異在 <em>跨雲一致 schema + enterprise FinOps operating model</em>、單雲帳單細節反而是原生工具更深。Cost Explorer 在 AWS-only 場景的 granularity 更深、但跨 Azure / GCP 帳單對齊、成本中心 chargeback、policy 治理就需要 CloudHealth 這類 multi-cloud platform。</p>
<p>跟 Vantage 比、CloudHealth 走 <em>enterprise governance-first</em>、Vantage 走 <em>engineering-friendly dashboard-first</em>。Vantage 對小到中型 cloud-native 團隊更快上手、但 chargeback 流程、policy violation queue、approval workflow 都不是它的主場。跟 Apptio Cloudability（IBM 收購）比、兩者定位最接近、都吃 large enterprise FinOps 市場；CloudHealth 的差異是 VMware / Broadcom ecosystem 整合（vCenter / Tanzu / on-prem hybrid），Cloudability 強在 TBM（Technology Business Management）財務分攤模型成熟度。</p>
<p>關鍵張力：<em>Broadcom 收購後的 product roadmap 不確定性</em> ↔ <em>enterprise FinOps ecosystem 深度</em>。Broadcom 對 VMware portfolio 的價格調整、partner 縮編、support tier 變動 2024-2025 持續發生；客戶要評估 <em>退場成本（chargeback rule + tag taxonomy 量大）vs 短期 license 漲幅</em>、不是只看當下功能。</p>
<h2 id="定位">定位</h2>
<p>CloudHealth 適合 enterprise FinOps 與 cloud governance。當組織需要跨 AWS、Azure、Google Cloud、Kubernetes、shared services 與成本中心建立 showback、chargeback、policy 與 optimization workflow，CloudHealth 類平台可以提供集中式成本管理與治理視角。</p>
<p>這個定位讓 CloudHealth 接到三個主章。它從 <a href="/blog/backend/09-performance-capacity/cost-engineering/" data-link-title="9.7 成本邊界與 efficiency" data-link-desc="cost per request、cost curve、降級成本、over-provisioning trade-off">9.7 成本邊界與 efficiency</a> 接收 cost curve 與 over-provision waste，從 <a href="/blog/backend/09-performance-capacity/performance-observability/" data-link-title="9.8 效能可觀測性" data-link-desc="saturation metric、USE / RED method、cost dashboard">9.8 效能可觀測性</a> 接收成本 dashboard 需求，從 <a href="/blog/backend/04-observability/cost-attribution/" data-link-title="4.15 Cost Attribution / Chargeback" data-link-desc="把 observability 成本拆到團隊、產品、環境維度">04 可觀測性成本歸因</a> 接收 owner、tag 與 attribution 規則。</p>
<h2 id="適用場景">適用場景</h2>
<p>多雲成本治理是 CloudHealth 的主要入口。大型企業常有不同 cloud provider、不同採購合約、不同 account 結構與不同團隊成熟度；CloudHealth 可以把成本、資產、policy 與權限治理收斂到 FinOps 工作流程。</p>
<p>Showback / chargeback 適合用 CloudHealth 建立財務語言。成本中心、部門、產品線、環境與專案需要穩定分攤規則，才能讓工程決策接到預算管理、採購承諾與年度規劃。</p>
<p>Optimization workflow 適合用 CloudHealth 管理組織節奏。Rightsizing、reserved capacity、idle resource、tag compliance 與 policy violation 都需要 owner、例外、核准、驗證與追蹤，enterprise 平台的價值在於流程一致。</p>
<h2 id="選型判準">選型判準</h2>
<table>
  <thead>
      <tr>
          <th>判準</th>
          <th>CloudHealth 的價值</th>
          <th>需要補的能力</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>組織治理</td>
          <td>支援多 account、多團隊、成本中心與 policy</td>
          <td>FinOps operating model、owner taxonomy</td>
      </tr>
      <tr>
          <td>成本分攤</td>
          <td>支援 showback / chargeback 與 shared cost rule</td>
          <td>tag hygiene、成本中心對照表</td>
      </tr>
      <tr>
          <td>最佳化流程</td>
          <td>支援 rightsizing、commitment 與 policy action</td>
          <td>工程驗證、變更排程、saving confirmation</td>
      </tr>
      <tr>
          <td>Enterprise 整合</td>
          <td>適合採購、財務、平台與工程共同使用</td>
          <td>權限模型、報表治理、例外處理</td>
      </tr>
  </tbody>
</table>
<p>組織治理價值來自一致流程。單一工程團隊可以靠雲端原生工具追成本；大型組織需要 policy、role、approval、exception 與 audit trail 才能讓成本治理長期運作。</p>
<p>成本分攤價值來自可對帳。Showback / chargeback 要能讓財務、平台與服務 owner 對同一筆費用得到相同解釋，shared platform cost、discount、support fee 與 commitment benefit 都要有分攤規則。</p>
<p>最佳化流程價值來自閉環管理。Rightsizing recommendation 只有在 owner 接手、服務驗證、變更落地與 saving confirmation 完成後，才會變成實際成本改善。</p>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 CloudHealth deployment 是否健康、最少看四件事：</p>
<ul>
<li><strong>Multi-cloud connector 完整性</strong>：AWS（CUR / billing role）、Azure（EA / MCA billing role）、GCP（BigQuery billing export）、Kubernetes（kube-state-metrics + Prometheus）連接器是否都接通、是否有 daily ingestion lag、是否漏 account / subscription</li>
<li><strong>FinOps team workflow 落地</strong>：policy queue、recommendation queue、approval flow 是否有實際 owner（不只是 dashboard 看一看）、weekly / monthly FinOps cadence 是否進到工程 sprint 跟財務 close cycle</li>
<li><strong>Chargeback 規則可對帳</strong>：business unit / cost center / application / environment 的分攤公式是否文件化、shared service（platform team / CI runner / observability stack）的 split rule 是否被各 BU 接受、月底財務 close 對得起來</li>
<li><strong>Reserved Instance / Savings Plan 管理</strong>：commitment coverage（已 commit 比例）、utilization（已用比例）、expiration alert、跨 account 的 commitment sharing 是否有 owner 主動經營、不是買完就放著</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/09-performance-capacity/cost-engineering/" data-link-title="9.7 成本邊界與 efficiency" data-link-desc="cost per request、cost curve、降級成本、over-provisioning trade-off">9.7 成本邊界與 efficiency</a> 邊界的待補項目。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>CloudHealth</th>
          <th>Vantage</th>
          <th>AWS Cost Explorer</th>
          <th>Apptio Cloudability</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Multi-cloud</td>
          <td>強 — AWS / Azure / GCP / K8s</td>
          <td>強 — 加 Snowflake / Datadog 整合</td>
          <td>弱 — AWS-only</td>
          <td>強 — 三大雲 + on-prem</td>
      </tr>
      <tr>
          <td>學習曲線</td>
          <td>陡 — enterprise model 複雜</td>
          <td>緩 — engineer 友善 dashboard</td>
          <td>緩 — AWS console 內建</td>
          <td>陡 — TBM 模型門檻高</td>
      </tr>
      <tr>
          <td>Chargeback</td>
          <td>強 — policy + approval flow 完整</td>
          <td>中 — report-driven、流程靠外掛</td>
          <td>弱 — 報表為主、無 workflow</td>
          <td>強 — TBM 財務分攤是主場</td>
      </tr>
      <tr>
          <td>部署模型</td>
          <td>SaaS only</td>
          <td>SaaS only</td>
          <td>AWS console 內建</td>
          <td>SaaS only</td>
      </tr>
      <tr>
          <td>適合規模</td>
          <td>Enterprise（多 BU + 多雲）</td>
          <td>Startup ~ Mid（cloud-native）</td>
          <td>AWS single-account ~ Org</td>
          <td>Enterprise（重財務治理）</td>
      </tr>
      <tr>
          <td>計費模型</td>
          <td>% of cloud spend + minimum</td>
          <td>Per-cloud-account tier</td>
          <td>Free（AWS 內建）</td>
          <td>% of cloud spend + minimum</td>
      </tr>
      <tr>
          <td>Roadmap 風險</td>
          <td>Broadcom 收購後不確定</td>
          <td>獨立公司、roadmap 穩定</td>
          <td>AWS 自家、roadmap 跟雲同步</td>
          <td>IBM 收購後整合中</td>
      </tr>
      <tr>
          <td>退場成本</td>
          <td>高 — chargeback rule + tag 量大</td>
          <td>低 — report 可重建</td>
          <td>無 — AWS-native 切換無痛</td>
          <td>高 — TBM 模型重 migrate</td>
      </tr>
  </tbody>
</table>
<p>選 CloudHealth 的核心訴求：<em>enterprise scale + 多雲 + 已有 VMware / Broadcom ecosystem</em>、且能投入 FinOps team 維護 chargeback rule、policy queue、commitment management lifecycle。中小型 cloud-native 走 Vantage 更快；AWS-only 直接用 Cost Explorer + Cost Anomaly Detection；重財務 TBM 整合走 Apptio Cloudability。</p>
<h2 id="跟其他工具的取捨">跟其他工具的取捨</h2>
<p>CloudHealth 和 Vantage 的主要差異是治理深度。Vantage 偏工程友善報表與 Kubernetes cost visibility；CloudHealth 偏 enterprise FinOps operating model、policy 與大組織分攤流程。</p>
<p>CloudHealth 和 Akamas 的主要差異是最佳化方式。CloudHealth 偏成本治理與推薦流程；Akamas 偏把 SLO 約束與 configuration tuning 放進 optimization engine。</p>
<p>CloudHealth 和 AWS Cost Explorer 的主要差異是多雲與流程。Cost Explorer 適合 AWS-native 成本分析；CloudHealth 適合跨 provider、跨成本中心與跨團隊治理。</p>
<h2 id="操作成本">操作成本</h2>
<p>CloudHealth 的主要成本是組織模型維護。Business unit、cost center、application、environment、owner、account 與 tag policy 需要持續治理，平台才能提供穩定報表。</p>
<p>流程成本會高於單純報表工具。Recommendation 需要進入 approval、exception、change management、validation 與 financial close process；這些流程讓工具適合大型組織，也要求更高維運紀律。</p>
<p>資料品質成本會集中在標籤與 shared cost。未標記資源、跨團隊 shared service、commitment benefit 分攤與 marketplace charge 都會影響成本歸屬信任度。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Reserved Instance 與 Savings Plan management</strong>：CloudHealth 把 commitment 視為 portfolio、不是單筆採購。Coverage（已 commit 比例）、utilization（已用比例）、break-even（攤平時間）三個指標要持續追、跟業務 roadmap 對齊；新服務上線前先 model 預期用量、commit 太多反而 lock-in 浪費、太少又付 on-demand 溢價。跨 account / linked account 的 commitment sharing 要明確 owner、不然 platform team 買的 RI 被 product team 吃掉、財務分攤回不去。</p>
<p><strong>Chargeback / showback 流程</strong>：showback 是 <em>讓 BU 看到自己花多少</em>、chargeback 是 <em>讓 BU 帳本上真的扣這筆</em>。chargeback 需要財務簽核、需要每月 close cycle、需要 dispute 機制；CloudHealth 的 chargeback rule 改動要走 approval、不能 admin 自己改完就上線、會直接影響 BU 月結。</p>
<p><strong>Multi-cloud asset inventory</strong>：CloudHealth 不只是帳單工具、也作 asset inventory — EC2 / RDS / VM / GKE node / Azure SQL 等資源的 owner、tag、environment、policy state 在同一視角。這個能力是 enterprise CMDB integration 的入口、也能反向支援 <a href="/blog/backend/07-security-data-protection/" data-link-title="模組七：資安與資料保護" data-link-desc="以問題驅動方式擴充資安知識網：先定義服務環節問題，再以案例作為觸發式參考">7 security posture</a> 的 untagged / unauthorized resource 偵測。</p>
<p><strong>跟 Datadog / SIEM integration</strong>：CloudHealth 的 cost data 可以 export 到 <a href="/blog/backend/04-observability/vendors/datadog/" data-link-title="Datadog" data-link-desc="All-in-one SaaS 觀測平台、APM / Logs / Metrics / RUM / Security">Datadog</a> 作 SRE cost-aware alert（service 突然花費暴衝 → 通常是 retry storm / runaway job），也可送 SIEM 作 untagged resource / cross-account spend anomaly 偵測。整合的價值不是把 CloudHealth 當另一個 observability tool、而是讓 cost signal 進到工程值班的視野。</p>
<p><strong>Broadcom 收購後 product roadmap 變動風險</strong>：2023 Broadcom 完成 VMware 收購後、CloudHealth 經歷 license model 調整、partner program 變動、support tier 重整。對既有大客戶來說 license 漲幅、SLA 條款、roadmap 透明度都進入再評估期；新客戶選型時 <em>退場成本評估</em> 要先做、不能假設 platform 五年不變。Broadcom 對 enterprise 客戶仍會維持產品線、但中小客戶可能感受到 support 縮減。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Multi-cloud tag 不一致</strong>：AWS 用 <code>Environment=prod</code>、Azure 用 <code>env=production</code>、GCP 用 <code>env-tier=prod</code> — CloudHealth 報表看起來三套不同 — 統一 tag taxonomy（cost center / application / environment / owner）寫進 cloud governance policy、用 cloud-native enforcement（AWS Tag Policy / Azure Policy / GCP Org Policy）擋未標記資源</li>
<li><strong>Chargeback 對不上帳</strong>：BU 看到的金額 ≠ 財務 close 的金額 — shared service split rule 沒被簽核、commitment benefit attribution 跑掉、marketplace charge 沒分攤 — 走 monthly close reconciliation、把 rule 鎖定後才開 dispute window</li>
<li><strong>Reserved Instance 浪費</strong>：commit 買了沒用滿（utilization &lt; 80%）— 跨 account share 沒開、或業務 roadmap 改了沒同步 commitment team — 開 cross-account RI sharing、commitment review 進 monthly FinOps cadence</li>
<li><strong>新雲帳號接不進來</strong>：connector 一直 ingestion failure — IAM role / EA permission / BigQuery export 沒設好、或 organization 結構改了 CloudHealth 沒同步 — 走 onboarding checklist、新 account 自動化納管</li>
<li><strong>Recommendation 一直沒人 action</strong>：rightsizing queue 累積幾百筆沒處理 — 沒有 owner、或 recommendation 沒對應到實際 service team — 用 tag 反查 owner、把 recommendation 進 sprint backlog 而非 FinOps 自己追</li>
<li><strong>Broadcom 收購後 support / price 變動</strong>：renewal 漲幅突然 30-50%、support tier 被降級 — 早一年開始評估替代方案（Vantage / Apptio / 雲原生組合）、把 chargeback rule 跟 tag taxonomy 抽象到不綁 vendor 的格式</li>
</ul>
<h2 id="evidence-package">Evidence Package</h2>
<p>CloudHealth 結果應回寫到 FinOps governance evidence package。最小欄位包括 business unit、cost center、application、provider、account、policy、recommendation、expected saving、approval state、implementation state、verified saving 與 exception。</p>
<table>
  <thead>
      <tr>
          <th>欄位</th>
          <th>CloudHealth 證據來源</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Source</td>
          <td>cost report、policy report、recommendation queue</td>
      </tr>
      <tr>
          <td>Time range</td>
          <td>billing period、review cycle、saving validation window</td>
      </tr>
      <tr>
          <td>Query link</td>
          <td>CloudHealth report、cloud billing query、policy detail</td>
      </tr>
      <tr>
          <td>Data quality</td>
          <td>tag compliance、account coverage、allocation rule</td>
      </tr>
      <tr>
          <td>Confidence</td>
          <td>owner mapping、approval status、verified saving</td>
      </tr>
      <tr>
          <td>Known gap</td>
          <td>shared service rule、manual exception、provider delay</td>
      </tr>
  </tbody>
</table>
<p>Evidence package 的核心用途是支援治理審查。CloudHealth report 要能回答「這筆成本屬於誰、哪條 policy 觸發、誰核准例外、變更是否真的帶來 savings」。</p>
<h2 id="案例回寫">案例回寫</h2>
<p>CloudHealth 目前適合作為 enterprise FinOps 與多雲治理案例的工具承接點。它可回寫到 <a href="/blog/backend/09-performance-capacity/cases/standard-chartered-aurora-banking/" data-link-title="9.C14 Standard Chartered：受監管銀行的 Aurora 4000 TPS 容量提升" data-link-desc="Standard Chartered 銀行遷移到 Aurora 後吞吐量提升 10 倍至 4000 TPS、跨 7 個受監管市場">9.C14 Standard Chartered</a> 的 7 個受監管市場跨地區治理與成本中心分攤需求、<a href="/blog/backend/09-performance-capacity/cases/maersk-bosch-azure-aks/" data-link-title="9.C33 Maersk &#43; Bosch：傳統產業在 Azure AKS 上的微服務治理" data-link-desc="全球海運 Maersk 跟 Bosch 智慧建築把 AKS 當微服務治理基礎、釋放工程資源做業務功能">9.C33 Maersk + Bosch on Azure AKS</a> 的傳統產業多 BU 治理一致性、<a href="/blog/backend/09-performance-capacity/cases/wayfair-gcp-burst-capacity/" data-link-title="9.C22 Wayfair：用 GCP 提供 Way Day / Black Friday 的 burst capacity" data-link-desc="Wayfair 22M&#43; 商品 &#43; 16,000&#43; 供應商、用 GCP 補充 on-prem data center 在峰值事件的 burst capacity">9.C22 Wayfair hybrid burst</a> 的 on-prem + GCP 雙來源帳單合併、以及 <a href="/blog/backend/09-performance-capacity/cases/snap-gcp-keydb-cross-cloud/" data-link-title="9.C35 Snap：GCP &#43; KeyDB 在 multi-cloud 架構下的低延遲快取" data-link-desc="Snap 用 GCP 上的 KeyDB cluster 減少跨 cloud cache 延遲、用 TPU 訓練廣告推薦模型">9.C35 Snap multi-cloud</a> 的 GCP + AWS 跨雲成本對照。</p>
<p>這些案例的重點是組織能力。CloudHealth 頁引用案例時，要把案例拆成 governance model、owner taxonomy、policy action、engineering validation 與 financial reporting — 例如 Standard Chartered 的 7 市場分割要回到 per-market policy + 合規 tag、不是單一全球 report、而非停在雲端帳單下降。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/09-performance-capacity/cost-engineering/" data-link-title="9.7 成本邊界與 efficiency" data-link-desc="cost per request、cost curve、降級成本、over-provisioning trade-off">9.7 成本邊界與 efficiency</a></li>
<li>上游：<a href="/blog/backend/09-performance-capacity/performance-observability/" data-link-title="9.8 效能可觀測性" data-link-desc="saturation metric、USE / RED method、cost dashboard">9.8 效能可觀測性</a></li>
<li>跨模組：<a href="/blog/backend/04-observability/cost-attribution/" data-link-title="4.15 Cost Attribution / Chargeback" data-link-desc="把 observability 成本拆到團隊、產品、環境維度">04 可觀測性成本歸因</a></li>
<li>平行：<a href="/blog/backend/09-performance-capacity/vendors/vantage/" data-link-title="Vantage" data-link-desc="用 cloud cost reports、Kubernetes cost allocation 與 forecast 建立工程可用的成本可見性">Vantage</a></li>
<li>官方：<a href="https://news.broadcom.com/apj/releases/broadcom-announces-new-cloudhealth-user-experience-for-greater-cloud-spend-management-across-enterprise-teams">Broadcom CloudHealth announcement</a></li>
</ul>
]]></content:encoded></item><item><title>Conftest</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/conftest/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/conftest/</guid><description>&lt;p>Conftest 是 &lt;em>OPA CLI wrapper for static config policy check&lt;/em>、Open Policy Agent project 旗下的 CLI 工具、Apache 2.0 OSS、無商業版。它的核心定位是 &lt;em>CI-time policy gate&lt;/em>、有別於 admission runtime：在 git commit / PR / merge 階段、用 Rego policy 對 config file（Terraform HCL / K8s YAML / Dockerfile / JSON / TOML / INI / serverless.yml）做 static check、把 misconfiguration 攔在 deploy 之前。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/opa/" data-link-title="Open Policy Agent (OPA)" data-link-desc="CNCF general-purpose policy engine、Rego Datalog-like 語言、decoupled decision &amp;#43; enforcement、跨 K8s / API / Terraform / SQL 統一 policy">OPA&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &amp;#43; Constraint 兩層、Rego policy &amp;#43; Audit &amp;#43; Mutation">Gatekeeper&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &amp;#43; Secret &amp;#43; License &amp;#43; SBOM、Apache 2.0、CI 友善">Trivy&lt;/a> Config 的差異在 &lt;em>執行時機 + 客製化方式&lt;/em>、規則表達力反而相近。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Conftest 是 OPA 生態中 &lt;em>最輕量的 CI-time tool&lt;/em> — 拿一份 Rego policy + 一份 config file、跑 &lt;code>conftest test&lt;/code> 就出 violation report。它不需要 cluster、不需要 daemon、不接 admission webhook、只是個 binary。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/opa/" data-link-title="Open Policy Agent (OPA)" data-link-desc="CNCF general-purpose policy engine、Rego Datalog-like 語言、decoupled decision &amp;#43; enforcement、跨 K8s / API / Terraform / SQL 統一 policy">OPA&lt;/a> 比、OPA 是 &lt;em>runtime decision engine&lt;/em>（HTTP server / library / sidecar 提供 policy decision）、Conftest 只是 &lt;em>CLI 跑 once、結束即關&lt;/em>。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &amp;#43; Constraint 兩層、Rego policy &amp;#43; Audit &amp;#43; Mutation">Gatekeeper&lt;/a> 比、Gatekeeper 是 &lt;em>K8s admission controller runtime&lt;/em>、會在 kubectl apply 時攔下違規；Conftest 是在 PR 階段就攔下、deploy 前就 fail CI。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/kyverno/" data-link-title="Kyverno" data-link-desc="K8s-native policy engine、YAML policy（非 Rego）、五類 rule（Validate / Mutate / Generate / Verify Images / Cleanup）、CNCF Incubating">Kyverno&lt;/a> 比、Kyverno 是 K8s-only 的 admission policy（YAML 語法）、Conftest 跨多 config format（不只 K8s）且用 Rego。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &amp;#43; Secret &amp;#43; License &amp;#43; SBOM、Apache 2.0、CI 友善">Trivy&lt;/a> Config 比、Trivy Config 是 &lt;em>built-in misconfig rule&lt;/em>（開箱即用、預定義常見 anti-pattern）、Conftest 是 &lt;em>自己寫 Rego policy&lt;/em>（客製化彈性大但要寫 rule）。&lt;/p></description><content:encoded><![CDATA[<p>Conftest 是 <em>OPA CLI wrapper for static config policy check</em>、Open Policy Agent project 旗下的 CLI 工具、Apache 2.0 OSS、無商業版。它的核心定位是 <em>CI-time policy gate</em>、有別於 admission runtime：在 git commit / PR / merge 階段、用 Rego policy 對 config file（Terraform HCL / K8s YAML / Dockerfile / JSON / TOML / INI / serverless.yml）做 static check、把 misconfiguration 攔在 deploy 之前。跟 <a href="/blog/backend/07-security-data-protection/vendors/opa/" data-link-title="Open Policy Agent (OPA)" data-link-desc="CNCF general-purpose policy engine、Rego Datalog-like 語言、decoupled decision &#43; enforcement、跨 K8s / API / Terraform / SQL 統一 policy">OPA</a> / <a href="/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &#43; Constraint 兩層、Rego policy &#43; Audit &#43; Mutation">Gatekeeper</a> / <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> Config 的差異在 <em>執行時機 + 客製化方式</em>、規則表達力反而相近。</p>
<h2 id="服務定位">服務定位</h2>
<p>Conftest 是 OPA 生態中 <em>最輕量的 CI-time tool</em> — 拿一份 Rego policy + 一份 config file、跑 <code>conftest test</code> 就出 violation report。它不需要 cluster、不需要 daemon、不接 admission webhook、只是個 binary。跟 <a href="/blog/backend/07-security-data-protection/vendors/opa/" data-link-title="Open Policy Agent (OPA)" data-link-desc="CNCF general-purpose policy engine、Rego Datalog-like 語言、decoupled decision &#43; enforcement、跨 K8s / API / Terraform / SQL 統一 policy">OPA</a> 比、OPA 是 <em>runtime decision engine</em>（HTTP server / library / sidecar 提供 policy decision）、Conftest 只是 <em>CLI 跑 once、結束即關</em>。跟 <a href="/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &#43; Constraint 兩層、Rego policy &#43; Audit &#43; Mutation">Gatekeeper</a> 比、Gatekeeper 是 <em>K8s admission controller runtime</em>、會在 kubectl apply 時攔下違規；Conftest 是在 PR 階段就攔下、deploy 前就 fail CI。跟 <a href="/blog/backend/07-security-data-protection/vendors/kyverno/" data-link-title="Kyverno" data-link-desc="K8s-native policy engine、YAML policy（非 Rego）、五類 rule（Validate / Mutate / Generate / Verify Images / Cleanup）、CNCF Incubating">Kyverno</a> 比、Kyverno 是 K8s-only 的 admission policy（YAML 語法）、Conftest 跨多 config format（不只 K8s）且用 Rego。跟 <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> Config 比、Trivy Config 是 <em>built-in misconfig rule</em>（開箱即用、預定義常見 anti-pattern）、Conftest 是 <em>自己寫 Rego policy</em>（客製化彈性大但要寫 rule）。</p>
<p>關鍵張力：<em>CI-time static check</em> ↔ <em>runtime admission enforcement</em> 是兩種互補機制、不是替代。CI 抓在 deploy 之前、但 manifest 不一定都走 PR（kubectl apply 直接打 cluster 就漏接）；admission 抓 runtime 寫入、但 deploy 後才 fail 已經慢。production 通常 CI（Conftest / Trivy Config）+ admission（Gatekeeper / Kyverno）雙層覆蓋。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>Conftest 在 policy-as-code stack 中承擔哪一段（CI gate）、跟 admission runtime 怎麼分工</li>
<li>Rego policy directory / <code>conftest test</code> / <code>conftest verify</code> / Bundle / Combine flag 的 ownership 跟工程化做法</li>
<li>Conftest vs Trivy Config vs Checkov vs OPA + custom CI wrapper 的取捨</li>
<li>何時用 Conftest、何時走 Trivy Config（不想學 Rego）或 Gatekeeper（runtime enforcement）</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Conftest 導入是否健康、最少看四件事：</p>
<ul>
<li><strong>Policy directory 走版控</strong>：Rego files（<code>policy/*.rego</code>）跟 application code 同 repo、或抽到中央 policy repo + Bundle 拉取、PR review 才能改 policy</li>
<li><strong><code>conftest verify</code> 是否跑</strong>：Rego policy 本身有單元測試（<code>*_test.rego</code>）、policy 改動有 test coverage、不是寫完就上 production CI</li>
<li><strong>CI integration 點</strong>：跑在 PR check / merge gate、fail 阻斷 merge、不是只跑 warning 沒人看</li>
<li><strong>跟 admission 是否雙層</strong>：CI fail 之外、cluster 也裝 <a href="/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &#43; Constraint 兩層、Rego policy &#43; Audit &#43; Mutation">Gatekeeper</a> / <a href="/blog/backend/07-security-data-protection/vendors/kyverno/" data-link-title="Kyverno" data-link-desc="K8s-native policy engine、YAML policy（非 Rego）、五類 rule（Validate / Mutate / Generate / Verify Images / Cleanup）、CNCF Incubating">Kyverno</a> 接 runtime；否則 kubectl apply 繞過 CI 就破口</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">Supply Chain Integrity</a> 邊界的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>Policy directory（Rego files）</strong>：Conftest 預設讀 <code>./policy/</code> 目錄下所有 <code>*.rego</code> 檔。Policy 用 <code>deny[msg]</code> / <code>warn[msg]</code> / <code>violation[msg]</code> rule 表達 — <code>deny</code> 失敗整個 test、<code>warn</code> 只 print 不 fail、<code>violation</code> 給結構化輸出（含 metadata 給後續 SOAR 處理）。慣例是一個 policy 檔對一個 anti-pattern（<code>policy/k8s_privileged.rego</code> / <code>policy/terraform_public_s3.rego</code>）、不混寫。</p>
<p><strong><code>conftest test</code> command</strong>：<code>conftest test deployment.yaml</code> / <code>conftest test --policy ./custom-policy terraform.plan.json</code> 是日常入口。支援 <code>--all-namespaces</code>（K8s 多 manifest）、<code>--input</code>（強制 parser 類型）、<code>--combine</code>（跨檔 check）、<code>--output json|tap|table</code>（CI 報表格式）。CI integration 通常 <code>conftest test infra/**/*.yaml --output github</code> 直接 emit GitHub Actions annotation。</p>
<p><strong>Parser（多 format 支援）</strong>：Conftest 原生支援 HCL（Terraform）/ YAML / JSON / TOML / INI / Dockerfile / CUE / Jsonnet / EDN / XML / VCL（Fastly）/ Cyclonedx SBOM 等。同一份 Rego 可跑多 format — parser 把不同 format normalize 成 Rego input JSON、policy 寫 <code>input.spec.containers[_].securityContext.privileged == true</code> 不管原本是 YAML 還是 JSON。這是 Conftest 比 Checkov / Trivy Config 客製化彈性更大的關鍵：同一個 policy 引擎處理跨 format misconfig。</p>
<p><strong>Combine flag（跨檔 check）</strong>：<code>conftest test --combine *.yaml</code> 把多檔合併成單一 input array、policy 可跨檔 reference。實務場景：K8s deployment 必須有對應 service + configmap + networkpolicy、缺一就 fail；Terraform module 跨檔 reference（VPC + subnet + security group）必須一致。沒有 Combine 就只能單檔檢查、跨檔 invariant 抓不到。</p>
<p><strong><code>conftest verify</code>（policy unit test）</strong>：Policy 本身要有測試 — <code>policy/k8s_privileged_test.rego</code> 寫 <code>test_privileged_denied</code> / <code>test_non_privileged_allowed</code>、<code>conftest verify</code> 跑這些測試。Policy 改動先跑 verify、再 merge policy 到 production CI。沒做 verify 的 policy 是「policy 自己 broken 沒人發現」的常見破口。</p>
<p><strong>Bundle（OPA bundle 拉 policy）</strong>：<code>conftest pull</code> 從 OCI registry / HTTP / git / S3 拉 policy bundle、policy 集中在 central repo、各 service repo 不重複維護。Bundle 包含 Rego files + data files + manifest、可簽章驗證（配 <a href="https://docs.sigstore.dev/">Sigstore cosign</a>）。大組織通常 platform team 維護 policy bundle、application team 在 CI 拉最新版本跑。</p>
<p><strong>CI integration</strong>：GitHub Actions（<code>open-policy-agent/conftest-action</code>）/ GitLab CI / Jenkins / CircleCI 都有現成 step。跑點通常在 PR check 階段（review 前 fail fast）+ merge gate（防止繞過）。失敗訊息含 file / line / policy name、SOC / SRE 看 annotation 就知道哪行違規。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Conftest</th>
          <th>Trivy Config</th>
          <th>Checkov</th>
          <th>OPA + custom CI wrapper</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>規則來源</td>
          <td>自己寫 Rego（彈性大、要學 Rego）</td>
          <td>內建 misconfig rule（開箱即用）</td>
          <td>內建 + 自訂 Python rule</td>
          <td>自己寫 Rego + 自己包 CI</td>
      </tr>
      <tr>
          <td>學習曲線</td>
          <td>中 — Rego 語法 + Conftest CLI</td>
          <td>緩 — <code>trivy config</code> 一個指令</td>
          <td>緩 — 內建 rule、自訂 Python 稍重</td>
          <td>陡 — Rego + 自己組 CI 跑點</td>
      </tr>
      <tr>
          <td>Format 支援</td>
          <td>廣 — Terraform / K8s / Dockerfile 等</td>
          <td>中 — Terraform / K8s / CloudFormation</td>
          <td>中 — Terraform / K8s / Serverless</td>
          <td>看自己包</td>
      </tr>
      <tr>
          <td>客製彈性</td>
          <td>高 — 任意 Rego policy</td>
          <td>低 — 內建 rule、客製要寫 plugin</td>
          <td>中 — Python custom rule</td>
          <td>高</td>
      </tr>
      <tr>
          <td>跨檔 check</td>
          <td>強 — <code>--combine</code> flag</td>
          <td>弱 — 主要單檔</td>
          <td>中</td>
          <td>看自己寫</td>
      </tr>
      <tr>
          <td>Policy 共享</td>
          <td>OPA Bundle（OCI / git / HTTP）</td>
          <td>Trivy DB（中央更新）</td>
          <td>Checkov rule pack</td>
          <td>自己管</td>
      </tr>
      <tr>
          <td>計費</td>
          <td>OSS Apache 2.0</td>
          <td>OSS（Aqua 商業版有加值）</td>
          <td>OSS（Bridgecrew 商業版）</td>
          <td>OSS（OPA）</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>客製化 policy、Rego 已用、跨 format</td>
          <td>開箱即用、團隊不想學 Rego</td>
          <td>Terraform-heavy、Python team 熟</td>
          <td>OPA 已是 runtime、CI 想複用 policy</td>
      </tr>
  </tbody>
</table>
<p>選 Conftest 的核心訴求：<em>組織有 custom policy 需求</em> + <em>已用 OPA / Rego（admission 走 Gatekeeper、CI 走 Conftest 統一語言）</em> + <em>跨多 config format 需要同一個 policy 引擎</em>。如果只是要 K8s privileged container / Terraform public S3 這類常見 anti-pattern 攔截、直接 Trivy Config 開箱即用更划算。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong><code>conftest verify</code>（policy unit test lifecycle）</strong>：Policy 是 code、code 要有測試。<code>policy/k8s_privileged_test.rego</code> 寫 <code>test_privileged_denied { count(deny) &gt; 0 with input as {...} }</code>、CI 跑 <code>conftest verify ./policy</code> 把 policy test 當 unit test。Policy change 走 PR → verify pass → 部署到 central bundle → application CI 拉新版本。沒 verify 的 policy 是「沒人知道 policy 自己壞掉、所有 application CI 都 silently pass」的 systemic 風險。</p>
<p><strong>Bundle 從 OCI registry pull + 簽章驗證</strong>：<code>conftest pull oci://registry.example.com/policy-bundle:v1.2.3</code> 從 OCI registry 拉 policy bundle、policy distribution 走 container image 同一套 supply chain。配 <a href="https://docs.sigstore.dev/">Sigstore cosign</a> 簽章驗證、policy bundle 也走 <a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">7.12 供應鏈完整性</a> 的 release gate 邏輯 — policy 本身就是 artifact、需要 signing + verification。</p>
<p><strong>跟 <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> Config 混用</strong>：實務上 <em>Trivy Config 跑預設 rule</em>（CIS / NSA / OWASP baseline、開箱即用）+ <em>Conftest 跑客製 rule</em>（organization-specific：必須有特定 label、必須走特定 namespace、必須引用特定 ConfigMap）。兩者 CI 階段都跑、報表合併。不是二選一、是 baseline + custom 的分工。</p>
<p><strong>跟 admission 雙層</strong>：CI 階段 Conftest fail 之外、cluster 也裝 <a href="/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &#43; Constraint 兩層、Rego policy &#43; Audit &#43; Mutation">Gatekeeper</a> 接 admission。Gatekeeper 用 ConstraintTemplate（也是 Rego）、同一份 Rego policy 理論上 CI / runtime 共用 — 但實務上 admission 場景跟 static check 場景的 input shape 不同（admission 拿 AdmissionReview object、static 拿 raw manifest）、policy 通常分兩份維護或寫 abstraction layer 共用。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Policy pass 但 production 還是 misconfig</strong>：CI 沒卡在 merge gate、或有 <code>kubectl apply</code> 繞過 PR — 加 admission controller（<a href="/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &#43; Constraint 兩層、Rego policy &#43; Audit &#43; Mutation">Gatekeeper</a> / <a href="/blog/backend/07-security-data-protection/vendors/kyverno/" data-link-title="Kyverno" data-link-desc="K8s-native policy engine、YAML policy（非 Rego）、五類 rule（Validate / Mutate / Generate / Verify Images / Cleanup）、CNCF Incubating">Kyverno</a>）做 runtime 雙層</li>
<li><strong>Rego policy 自己 broken / silently pass</strong>：沒寫 <code>*_test.rego</code> + <code>conftest verify</code> — 補 policy unit test、CI 跑 verify 才 promote</li>
<li><strong><code>conftest test</code> 跑出 0 violations 但 manifest 有問題</strong>：policy directory 沒讀對、或 parser 自動偵測選錯 — 顯式 <code>--policy ./policy --input yaml</code></li>
<li><strong>跨檔 invariant 抓不到</strong>（deployment 沒對應 service）：忘記用 <code>--combine</code> flag — 改 <code>conftest test --combine *.yaml</code></li>
<li><strong>Bundle 拉到舊版本 / policy drift</strong>：沒固定 bundle tag、用 <code>latest</code> 漂移 — bundle reference 用 digest（<code>sha256:...</code>）或 immutable tag</li>
<li><strong>False positive 多 / team 開始 ignore CI</strong>：policy 寫得太寬、沒考慮合理例外 — Rego 加 exception list（<code>data.exceptions</code>）、走 <a href="/blog/backend/07-security-data-protection/blue-team/" data-link-title="7.B 防守者視角（藍隊）與控制面驗證" data-link-desc="從防守者角度整理控制面、偵測路由、驗證策略與演練回寫">Exception Workflow</a> lifecycle</li>
<li><strong>Policy 散落各 application repo / 維護不一致</strong>：沒走 central bundle — 抽 policy 到中央 repo、各 application 拉 bundle</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>開箱即用、不想學 Rego</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy Config</a></td>
      </tr>
      <tr>
          <td>K8s admission runtime</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &#43; Constraint 兩層、Rego policy &#43; Audit &#43; Mutation">Gatekeeper</a> / <a href="/blog/backend/07-security-data-protection/vendors/kyverno/" data-link-title="Kyverno" data-link-desc="K8s-native policy engine、YAML policy（非 Rego）、五類 rule（Validate / Mutate / Generate / Verify Images / Cleanup）、CNCF Incubating">Kyverno</a></td>
      </tr>
      <tr>
          <td>Runtime application policy</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/opa/" data-link-title="Open Policy Agent (OPA)" data-link-desc="CNCF general-purpose policy engine、Rego Datalog-like 語言、decoupled decision &#43; enforcement、跨 K8s / API / Terraform / SQL 統一 policy">OPA</a></td>
      </tr>
      <tr>
          <td>Terraform-heavy + Python team</td>
          <td>Checkov / tfsec</td>
      </tr>
      <tr>
          <td>Cloud-native CNAPP</td>
          <td>Wiz / Prisma Cloud</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Rego 完整語法 reference、<code>every</code> / <code>walk</code> / built-in function 進階用法</li>
<li>OPA Bundle 的 server-side 實作（policy publish pipeline）</li>
<li>Conftest 跟 Open Policy Agent runtime 的內部架構差異</li>
<li>Sigstore cosign 的 keyless signing flow 細節</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>Conftest 在 07 案例庫沒有直接 vendor-level 事件、但所有 supply chain case 都是 CI-time policy gate 的對照：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 Conftest 的關係（對照啟示）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/solarwinds-2020-sunburst/" data-link-title="7.R7.2.1 SolarWinds 2020：更新鏈被濫用" data-link-desc="合法更新流程遭植入後，攻擊者如何長期潛伏與橫向擴散">SolarWinds 2020 Sunburst</a></td>
          <td>Conftest 在 CI 階段檢查 Terraform / K8s manifest 是否符合 image signing policy（image 必須來自 signed registry、必須有 cosign attestation）</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/log4shell-cve-2021-44228-component-chain/" data-link-title="7.R7.2.7 Log4Shell 2021：共用元件風險與修補鏈" data-link-desc="共用元件漏洞如何同步影響多服務，並迫使團隊建立依賴治理 workflow">Log4Shell CVE-2021-44228</a></td>
          <td>Conftest 配 SBOM 檔案做 CI-time vulnerable component check、補 admission 之前的 gate（image 含 log4j-core &lt;2.17 直接 PR fail）</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">7.12 供應鏈完整性 (section)</a></td>
          <td>Conftest 是 release gate 在 CI 階段的 policy enforcement 工具、跟 admission 雙層覆蓋、policy bundle 本身也走 cosign 簽章 supply chain</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">7.12 供應鏈完整性與 artifact 信任</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/opa/" data-link-title="Open Policy Agent (OPA)" data-link-desc="CNCF general-purpose policy engine、Rego Datalog-like 語言、decoupled decision &#43; enforcement、跨 K8s / API / Terraform / SQL 統一 policy">OPA</a>、<a href="/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &#43; Constraint 兩層、Rego policy &#43; Audit &#43; Mutation">Gatekeeper</a>、<a href="/blog/backend/07-security-data-protection/vendors/kyverno/" data-link-title="Kyverno" data-link-desc="K8s-native policy engine、YAML policy（非 Rego）、五類 rule（Validate / Mutate / Generate / Verify Images / Cleanup）、CNCF Incubating">Kyverno</a>、<a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a></li>
<li>跨類：<a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GitHub Advanced Security</a>（CI security check pipeline 共用）</li>
<li>官方：<a href="https://www.conftest.dev/">Conftest Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>AWS Cost Explorer</title><link>https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/aws-cost-explorer/</link><pubDate>Fri, 15 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/aws-cost-explorer/</guid><description>&lt;p>AWS Cost Explorer 的核心責任是提供 AWS-native 的成本、用量、forecast、reservation 與 rightsizing 分析入口。它適合 AWS-first 團隊把帳單變化拆到 account、service、region、tag、usage type 與 time range，並把成本訊號接回容量規劃與服務 owner review。&lt;/p>
&lt;h2 id="定位">定位&lt;/h2>
&lt;p>AWS Cost Explorer 適合做 AWS 成本分析的 baseline。當團隊需要回答「哪個服務、帳號、tag 或 usage type 造成成本變化」，Cost Explorer 可以直接使用 AWS billing data 產生圖表、report、forecast 與 API 查詢。&lt;/p>
&lt;p>這個定位讓 AWS Cost Explorer 接到三個主章。它從 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cost-engineering/" data-link-title="9.7 成本邊界與 efficiency" data-link-desc="cost per request、cost curve、降級成本、over-provisioning trade-off">9.7 成本邊界與 efficiency&lt;/a> 接收 cost per request 與 cost curve，從 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/performance-observability/" data-link-title="9.8 效能可觀測性" data-link-desc="saturation metric、USE / RED method、cost dashboard">9.8 效能可觀測性&lt;/a> 接收成本 dashboard 需求，從 &lt;a href="https://tarrragon.github.io/blog/backend/04-observability/cost-attribution/" data-link-title="4.15 Cost Attribution / Chargeback" data-link-desc="把 observability 成本拆到團隊、產品、環境維度">04 可觀測性成本歸因&lt;/a> 接收 tag 與 ownership 規則。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/cloudhealth/" data-link-title="CloudHealth" data-link-desc="用 enterprise FinOps governance、policy 與多雲成本管理支援大型組織的容量成本治理">CloudHealth&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/vantage/" data-link-title="Vantage" data-link-desc="用 cloud cost reports、Kubernetes cost allocation 與 forecast 建立工程可用的成本可見性">Vantage&lt;/a> 等 multi-cloud FinOps 平台比、Cost Explorer 走 &lt;em>AWS-native + free&lt;/em>：不另收費（API 查詢按 request 收 USD 0.01）、跟 Billing Console + CUR + Budgets + Anomaly Detection 同一 IAM 邊界、tag 與 Cost Category 設定直接從 billing data 拉。換來的限制是 &lt;em>只看 AWS&lt;/em>、跨雲 / Kubernetes pod-level / SaaS license 都要外接。&lt;/p>
&lt;h2 id="最短判讀路徑">最短判讀路徑&lt;/h2>
&lt;p>判斷 Cost Explorer 是否健康發揮、最少看四件事：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Cost Explorer view 是否有 saved report&lt;/strong>：team-level saved report（依 service / linked account / tag 拆）、月度 review checklist、有沒有人定期看 trend、view 是否進 dashboard share&lt;/li>
&lt;li>&lt;strong>CUR（Cost &amp;amp; Usage Report）設定&lt;/strong>：是否啟用 CUR 2.0 / Data Exports、S3 bucket 是否打開 Athena / QuickSight 查詢、hourly granularity 是否開、resource ID 是否開（沒開的話 tag-based allocation 拆不到 instance level）&lt;/li>
&lt;li>&lt;strong>Budgets + Anomaly Detection alert routing&lt;/strong>：service-level / account-level budget threshold、Cost Anomaly Detection monitor 是否分 service / linked account 設定、alert 接到 Slack / PagerDuty / email、誰負責 triage&lt;/li>
&lt;li>&lt;strong>Tag policy + Cost Category 治理&lt;/strong>：哪些 cost allocation tag 已啟用（在 Billing Console activate 才會進 CUR）、untagged resource 比例、Cost Category rule 是否覆蓋多帳號合併、誰維護 rule lifecycle&lt;/li>
&lt;/ul>
&lt;p>四件事任一缺失就是 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cost-engineering/" data-link-title="9.7 成本邊界與 efficiency" data-link-desc="cost per request、cost curve、降級成本、over-provisioning trade-off">9.7 成本邊界與 efficiency&lt;/a> 邊界的待補項目 — CUR 沒開就只能看 console aggregated view、CUR 開了沒接 Athena / QuickSight 就只能看 Console 介面、不能跟 release / capacity 資料 join。&lt;/p></description><content:encoded><![CDATA[<p>AWS Cost Explorer 的核心責任是提供 AWS-native 的成本、用量、forecast、reservation 與 rightsizing 分析入口。它適合 AWS-first 團隊把帳單變化拆到 account、service、region、tag、usage type 與 time range，並把成本訊號接回容量規劃與服務 owner review。</p>
<h2 id="定位">定位</h2>
<p>AWS Cost Explorer 適合做 AWS 成本分析的 baseline。當團隊需要回答「哪個服務、帳號、tag 或 usage type 造成成本變化」，Cost Explorer 可以直接使用 AWS billing data 產生圖表、report、forecast 與 API 查詢。</p>
<p>這個定位讓 AWS Cost Explorer 接到三個主章。它從 <a href="/blog/backend/09-performance-capacity/cost-engineering/" data-link-title="9.7 成本邊界與 efficiency" data-link-desc="cost per request、cost curve、降級成本、over-provisioning trade-off">9.7 成本邊界與 efficiency</a> 接收 cost per request 與 cost curve，從 <a href="/blog/backend/09-performance-capacity/performance-observability/" data-link-title="9.8 效能可觀測性" data-link-desc="saturation metric、USE / RED method、cost dashboard">9.8 效能可觀測性</a> 接收成本 dashboard 需求，從 <a href="/blog/backend/04-observability/cost-attribution/" data-link-title="4.15 Cost Attribution / Chargeback" data-link-desc="把 observability 成本拆到團隊、產品、環境維度">04 可觀測性成本歸因</a> 接收 tag 與 ownership 規則。</p>
<p>跟 <a href="/blog/backend/09-performance-capacity/vendors/cloudhealth/" data-link-title="CloudHealth" data-link-desc="用 enterprise FinOps governance、policy 與多雲成本管理支援大型組織的容量成本治理">CloudHealth</a> / <a href="/blog/backend/09-performance-capacity/vendors/vantage/" data-link-title="Vantage" data-link-desc="用 cloud cost reports、Kubernetes cost allocation 與 forecast 建立工程可用的成本可見性">Vantage</a> 等 multi-cloud FinOps 平台比、Cost Explorer 走 <em>AWS-native + free</em>：不另收費（API 查詢按 request 收 USD 0.01）、跟 Billing Console + CUR + Budgets + Anomaly Detection 同一 IAM 邊界、tag 與 Cost Category 設定直接從 billing data 拉。換來的限制是 <em>只看 AWS</em>、跨雲 / Kubernetes pod-level / SaaS license 都要外接。</p>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Cost Explorer 是否健康發揮、最少看四件事：</p>
<ul>
<li><strong>Cost Explorer view 是否有 saved report</strong>：team-level saved report（依 service / linked account / tag 拆）、月度 review checklist、有沒有人定期看 trend、view 是否進 dashboard share</li>
<li><strong>CUR（Cost &amp; Usage Report）設定</strong>：是否啟用 CUR 2.0 / Data Exports、S3 bucket 是否打開 Athena / QuickSight 查詢、hourly granularity 是否開、resource ID 是否開（沒開的話 tag-based allocation 拆不到 instance level）</li>
<li><strong>Budgets + Anomaly Detection alert routing</strong>：service-level / account-level budget threshold、Cost Anomaly Detection monitor 是否分 service / linked account 設定、alert 接到 Slack / PagerDuty / email、誰負責 triage</li>
<li><strong>Tag policy + Cost Category 治理</strong>：哪些 cost allocation tag 已啟用（在 Billing Console activate 才會進 CUR）、untagged resource 比例、Cost Category rule 是否覆蓋多帳號合併、誰維護 rule lifecycle</li>
</ul>
<p>四件事任一缺失就是 <a href="/blog/backend/09-performance-capacity/cost-engineering/" data-link-title="9.7 成本邊界與 efficiency" data-link-desc="cost per request、cost curve、降級成本、over-provisioning trade-off">9.7 成本邊界與 efficiency</a> 邊界的待補項目 — CUR 沒開就只能看 console aggregated view、CUR 開了沒接 Athena / QuickSight 就只能看 Console 介面、不能跟 release / capacity 資料 join。</p>
<h2 id="適用場景">適用場景</h2>
<p>AWS 月度成本 review 是 Cost Explorer 的主要入口。團隊可以依 service、linked account、region、tag、cost category、purchase option 或 usage type 檢視趨勢，找出 EC2、RDS、S3、NAT Gateway、Data Transfer 或 managed service 的成本變化。</p>
<p>Forecast 與 trend review 適合用 Cost Explorer 連到容量規劃。月中 forecast、daily cost trend、commitment utilization 與 reservation recommendation 可以讓平台團隊提前調整 autoscaling、instance family、reserved capacity 或 service 配置。</p>
<p>Programmatic cost query 適合接內部 dashboard。Cost Explorer API 可以把成本與用量資料拉到 release dashboard、capacity review、service scorecard 或 FinOps workflow，讓工程團隊在自己熟悉的介面看成本訊號。</p>
<h2 id="選型判準">選型判準</h2>
<table>
  <thead>
      <tr>
          <th>判準</th>
          <th>AWS Cost Explorer 的價值</th>
          <th>需要補的能力</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>AWS baseline</td>
          <td>直接使用 AWS billing data 與 Cost Management 入口</td>
          <td>Tag policy、Cost Category 設計</td>
      </tr>
      <tr>
          <td>Report</td>
          <td>支援 service、account、region、tag、usage type 分析</td>
          <td>owner mapping、business context</td>
      </tr>
      <tr>
          <td>Forecast</td>
          <td>支援成本預測與趨勢判讀</td>
          <td>release marker、event calendar</td>
      </tr>
      <tr>
          <td>API</td>
          <td>支援把 cost query 接到內部工具</td>
          <td>cache、權限控管、查詢成本治理</td>
      </tr>
  </tbody>
</table>
<p>AWS baseline 價值來自資料來源直接。Cost Explorer 使用 AWS 成本與用量資料，適合作為其他 FinOps 工具導入前的共同對帳入口。</p>
<p>Report 價值來自快速拆解。當某月成本上升，工程團隊可以先用 service、usage type、region 與 tag 找出最大變動，再決定是否需要更細的 workload-level 或 Kubernetes-level 工具。</p>
<p>API 價值來自流程整合。把 cost query 接到 release note、incident review 或 capacity planning dashboard，能讓成本變化跟部署、流量與容量決策同時被檢視。</p>
<h2 id="跟其他工具的取捨">跟其他工具的取捨</h2>
<p>AWS Cost Explorer 和 Vantage 的主要差異是範圍。Cost Explorer 是 AWS-native 成本入口；Vantage 適合跨 provider、Kubernetes 成本與工程團隊自助報表。</p>
<p>AWS Cost Explorer 和 CloudHealth 的主要差異是治理層級。Cost Explorer 適合 AWS account 與 service-level 分析；CloudHealth 適合 enterprise FinOps policy、showback / chargeback 與多雲治理。</p>
<p>AWS Cost Explorer 和 Akamas 的主要差異是行動模型。Cost Explorer 提供成本與用量事實；Akamas 把成本、SLO 與配置調校接成 optimization loop。</p>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>AWS Cost Explorer</th>
          <th>CloudHealth</th>
          <th>Vantage</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>範圍</td>
          <td>AWS-only</td>
          <td>Multi-cloud（AWS / Azure / GCP / SaaS）</td>
          <td>Multi-cloud + Kubernetes pod-level + SaaS</td>
      </tr>
      <tr>
          <td>計費</td>
          <td>Free（API 按 request 微收）</td>
          <td>Per-cloud-spend % 或 fixed tier</td>
          <td>Per-cloud-spend % 或 fixed tier</td>
      </tr>
      <tr>
          <td>治理層級</td>
          <td>Account / service / tag / usage type</td>
          <td>Enterprise FinOps policy、showback chargeback</td>
          <td>Engineering self-serve、業務團隊自助查詢</td>
      </tr>
      <tr>
          <td>Kubernetes</td>
          <td>EKS service-level、不到 pod / namespace</td>
          <td>Container module 補位</td>
          <td>內建 Kubernetes cost allocation</td>
      </tr>
      <tr>
          <td>退場成本</td>
          <td>低 — 跟 AWS billing 同源、隨時可切</td>
          <td>中 — policy / showback rule 量多</td>
          <td>中 — query 跟 dashboard 量多</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>AWS-first、預算敏感、團隊小</td>
          <td>Enterprise、多雲、需要 chargeback</td>
          <td>Cloud-native、跨雲、engineering 自助 FinOps</td>
      </tr>
  </tbody>
</table>
<p>選 Cost Explorer 的核心訴求：<em>AWS-only + free + 跟 Billing / Budgets / Anomaly Detection 同 IAM 邊界</em>。當需求出現 <em>跨雲對帳</em> / <em>Kubernetes pod-level chargeback</em> / <em>SaaS license 整合</em>、就改走 CloudHealth / Vantage。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Cost Anomaly Detection</strong>：基於 ML 的 cost spike 偵測、按 service / linked account / cost category / tag 建 monitor、anomaly score 超 threshold 就 alert。實務治理：先用 <em>AWS services</em> monitor 全 service 跑 2-4 週看 baseline、再針對高變動 service（EC2 / Data Transfer / S3）建 dedicated monitor 拉緊 threshold、alert 接 SNS → Slack / PagerDuty。false positive 主要來自 release event 或 batch job、用 dimensional filter（exclude 特定 usage type / region）+ subscribe threshold 調 absolute USD + percentage 雙條件。</p>
<p><strong>Budgets + Forecast</strong>：Budget 可設 monthly / quarterly / annual、threshold 走 actual 跟 forecast 兩條 — forecast 達 80% 先 warn、actual 達 100% 才 page。Forecast 基於過去 historical pattern + linear extrapolation、新 workload / peak event 前要手動調整或關 forecast alert 避免噪音。Budget action 可以自動執行 IAM policy / SCP（例如 dev account 超預算自動 detach attach role）、但 production 別開、誤殺風險高。</p>
<p><strong>CUR (Cost &amp; Usage Report) + S3 + Athena / QuickSight</strong>：CUR 是 hourly granularity、含 resource ID、reserved instance / savings plan attribution、cost allocation tag 全欄位的 raw billing data、寫到 S3 bucket（Parquet 格式）。標準 pipeline：CUR → S3 → Glue Crawler → Athena → QuickSight dashboard、或直接拉到 BigQuery / Snowflake 跟其他維度 join（release calendar / SLO / traffic）。CUR 2.0 / Data Exports 是新版、欄位 schema 穩定、recommend 新部署直接走 CUR 2.0。</p>
<p><strong>Reserved Instance + Savings Plan recommendation</strong>：Cost Explorer 內建 RI / SP recommendation engine、看 past 7 / 30 / 60 day usage、推薦 commitment term（1yr / 3yr）+ payment option（All Upfront / Partial / No Upfront）+ break-even point。實務做法：先看 <em>Compute Savings Plan</em>（覆蓋 EC2 / Fargate / Lambda）的 baseline、再看 <em>EC2 Instance Savings Plan</em>（鎖 family + region）加深、最後看 RI 鎖 specific instance type — 三層疊加可達 60-70% saving、但 commitment 風險也疊加、要對齊 capacity planning。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Tag-based allocation 拆不到 instance / 比例異常</strong>：cost allocation tag 沒在 Billing Console activate（即使 EC2 tag 有設、billing 沒看到）— 進 Billing Console → Cost Allocation Tags → activate、要等 24hr CUR 才回填。Untagged resource 比例 &gt; 10% 直接代表 tag policy 沒落地、補 AWS Config rule 或 SCP 強制 tag。</li>
<li><strong>CUR delivery lag / 資料對不上 Console</strong>：CUR delivery 是 daily、月底結算後 finalized 還要等 1-3 天、月中看 CUR 跟 Console 有 % 差是正常 — 月中 review 用 Console、月底結算用 CUR finalized。如果 CUR 過了 48hr 還沒 delivery、檢查 S3 bucket policy 跟 CUR report status。</li>
<li><strong>Anomaly Detection false positive 多</strong>：threshold 設太嚴（absolute USD 太低 / percentage 太敏感）、或 monitor scope 太寬（包含 dev / sandbox account）— 拆 monitor 按 environment 分、production 抓 absolute USD + percentage 雙條件、dev 降低敏感度或關。</li>
<li><strong>Forecast 跳水 / 跳漲不合理</strong>：forecast 用 linear extrapolation、月中 spike / drop 會被放大、release 前 / peak event 前 forecast 不準 — 用 actual + Budget threshold 校正、別只看 forecast 決策。</li>
<li><strong>API rate limit / 查詢費用爆增</strong>：內部 dashboard 沒 cache 直接打 Cost Explorer API、每 request USD 0.01 月底結算 USD 數千 — cache 層 1hr TTL、time range 對齊 daily granularity、別 per-minute polling。</li>
<li><strong>Cost Category rule 衝突 / unallocated 過多</strong>：rule 設有 overlap 但 priority 沒設、或 rule 沒覆蓋新 service — Cost Category 走 explicit priority + default rule、新 service launch 進 owner checklist。</li>
</ul>
<h2 id="操作成本">操作成本</h2>
<p>Cost Explorer 的主要成本是資料治理。Tag、Cost Category、account structure、reservation sharing 與 owner mapping 要先整理，報表才會對工程團隊有行動意義。</p>
<p>API 整合需要查詢治理。程式化查詢要控制權限、頻率、cache、time range 與 paginated request 成本，避免內部 dashboard 造成額外查詢浪費。</p>
<p>成本解釋需要補業務 context。Cost Explorer 可以指出哪個 service 或 usage type 變貴；真正的工程判斷還要接 release、traffic、peak event、data retention、capacity policy 與 SLO 變化。</p>
<h2 id="evidence-package">Evidence Package</h2>
<p>AWS Cost Explorer 結果應回寫到 AWS cost evidence package。最小欄位包括 report name、group by、filter、time range、account、service、region、tag、usage type、forecast、recommendation、owner 與 action item。</p>
<table>
  <thead>
      <tr>
          <th>欄位</th>
          <th>AWS Cost Explorer 證據來源</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Source</td>
          <td>Cost Explorer report、Cost Explorer API、RI / rightsizing recommendation</td>
      </tr>
      <tr>
          <td>Time range</td>
          <td>billing period、daily trend、forecast period</td>
      </tr>
      <tr>
          <td>Query link</td>
          <td>AWS Console report、API query、internal dashboard</td>
      </tr>
      <tr>
          <td>Data quality</td>
          <td>tag coverage、Cost Category rule、data freshness</td>
      </tr>
      <tr>
          <td>Confidence</td>
          <td>owner mapping、trend repeatability、billing delay</td>
      </tr>
      <tr>
          <td>Known gap</td>
          <td>shared cost rule、multi-cloud gap、Kubernetes pod-level gap</td>
      </tr>
  </tbody>
</table>
<p>Evidence package 的核心用途是讓 AWS 成本 review 可以重跑。Cost Explorer report 要能回答「查詢條件是什麼、成本變化在哪個維度、誰負責處理、下次如何確認改善」。</p>
<h2 id="案例回寫">案例回寫</h2>
<p>AWS Cost Explorer 目前適合作為 AWS-first 成本案例的 baseline 工具。它可回寫到 <a href="/blog/backend/09-performance-capacity/cases/netflix-aurora-consolidation/" data-link-title="9.C23 Netflix：把關聯式 DB 統一到 Aurora、效能 &#43;75%、成本 -28%" data-link-desc="Netflix 把多套關聯式 DB 統一到 Aurora、效能提升 75%、成本下降 28%、串流數十億小時">9.C23 Netflix Aurora consolidation</a> 的跨 DB 整併與 28% 成本下降驗證、<a href="/blog/backend/09-performance-capacity/cases/bookmyshow-indian-ticketing-platform/" data-link-title="9.C17 BookMyShow：印度年售 2 億張票的資料架構現代化" data-link-desc="BookMyShow 從 15 年自建 analytics 遷移到 AWS modern data architecture、4 個月完成、分析成本下降 80%">9.C17 BookMyShow modern data architecture</a> 的 80 TB 多副本 → 單一 source of truth + 80% 分析成本下降、<a href="/blog/backend/09-performance-capacity/cases/zomato-tidb-to-dynamodb-migration/" data-link-title="9.C20 Zomato：從 TiDB 遷移到 DynamoDB、吞吐 4 倍、延遲降 90%、成本減 50%" data-link-desc="Zomato 帳單系統從 TiDB 遷移到 DynamoDB、吞吐 2K→8K RPM、延遲降 90%、成本減 50%">9.C20 Zomato</a> 的 on-demand vs over-provisioned 對照、以及 <a href="/blog/backend/09-performance-capacity/cases/wayfair-gcp-burst-capacity/" data-link-title="9.C22 Wayfair：用 GCP 提供 Way Day / Black Friday 的 burst capacity" data-link-desc="Wayfair 22M&#43; 商品 &#43; 16,000&#43; 供應商、用 GCP 補充 on-prem data center 在峰值事件的 burst capacity">9.C22 Wayfair GCP burst</a> 的 hybrid 模式 AWS-side baseline 釐清（即使是跨雲案例、AWS 側的 review 仍可用 Cost Explorer 跑）。</p>
<p>這些案例的重點是成本訊號到工程行動的轉換。Cost Explorer 頁引用案例時，要把 report 維度、變化原因、服務 owner、容量調整與驗證方式寫成可重跑流程 — Netflix 28% 下降要對應 Aurora cluster 數、IO-Optimized 切換時機與 reader replica 配比。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/09-performance-capacity/cost-engineering/" data-link-title="9.7 成本邊界與 efficiency" data-link-desc="cost per request、cost curve、降級成本、over-provisioning trade-off">9.7 成本邊界與 efficiency</a></li>
<li>上游：<a href="/blog/backend/09-performance-capacity/performance-observability/" data-link-title="9.8 效能可觀測性" data-link-desc="saturation metric、USE / RED method、cost dashboard">9.8 效能可觀測性</a></li>
<li>跨模組：<a href="/blog/backend/04-observability/cost-attribution/" data-link-title="4.15 Cost Attribution / Chargeback" data-link-desc="把 observability 成本拆到團隊、產品、環境維度">04 可觀測性成本歸因</a></li>
<li>平行：<a href="/blog/backend/09-performance-capacity/vendors/vantage/" data-link-title="Vantage" data-link-desc="用 cloud cost reports、Kubernetes cost allocation 與 forecast 建立工程可用的成本可見性">Vantage</a></li>
<li>官方：<a href="https://docs.aws.amazon.com/cost-management/latest/userguide/ce-what-is.html">AWS Cost Explorer documentation</a></li>
</ul>
]]></content:encoded></item><item><title>Falco</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/falco/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/falco/</guid><description>&lt;p>Falco 是 CNCF Graduated 的 runtime cloud-native threat detection engine、原 Sysdig 開源、Apache 2.0 license。它在 host / container 上用 eBPF（或 kernel module / userspace fallback）攔截 syscall、跟 Plugin 拉到的 audit log 串成同一條 event stream、丟給 Rule engine 比對 YAML rule、命中後 alert 到 stdout / Falcosidekick / SIEM。它跟商業 CNAPP runtime 模組（&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &amp;#43; CSPM &amp;#43; CWS &amp;#43; AAP &amp;#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog CWS&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/lacework/" data-link-title="Lacework" data-link-desc="CNAPP 走 Polygraph ML behavioral baseline 路線、2024 跟 Fortinet 合併成 FortiCNAPP、自動學 normal、anomaly 自動 alert">Lacework Polygraph&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/prisma-cloud/" data-link-title="Prisma Cloud" data-link-desc="Palo Alto CNAPP、agent (Defender) &amp;#43; agentless 雙軌、五模組（Compute / CSPM / Code / Data / CIEM）、Compliance template 強">Prisma Cloud Defender&lt;/a>）的差異在 &lt;em>OSS rule-based vs SaaS ML-based + 平台廣度 + 自動 response 的工程責任歸屬&lt;/em>、偵測技術本身相近。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Falco 的核心定位是 &lt;em>K8s container runtime detection engine 的 OSS 基準&lt;/em>、不是 full CNAPP、也不是 inline enforcement。底層 Driver 分三層：&lt;em>modern eBPF&lt;/em>（Linux 5.8+、預設）、&lt;em>legacy kernel module (kmod)&lt;/em>（舊 kernel fallback）、&lt;em>pdig userspace probe&lt;/em>（沒 root 或非 Linux）；Driver 抓 syscall 跟 K8s audit / cloud audit event、送進 Falco engine；engine 用 Sysdig filter syntax 比對 YAML rule、命中後吐 alert。Plugin 系統讓 Falco 看到非 syscall event（K8s audit log、Okta event、GitHub audit、AWS CloudTrail）— 變成 &lt;em>general detection engine&lt;/em>、不只 host runtime。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/cilium-tetragon/" data-link-title="Cilium Tetragon" data-link-desc="eBPF-based runtime security &amp;#43; inline enforcement、跟 Cilium CNI 同生態、TracingPolicy CRD、process credentials tracking &amp;#43; KillerAction">Cilium Tetragon&lt;/a> 比、Falco 走 &lt;em>rule engine + alert-only&lt;/em>、Tetragon 走 &lt;em>eBPF + 可 enforce kill action&lt;/em>；Falco 偵測為主、Tetragon 偵測 + 防護。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &amp;#43; CSPM &amp;#43; CWS &amp;#43; AAP &amp;#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Security&lt;/a>（CWS）比、Datadog 是 SaaS observability 上加 runtime security view、ML-based behavioral baseline 內建、但 vendor lock + per-host 計費；Falco 是 OSS 自管、rule 完全可寫、但 ML baseline / threat intel / cross-source correlation 要自己接 SIEM。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/lacework/" data-link-title="Lacework" data-link-desc="CNAPP 走 Polygraph ML behavioral baseline 路線、2024 跟 Fortinet 合併成 FortiCNAPP、自動學 normal、anomaly 自動 alert">Lacework&lt;/a> Polygraph 比、Lacework 走 behavior graph 自動建 baseline、Falco 走 rule-explicit、邊界看得到也好 audit。&lt;/p></description><content:encoded><![CDATA[<p>Falco 是 CNCF Graduated 的 runtime cloud-native threat detection engine、原 Sysdig 開源、Apache 2.0 license。它在 host / container 上用 eBPF（或 kernel module / userspace fallback）攔截 syscall、跟 Plugin 拉到的 audit log 串成同一條 event stream、丟給 Rule engine 比對 YAML rule、命中後 alert 到 stdout / Falcosidekick / SIEM。它跟商業 CNAPP runtime 模組（<a href="/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &#43; CSPM &#43; CWS &#43; AAP &#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog CWS</a> / <a href="/blog/backend/07-security-data-protection/vendors/lacework/" data-link-title="Lacework" data-link-desc="CNAPP 走 Polygraph ML behavioral baseline 路線、2024 跟 Fortinet 合併成 FortiCNAPP、自動學 normal、anomaly 自動 alert">Lacework Polygraph</a> / <a href="/blog/backend/07-security-data-protection/vendors/prisma-cloud/" data-link-title="Prisma Cloud" data-link-desc="Palo Alto CNAPP、agent (Defender) &#43; agentless 雙軌、五模組（Compute / CSPM / Code / Data / CIEM）、Compliance template 強">Prisma Cloud Defender</a>）的差異在 <em>OSS rule-based vs SaaS ML-based + 平台廣度 + 自動 response 的工程責任歸屬</em>、偵測技術本身相近。</p>
<h2 id="服務定位">服務定位</h2>
<p>Falco 的核心定位是 <em>K8s container runtime detection engine 的 OSS 基準</em>、不是 full CNAPP、也不是 inline enforcement。底層 Driver 分三層：<em>modern eBPF</em>（Linux 5.8+、預設）、<em>legacy kernel module (kmod)</em>（舊 kernel fallback）、<em>pdig userspace probe</em>（沒 root 或非 Linux）；Driver 抓 syscall 跟 K8s audit / cloud audit event、送進 Falco engine；engine 用 Sysdig filter syntax 比對 YAML rule、命中後吐 alert。Plugin 系統讓 Falco 看到非 syscall event（K8s audit log、Okta event、GitHub audit、AWS CloudTrail）— 變成 <em>general detection engine</em>、不只 host runtime。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/cilium-tetragon/" data-link-title="Cilium Tetragon" data-link-desc="eBPF-based runtime security &#43; inline enforcement、跟 Cilium CNI 同生態、TracingPolicy CRD、process credentials tracking &#43; KillerAction">Cilium Tetragon</a> 比、Falco 走 <em>rule engine + alert-only</em>、Tetragon 走 <em>eBPF + 可 enforce kill action</em>；Falco 偵測為主、Tetragon 偵測 + 防護。跟 <a href="/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &#43; CSPM &#43; CWS &#43; AAP &#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Security</a>（CWS）比、Datadog 是 SaaS observability 上加 runtime security view、ML-based behavioral baseline 內建、但 vendor lock + per-host 計費；Falco 是 OSS 自管、rule 完全可寫、但 ML baseline / threat intel / cross-source correlation 要自己接 SIEM。跟 <a href="/blog/backend/07-security-data-protection/vendors/lacework/" data-link-title="Lacework" data-link-desc="CNAPP 走 Polygraph ML behavioral baseline 路線、2024 跟 Fortinet 合併成 FortiCNAPP、自動學 normal、anomaly 自動 alert">Lacework</a> Polygraph 比、Lacework 走 behavior graph 自動建 baseline、Falco 走 rule-explicit、邊界看得到也好 audit。</p>
<p>關鍵張力：<em>偵測 vs 防護</em> 跟 <em>rule-explicit vs ML-baseline</em> 是兩條取捨軸。Falco 預設只發 alert、要 inline kill / cordon 要靠 Falco Talon 或外接 SOAR；rule 完全可寫是優點也是負擔 — 自家 anti-pattern 要自己寫成 condition、不像 SaaS CNAPP 預設有 ML baseline。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>Falco 在 K8s runtime security stack 中承擔哪一段（syscall detection / audit log detection / alert forwarding）、哪些要外接（Talon / SIEM / SOAR）</li>
<li>Driver 選擇（modern eBPF / kmod / pdig）跟 kernel 環境 / 部署模型 的對應、選錯會 silent miss event</li>
<li>Rule 寫作的 ownership 設計（誰寫、誰 review、staging 怎麼觀察 false positive）</li>
<li>何時用 Falco、何時改走 Tetragon（要 enforcement）或商業 CNAPP（要 ML baseline + 跨雲 posture）</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Falco deployment 是否健康、最少看四件事：</p>
<ul>
<li><strong>Driver 是否符合 kernel 環境</strong>：modern eBPF on 5.8+ / kmod on legacy / pdig on serverless 或 non-root container；driver 跟 kernel 不對等於 silent miss，要看 <code>falco --version</code> 跟啟動 log 確認 driver 載入成功</li>
<li><strong>Rule ownership 跟 lifecycle</strong>：Falco 內建 rule（<code>falco_rules.yaml</code> / <code>k8s_audit_rules.yaml</code>）+ 自家 custom rule 是否走 Git PR review、staging tenant 跑幾小時觀察 false positive、再 promote production</li>
<li><strong>Alert sink + downstream routing</strong>：Falco 預設輸出 stdout / file / syslog、production 幾乎都接 Falcosidekick 做 fan-out（Slack / SIEM / S3 / Webhook），跟 <a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / <a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a> / <a href="/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &#43; CSPM &#43; CWS &#43; AAP &#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Security</a> 的接點明確</li>
<li><strong>Response 是 alert-only 還是有 enforcement</strong>：純 alert 走 <a href="/blog/backend/08-incident-response/" data-link-title="模組八：事故處理與復盤" data-link-desc="用 IR 領域詞彙建問題節點、以服務級案例庫累積事故脈絡，先建概念與案例庫再進實作交接">8 事故處理</a> routing；要自動 kill pod / cordon node 需 Falco Talon 或 SOAR、且 high-impact action 走 approval gate</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">Detection Coverage and Signal Governance</a> 邊界的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>Driver layer</strong>：Falco 三種 driver — <em>modern eBPF</em>（CO-RE、Linux 5.8+、預設、不需 kernel header）、<em>legacy kernel module</em>（kmod、舊 kernel 唯一選、要 DKMS build）、<em>pdig</em>（userspace、ptrace-based、非 root container 或 macOS dev 環境用、效能差）。production K8s deployment 幾乎都走 modern eBPF、DaemonSet 部署到每個 node、kernel 版本不夠才走 kmod；不要混用 driver、否則 alert source 難對齊。</p>
<p><strong>Rule YAML 結構</strong>：Falco rule 由 <code>condition</code>（Sysdig filter syntax、類 SQL where）、<code>output</code>（alert template、含 field interpolation）、<code>priority</code>（emergency / alert / critical / error / warning / notice / informational / debug）、<code>tags</code>（mitre / cis / NIST 對應）組成。<code>condition</code> 寫法跟 Linux syscall 緊耦合（<code>evt.type=execve</code>、<code>fd.name=/etc/passwd</code>、<code>proc.name=nc</code>）— rule engineer 要對 syscall 跟 process tree 熟悉。<code>macro</code> 跟 <code>list</code> 讓 rule 可重用（<code>macro: container_started</code> / <code>list: shell_binaries</code>）、production rule 庫應該 macro-first、不是每條 rule 重寫 condition。</p>
<p><strong>Plugin ecosystem</strong>：Plugin 把 Falco 從 host syscall 擴張到任意 event source — <em>k8saudit plugin</em> 接 K8s API server audit log（看 RBAC change / Secret access）、<em>cloudtrail plugin</em> 接 AWS CloudTrail、<em>okta plugin</em> 接 Okta system log、<em>github plugin</em> 接 GitHub audit log。Plugin 讓 Falco 成為 <em>general detection engine</em>、不只 container runtime；但 plugin event source 跟 SIEM 重疊、要清楚 ownership — <em>Falco 做近 host 即時偵測、SIEM 做跨來源歷史 correlation</em>、別兩邊都跑同一條 rule。</p>
<p><strong>Falcosidekick + alert fan-out</strong>：Falco engine 預設輸出 stdout / file / gRPC、production 接 Falcosidekick（DaemonSet 旁邊或單獨 Deployment）做 fan-out — 同一個 alert 同時 forward 到 Slack（SOC chat）、Splunk HEC / Elastic / Loki（SIEM 持久化）、S3（合規 archive）、Webhook（自家 dashboard）、Prometheus（metrics）。Sidekick 是 stateless forwarder、不做 dedup / aggregation、那層要在 SIEM 處理。</p>
<p><strong>Falco Talon + 自動 response</strong>：Talon 是 response orchestrator、訂閱 Falcosidekick 的 webhook output、依照 rule action 自動執行 — kill pod、cordon node、加 NetworkPolicy、call webhook 通知 SOAR。Talon 把 <em>偵測 → 處置</em> 從手動 SOC playbook 變 declarative YAML、但 high-impact action（kill prod pod、cordon node）必須走 approval gate 或限制在 staging namespace、不能黑箱 fire-and-forget。對應 <a href="/blog/backend/07-security-data-protection/blue-team/detection-to-response-routing/" data-link-title="7.B2 從偵測到回應的路由" data-link-desc="建立資安偵測訊號如何轉成 triage、severity、升級與 incident workflow 的大綱">Detection to Response Routing</a> 的章節原則。</p>
<p><strong>Helm chart 部署 + GitOps</strong>：Falco 官方 Helm chart 把 DaemonSet（Falco engine + driver）、Deployment（Falcosidekick）、ConfigMap（rule YAML）、ServiceAccount + RBAC 包成一組。生產 deployment 走 Argo CD / Flux 同步 Helm value、rule YAML 進 Git PR review、merge 觸發 staging tenant deploy、人工觀察 24-48hr false positive、再 promote production。Rule 直接改 ConfigMap、不走版控等於 detection drift、後續審計接不上。</p>
<p><strong>跟 SIEM / 8 事故處理整合</strong>：Falco alert 經 Falcosidekick 進 <a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / <a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a> / <a href="/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &#43; CSPM &#43; CWS &#43; AAP &#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Security</a> 後、走跟其他 detection signal 同一條 correlation + triage 管線、不獨立 channel。Notable / high-priority alert 進 <a href="/blog/backend/08-incident-response/" data-link-title="模組八：事故處理與復盤" data-link-desc="用 IR 領域詞彙建問題節點、以服務級案例庫累積事故脈絡，先建概念與案例庫再進實作交接">8 事故處理</a> 的 IR queue、走 incident commander handoff。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Falco</th>
          <th>Cilium Tetragon</th>
          <th>Datadog CWS</th>
          <th>Lacework Polygraph</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>License</td>
          <td>Apache 2.0 OSS</td>
          <td>Apache 2.0 OSS</td>
          <td>Commercial SaaS</td>
          <td>Commercial SaaS</td>
      </tr>
      <tr>
          <td>Detection 模型</td>
          <td>Rule-explicit（YAML + Sysdig filter）</td>
          <td>Rule-explicit（YAML + TracingPolicy）</td>
          <td>ML-based behavioral baseline + rule</td>
          <td>Behavior graph 自動 baseline</td>
      </tr>
      <tr>
          <td>Enforcement</td>
          <td>Alert-only（Talon 補 response）</td>
          <td>Inline enforce（kill / signal、可阻擋）</td>
          <td>Inline enforce（Datadog Agent）</td>
          <td>Alert + workload baseline drift</td>
      </tr>
      <tr>
          <td>Driver</td>
          <td>modern eBPF / kmod / pdig</td>
          <td>eBPF only（cilium ecosystem）</td>
          <td>eBPF（Datadog Agent）</td>
          <td>eBPF（Lacework Agent）</td>
      </tr>
      <tr>
          <td>涵蓋面</td>
          <td>Container + host + plugin (audit log)</td>
          <td>Container + host（cilium 整合 network）</td>
          <td>Container + host + cloud + app</td>
          <td>Cloud + container + workload + IaC posture</td>
      </tr>
      <tr>
          <td>Cross-source</td>
          <td>靠 Plugin + Falcosidekick → SIEM</td>
          <td>靠 Cilium Hubble + 外接 SIEM</td>
          <td>內建（Datadog observability plane）</td>
          <td>內建（Polygraph graph）</td>
      </tr>
      <tr>
          <td>學習曲線</td>
          <td>中 — Sysdig filter + macro</td>
          <td>中 — TracingPolicy + cilium 知識</td>
          <td>緩 — 沿用 Datadog UI / Workload Security</td>
          <td>緩 — SaaS console</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>OSS-first、SIEM 已部署、rule 想完全可寫</td>
          <td>要 inline enforcement、cilium CNI 已用</td>
          <td>Datadog 已用、cloud-native、預算允許</td>
          <td>CNAPP + posture 一站、跨雲</td>
      </tr>
      <tr>
          <td>退場成本</td>
          <td>低 — rule 是 YAML、可移植 Sigma</td>
          <td>中 — TracingPolicy 跟 cilium 綁定</td>
          <td>高 — Workload Security rule 跟 platform 綁</td>
          <td>高 — Polygraph data 跟 platform 綁</td>
      </tr>
  </tbody>
</table>
<p>選 Falco 的核心訴求：<em>K8s container runtime detection、OSS + rule-customizable、SIEM 已部署、SOC 有 detection engineer 寫得了 Sysdig filter rule</em>。要 inline enforcement 直接走 Tetragon；要 ML baseline + 跨雲 posture + 不想自管 rule lifecycle 直接走 Datadog CWS / Lacework / <a href="/blog/backend/07-security-data-protection/vendors/wiz/" data-link-title="Wiz" data-link-desc="Agentless CNAPP、Security Graph &#43; Toxic Combination 風險優先級、API-only scan 不需 workload agent">Wiz</a> + <a href="/blog/backend/07-security-data-protection/vendors/crowdstrike-falcon-cs/" data-link-title="CrowdStrike Falcon Cloud Security" data-link-desc="CrowdStrike 在 Falcon endpoint EDR 之上的 CNAPP、agent 統一跨 endpoint &#43; workload &#43; container、CrowdStrike Intelligence 內建">CrowdStrike Falcon CS</a>。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Custom rule 設計</strong>：production rule 庫應該 <em>macro-first</em>、把可重用條件抽成 macro（<code>container_started</code> / <code>sensitive_mount</code> / <code>shell_in_container</code>）跟 list（<code>shell_binaries</code> / <code>sensitive_files</code>）；rule 引用 macro 而非重寫 condition、修改 macro 等於同時更新所有引用 rule。Rule 反例是 <em>single-event noisy rule</em>（看到一個 shell exec 就 alert）— production rule 應該 <em>context-bounded</em>（shell exec <strong>in container</strong> + parent <strong>不在 allowlist</strong> + image <strong>非 trusted registry</strong>）+ priority 階梯（生產 Notice、staging Warning、新規則先 Informational 觀察）。</p>
<p><strong>eBPF driver vs kmod 取捨</strong>：modern eBPF 用 CO-RE（Compile Once, Run Everywhere）、不需 per-kernel build、運行時動態 attach；kmod 需要 DKMS 在 host build、跟 kernel version 強耦合、升級 kernel 要重 build。所有現代 Linux distro 預設都該走 modern eBPF；只有 RHEL 7 / 老 Ubuntu LTS（kernel &lt; 5.8）才有理由用 kmod。pdig 給沒 root / 沒 eBPF 的環境（某些 serverless container、macOS dev）、效能差不適合 production。</p>
<p><strong>Falco Talon 自動 response 設計</strong>：Talon 把「Falco alert → 自動處置」變 declarative — rule action 可以是 <em>kubernetes:terminate-pod</em>、<em>kubernetes:label-pod</em>、<em>kubernetes:cordon-node</em>、<em>aws:disable-iam-user</em>、<em>calico:add-networkpolicy</em>。production 用 Talon 的關鍵原則：<em>high-impact action 走 approval gate</em>（PagerDuty incident → human approve → execute）、<em>containment-first not deletion</em>（先 cordon + label、再人工決定是否 terminate）、<em>blast radius 限制</em>（只能影響特定 namespace / label selector）、<em>audit trail</em>（每個 action 進 Splunk + IR queue）。</p>
<p><strong>Plugin ecosystem 邊界</strong>：Plugin 把 Falco 變 general detection engine、但要明確 plugin event 跟 SIEM 重疊處的 ownership。建議：<em>host syscall + container runtime → Falco rule</em>（即時 + low latency）、<em>K8s audit + cloud audit + IdP audit → 同時跑 Falco plugin（近即時 alert） + SIEM（歷史 correlation）</em>、<em>純跨來源 correlation（多 user 多 source 多時段）→ SIEM 為主</em>。別讓 Falco plugin 跟 SIEM rule 跑重複條件、會 double-alert 也 double-cost。</p>
<p><strong>Sigstore + SBOM 整合的位置</strong>：Falco 不做 image scan / SBOM 驗證（那是 <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> / <a href="/blog/backend/07-security-data-protection/vendors/syft-grype/" data-link-title="Syft &#43; Grype" data-link-desc="Anchore 開源姐妹工具：Syft 產 SBOM (CycloneDX / SPDX) &#43; Grype scan 漏洞、Unix philosophy、cosign attestation 整合">Syft &amp; Grype</a> 的位置）、但 runtime detection 是 <a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">Supply Chain Integrity</a> 縱深防禦的最後一層 — image scan 過、簽章驗證過、但 runtime 出現異常 syscall（log4shell 觸發 outbound LDAP、SolarWinds 合法簽章但行為異常）、Falco rule 是最後抓的點。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Falco 啟動成功但完全沒 event</strong>：driver 沒載入（modern eBPF 在舊 kernel fallback 失敗）— 看啟動 log 確認 <code>driver loaded successfully</code>、<code>falco --version</code> 對 driver 版本、舊 kernel 改 kmod</li>
<li><strong>大量 false positive 淹沒 SOC</strong>：rule 寫太寬（<code>shell in container</code> 但合法 debug shell 也 trigger）— staging tenant 跑 48hr 統計 FP、加 exception list 或改 macro 排除已知合法 source、新 rule 先 Informational priority 觀察</li>
<li><strong>Alert 沒進 SIEM</strong>：Falcosidekick 沒接、或 output channel 設錯 — 確認 Falcosidekick Deployment up、output webhook 對、SIEM HEC token 沒過期；Falco engine 本身的 stdout / file output 仍會留、不會 silent miss</li>
<li><strong>Rule update 後 detection drift</strong>：直接改 ConfigMap、沒走 Git PR + staging 觀察 — 強制 GitOps（Argo CD / Flux）、ConfigMap immutable、rule change 必須走 PR review + staging promote</li>
<li><strong>Plugin event lag / 漏抓</strong>：plugin polling cloud audit log（CloudTrail / Okta）的 latency 跟 API rate limit、不是即時 — 純即時偵測別靠 plugin、改靠 SIEM streaming ingest；plugin 適合補 syscall 看不到的層</li>
<li><strong>Talon 自動 response 誤殺 prod</strong>：rule action 直接 kill pod、沒 approval gate — 高影響 action 拆成兩步（先 label + cordon、再人工 approve terminate）、blast radius 限 namespace / label selector、audit trail 全進 SIEM</li>
<li><strong>eBPF driver 跟 kernel 升級不對齊</strong>：node kernel 升級後 modern eBPF 仍 CO-RE 自動適配、但 Falco 版本太舊不支援新 syscall — Falco engine 跟著定期升級、別 pin 在兩年前的 version</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>要 inline kill / enforcement</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/cilium-tetragon/" data-link-title="Cilium Tetragon" data-link-desc="eBPF-based runtime security &#43; inline enforcement、跟 Cilium CNI 同生態、TracingPolicy CRD、process credentials tracking &#43; KillerAction">Cilium Tetragon</a></td>
      </tr>
      <tr>
          <td>ML behavioral baseline + 跨雲</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &#43; CSPM &#43; CWS &#43; AAP &#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Security</a>、<a href="/blog/backend/07-security-data-protection/vendors/lacework/" data-link-title="Lacework" data-link-desc="CNAPP 走 Polygraph ML behavioral baseline 路線、2024 跟 Fortinet 合併成 FortiCNAPP、自動學 normal、anomaly 自動 alert">Lacework</a>、<a href="/blog/backend/07-security-data-protection/vendors/wiz/" data-link-title="Wiz" data-link-desc="Agentless CNAPP、Security Graph &#43; Toxic Combination 風險優先級、API-only scan 不需 workload agent">Wiz</a></td>
      </tr>
      <tr>
          <td>Full CNAPP + posture + runtime</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/prisma-cloud/" data-link-title="Prisma Cloud" data-link-desc="Palo Alto CNAPP、agent (Defender) &#43; agentless 雙軌、五模組（Compute / CSPM / Code / Data / CIEM）、Compliance template 強">Prisma Cloud</a>、<a href="/blog/backend/07-security-data-protection/vendors/crowdstrike-falcon-cs/" data-link-title="CrowdStrike Falcon Cloud Security" data-link-desc="CrowdStrike 在 Falcon endpoint EDR 之上的 CNAPP、agent 統一跨 endpoint &#43; workload &#43; container、CrowdStrike Intelligence 內建">CrowdStrike Falcon CS</a></td>
      </tr>
      <tr>
          <td>Image scan / SBOM / SCA</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a>、<a href="/blog/backend/07-security-data-protection/vendors/syft-grype/" data-link-title="Syft &#43; Grype" data-link-desc="Anchore 開源姐妹工具：Syft 產 SBOM (CycloneDX / SPDX) &#43; Grype scan 漏洞、Unix philosophy、cosign attestation 整合">Syft &amp; Grype</a>、<a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk</a></td>
      </tr>
      <tr>
          <td>Cross-source SIEM correlation</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a>、<a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a>、<a href="/blog/backend/07-security-data-protection/vendors/google-security-operations/" data-link-title="Google Security Operations" data-link-desc="Google 雲原生 SIEM &#43; SOAR &#43; Mandiant threat intel 三合一（前 Chronicle）、UDM &#43; YARA-L、fixed-price by data tier、PB-scale 友善">Google Security Operations</a></td>
      </tr>
      <tr>
          <td>Incident routing</td>
          <td><a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Sysdig filter syntax 完整 reference、syscall field 細目</li>
<li>Falco source code 內部架構（libsinsp / libscap）</li>
<li>Sysdig Secure（Falco 的商業版、Sysdig Inc. 維護、含 ML baseline + cloud posture）的功能對照細節</li>
<li>Container image scan / SBOM 驗證（屬 <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> / <a href="/blog/backend/07-security-data-protection/vendors/syft-grype/" data-link-title="Syft &#43; Grype" data-link-desc="Anchore 開源姐妹工具：Syft 產 SBOM (CycloneDX / SPDX) &#43; Grype scan 漏洞、Unix philosophy、cosign attestation 整合">Syft &amp; Grype</a> 的位置）</li>
<li>Kubernetes RBAC / Pod Security Standards / NetworkPolicy 的設計（屬 K8s 平台層、不在 runtime detection 範圍）</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>Falco 在 07 案例庫沒有直接 vendor-level 事件、但多個 runtime / supply chain case 都是 Falco rule 第一線該抓的場景：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 Falco 的關係（對照啟示）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/3cx-2023-desktopapp-supply-chain/" data-link-title="7.R7.2.8 3CX 2023：桌面軟體更新鏈攻擊" data-link-desc="合法更新流程被植入後，桌面端供應鏈事件如何傳到企業端點">3CX 2023 Desktop App Supply Chain</a></td>
          <td>Falco rule 偵測 desktop app process spawn 異常子程序 + outbound callback、補簽章驗證之外的 runtime 行為層</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/log4shell-cve-2021-44228-component-chain/" data-link-title="7.R7.2.7 Log4Shell 2021：共用元件風險與修補鏈" data-link-desc="共用元件漏洞如何同步影響多服務，並迫使團隊建立依賴治理 workflow">Log4Shell CVE-2021-44228</a></td>
          <td>Falco rule 偵測 JNDI lookup 觸發的 outbound LDAP / DNS、補 <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> image scan 之外的 runtime detection</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/solarwinds-2020-sunburst/" data-link-title="7.R7.2.1 SolarWinds 2020：更新鏈被濫用" data-link-desc="合法更新流程遭植入後，攻擊者如何長期潛伏與橫向擴散">SolarWinds 2020 Sunburst</a></td>
          <td>合法簽章 binary 但 runtime 行為異常（process tree / outbound C2 / 異常 file access）、Falco rule + Talon containment 是最後一層</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/data-exfiltration/snowflake-2024-credential-abuse/" data-link-title="7.R7.4.2 Snowflake 2024：憑證濫用與資料竊取" data-link-desc="外洩憑證與 MFA 缺口如何在資料平台形成高風險外送事件">Snowflake 2024 Credential Abuse</a></td>
          <td>對照啟示：Falco 主場是 host / container runtime、cloud-native data warehouse 行為偵測要走 SIEM + 平台層 audit、非 Falco 範圍</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/blue-team/detection-engineering-lifecycle/" data-link-title="7.B5 Detection Engineering Lifecycle" data-link-desc="把偵測規則視為可維護資產，建立從來源、測試、調校到退場的完整生命週期">Detection Engineering Lifecycle (section)</a></td>
          <td>Falco rule + macro + list 走 propose → staging tune → promote → review 的工程 lifecycle、不是 ConfigMap 直改</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/blue-team/alert-fatigue-and-signal-quality/" data-link-title="7.B10 Alert Fatigue and Signal Quality" data-link-desc="建立告警疲勞治理方法，讓訊號品質、分級一致性與處置效率同步提升">Alert Fatigue and Signal Quality (section)</a></td>
          <td>Falco rule priority 階梯（新規則先 Informational、staging 觀察 48hr、再 promote Warning / Critical）是 alert fatigue 的工程化解法</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">7.13 偵測覆蓋率與訊號治理</a>、<a href="/blog/backend/07-security-data-protection/blue-team/detection-engineering-lifecycle/" data-link-title="7.B5 Detection Engineering Lifecycle" data-link-desc="把偵測規則視為可維護資產，建立從來源、測試、調校到退場的完整生命週期">Detection Engineering Lifecycle</a>、<a href="/blog/backend/07-security-data-protection/blue-team/detection-to-response-routing/" data-link-title="7.B2 從偵測到回應的路由" data-link-desc="建立資安偵測訊號如何轉成 triage、severity、升級與 incident workflow 的大綱">Detection to Response Routing</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/cilium-tetragon/" data-link-title="Cilium Tetragon" data-link-desc="eBPF-based runtime security &#43; inline enforcement、跟 Cilium CNI 同生態、TracingPolicy CRD、process credentials tracking &#43; KillerAction">Cilium Tetragon</a>、<a href="/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &#43; CSPM &#43; CWS &#43; AAP &#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Security</a>、<a href="/blog/backend/07-security-data-protection/vendors/lacework/" data-link-title="Lacework" data-link-desc="CNAPP 走 Polygraph ML behavioral baseline 路線、2024 跟 Fortinet 合併成 FortiCNAPP、自動學 normal、anomaly 自動 alert">Lacework</a>、<a href="/blog/backend/07-security-data-protection/vendors/prisma-cloud/" data-link-title="Prisma Cloud" data-link-desc="Palo Alto CNAPP、agent (Defender) &#43; agentless 雙軌、五模組（Compute / CSPM / Code / Data / CIEM）、Compliance template 強">Prisma Cloud</a></li>
<li>下游：<a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / <a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-security-operations/" data-link-title="Google Security Operations" data-link-desc="Google 雲原生 SIEM &#43; SOAR &#43; Mandiant threat intel 三合一（前 Chronicle）、UDM &#43; YARA-L、fixed-price by data tier、PB-scale 友善">Google Security Operations</a>（Falco alert 進 SIEM 做 cross-source correlation）</li>
<li>跨類：<a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> / <a href="/blog/backend/07-security-data-protection/vendors/syft-grype/" data-link-title="Syft &#43; Grype" data-link-desc="Anchore 開源姐妹工具：Syft 產 SBOM (CycloneDX / SPDX) &#43; Grype scan 漏洞、Unix philosophy、cosign attestation 整合">Syft &amp; Grype</a>（image scan + SBOM、跟 runtime detection 構成 supply chain 縱深）、<a href="/blog/backend/07-security-data-protection/vendors/wiz/" data-link-title="Wiz" data-link-desc="Agentless CNAPP、Security Graph &#43; Toxic Combination 風險優先級、API-only scan 不需 workload agent">Wiz</a> / <a href="/blog/backend/07-security-data-protection/vendors/crowdstrike-falcon-cs/" data-link-title="CrowdStrike Falcon Cloud Security" data-link-desc="CrowdStrike 在 Falcon endpoint EDR 之上的 CNAPP、agent 統一跨 endpoint &#43; workload &#43; container、CrowdStrike Intelligence 內建">CrowdStrike Falcon CS</a>（商業 CNAPP runtime 對照）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（Falco notable alert → IR routing）、<a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">Supply Chain Integrity</a>（artifact trust 跟 runtime detection 的縱深關係）</li>
<li>官方：<a href="https://falco.org/docs/">Falco Documentation</a>、<a href="https://github.com/falcosecurity/rules">Falco Rules Repository</a></li>
</ul>
]]></content:encoded></item><item><title>MySQL 5.7 → 8.0 Major Version Upgrade：character set / authentication / atomic DDL 三條 paradigm 同時換軌</title><link>https://tarrragon.github.io/blog/backend/01-database/vendors/mysql/major-version-upgrade/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/01-database/vendors/mysql/major-version-upgrade/</guid><description>&lt;blockquote>
&lt;p>本文是 &lt;a href="https://tarrragon.github.io/blog/backend/01-database/vendors/mysql/" data-link-title="MySQL" data-link-desc="高併發網路服務常用關聯式資料庫、Vitess / PlanetScale 分片生態、GitHub / Shopify / Facebook 規模驗證">MySQL&lt;/a> 內 version upgrade migration playbook、走 &lt;a href="https://tarrragon.github.io/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">Migration playbook methodology&lt;/a> Type E paradigm shift 結構。&lt;/p>&lt;/blockquote>
&lt;p>5.7 → 8.0 看起來是 &lt;em>minor bump&lt;/em>（從 5.7.40 升到 8.0.36）、但不是。Oracle 把這個 release boundary 當成 &lt;em>清庫存的機會&lt;/em> — 同時推出 3 個 &lt;em>behavioral paradigm shift&lt;/em>：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Paradigm&lt;/th>
 &lt;th>5.7 default&lt;/th>
 &lt;th>8.0 default&lt;/th>
 &lt;th>影響&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Character set&lt;/td>
 &lt;td>latin1 / utf8（=utf8mb3）&lt;/td>
 &lt;td>utf8mb4&lt;/td>
 &lt;td>string column 儲存 + emoji / 4-byte UTF-8&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Authentication plugin&lt;/td>
 &lt;td>mysql_native_password&lt;/td>
 &lt;td>caching_sha2_password&lt;/td>
 &lt;td>client / library 需要支援新 plugin&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>DDL atomicity&lt;/td>
 &lt;td>Non-atomic（crash 留 orphan）&lt;/td>
 &lt;td>Atomic（crash recovery 乾淨）&lt;/td>
 &lt;td>開發信心、crash recovery 行為&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>對應 &lt;em>任意一個&lt;/em> paradigm 升級失誤、production 都會 down。三條同時換、必須 &lt;em>三條都規劃&lt;/em>。&lt;/p>
&lt;p>這條 upgrade 比 &lt;a href="https://tarrragon.github.io/blog/backend/01-database/vendors/postgresql/major-version-upgrade/" data-link-title="PostgreSQL major version upgrade (14 → 17)：為什麼這篇不套 5 type migration" data-link-desc="PostgreSQL major version upgrade 是 *5 type 漏類* 的實證 — source/target 同 vendor、5 維度都 Low 但 *upgrade-specific audit* 是核心；本文結構接近 deep article methodology 的 6-section &amp;#43; 額外 upgrade audit 段；涵蓋 pg_upgrade / logical replication / blue-green 三方法、extension 相容性、5 production 踩雷">PostgreSQL major-version-upgrade&lt;/a> 工作量大 — PG major upgrade 主要是 &lt;em>pg_upgrade&lt;/em> 工具流程、MySQL 是 &lt;em>behavioral compatibility audit + ecosystem 全 review&lt;/em>。&lt;/p>
&lt;h2 id="為什麼是-type-e不是-minor-upgrade">為什麼是 Type E（不是 minor upgrade）&lt;/h2>
&lt;p>跑 &lt;a href="https://tarrragon.github.io/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/#%e5%af%ab%e5%89%8d%e7%9a%84-diff-dimension-audit" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">6 維 diff dimension audit&lt;/a>：&lt;/p></description><content:encoded><![CDATA[<blockquote>
<p>本文是 <a href="/blog/backend/01-database/vendors/mysql/" data-link-title="MySQL" data-link-desc="高併發網路服務常用關聯式資料庫、Vitess / PlanetScale 分片生態、GitHub / Shopify / Facebook 規模驗證">MySQL</a> 內 version upgrade migration playbook、走 <a href="/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">Migration playbook methodology</a> Type E paradigm shift 結構。</p></blockquote>
<p>5.7 → 8.0 看起來是 <em>minor bump</em>（從 5.7.40 升到 8.0.36）、但不是。Oracle 把這個 release boundary 當成 <em>清庫存的機會</em> — 同時推出 3 個 <em>behavioral paradigm shift</em>：</p>
<table>
  <thead>
      <tr>
          <th>Paradigm</th>
          <th>5.7 default</th>
          <th>8.0 default</th>
          <th>影響</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Character set</td>
          <td>latin1 / utf8（=utf8mb3）</td>
          <td>utf8mb4</td>
          <td>string column 儲存 + emoji / 4-byte UTF-8</td>
      </tr>
      <tr>
          <td>Authentication plugin</td>
          <td>mysql_native_password</td>
          <td>caching_sha2_password</td>
          <td>client / library 需要支援新 plugin</td>
      </tr>
      <tr>
          <td>DDL atomicity</td>
          <td>Non-atomic（crash 留 orphan）</td>
          <td>Atomic（crash recovery 乾淨）</td>
          <td>開發信心、crash recovery 行為</td>
      </tr>
  </tbody>
</table>
<p>對應 <em>任意一個</em> paradigm 升級失誤、production 都會 down。三條同時換、必須 <em>三條都規劃</em>。</p>
<p>這條 upgrade 比 <a href="/blog/backend/01-database/vendors/postgresql/major-version-upgrade/" data-link-title="PostgreSQL major version upgrade (14 → 17)：為什麼這篇不套 5 type migration" data-link-desc="PostgreSQL major version upgrade 是 *5 type 漏類* 的實證 — source/target 同 vendor、5 維度都 Low 但 *upgrade-specific audit* 是核心；本文結構接近 deep article methodology 的 6-section &#43; 額外 upgrade audit 段；涵蓋 pg_upgrade / logical replication / blue-green 三方法、extension 相容性、5 production 踩雷">PostgreSQL major-version-upgrade</a> 工作量大 — PG major upgrade 主要是 <em>pg_upgrade</em> 工具流程、MySQL 是 <em>behavioral compatibility audit + ecosystem 全 review</em>。</p>
<h2 id="為什麼是-type-e不是-minor-upgrade">為什麼是 Type E（不是 minor upgrade）</h2>
<p>跑 <a href="/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/#%e5%af%ab%e5%89%8d%e7%9a%84-diff-dimension-audit" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">6 維 diff dimension audit</a>：</p>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>評</th>
          <th>說明</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Schema</td>
          <td>Medium</td>
          <td>SQL 一致、reserved keyword 新增、collation 預設變</td>
      </tr>
      <tr>
          <td>Operational</td>
          <td>Medium-High</td>
          <td>binary upgrade flow 簡單、但 ecosystem 工具兼容性 audit 工作量大</td>
      </tr>
      <tr>
          <td>Paradigm</td>
          <td>High</td>
          <td>3 條 default paradigm shift（charset / auth / atomic DDL）</td>
      </tr>
      <tr>
          <td>Components</td>
          <td>Low</td>
          <td>同 MySQL 引擎、不引新 component</td>
      </tr>
      <tr>
          <td>App change</td>
          <td>Medium-High</td>
          <td>client library / driver / connection string 都可能要改</td>
      </tr>
      <tr>
          <td>Topology</td>
          <td>Low</td>
          <td>部署 topology 不變</td>
      </tr>
  </tbody>
</table>
<p>Paradigm = High + App change = Medium-High → <strong>Type E paradigm shift</strong>。</p>
<p>雖然是 <em>同一個 vendor 的 major version</em>、實際的 <em>application 行為差異</em> 跨越多個 paradigm、6 type 框架仍適用、結構走 partial migration 收斂。</p>
<h2 id="4-phase-upgrade">4-phase upgrade</h2>
<h3 id="phase-1pre-check-audit">Phase 1：Pre-check audit</h3>
<p>8.0 升級前用 <em>MySQL Shell upgrade checker</em> + 手動 audit：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">mysqlsh root@5.7-primary.example.com -- util check-for-server-upgrade</span></span></code></pre></div><p>Upgrade checker 報告：</p>
<ul>
<li><em>Reserved keyword</em> 衝突（5.7 不是 keyword 但 8.0 是、例如 <code>WINDOW</code> / <code>RANK</code> / <code>LATERAL</code>）</li>
<li>舊 character set / collation 使用點（latin1 / utf8mb3）</li>
<li>Deprecated feature 使用（GROUP BY 隱含 ORDER BY 等）</li>
<li>Datatype 變動（DATETIME 行為微差）</li>
</ul>
<p>手動 audit：</p>
<ul>
<li>Application driver / library 版本是否支援 caching_sha2_password</li>
<li>Connection string 內 <code>default-authentication-plugin</code> 設定</li>
<li>ORM / framework 是否假設 utf8 而非 utf8mb4</li>
</ul>
<p>完成標準：寫出 <em>blocker list</em>（必須在升級前修） + <em>warning list</em>（可在升級後處理）。</p>
<h3 id="phase-2shadow-upgrade--replica-升-80">Phase 2：Shadow upgrade — Replica 升 8.0</h3>
<p>從 <em>non-critical replica</em> 升起。先升一個 replica、跑 production traffic（read-only）2-4 週：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># 1. Stop replica</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">systemctl stop mysql
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c1"># 2. Backup（XtraBackup）</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">xtrabackup --backup --target-dir<span class="o">=</span>/backup/pre-upgrade
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="c1"># 3. Install MySQL 8.0 binary（apt / yum 升級）</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">apt-get install mysql-server-8.0
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="c1"># 4. 啟動 8.0、自動 upgrade data dictionary</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">systemctl start mysql
</span></span><span class="line"><span class="ln">12</span><span class="cl">
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="c1"># 5. 8.0 自動跑 server-upgrade（8.0.16+ 內建、mysql_upgrade utility 已 deprecated）</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="c1"># 若 5.7 升 8.0.16 之前 server、才需要手動跑 mysql_upgrade -u root -p</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">
</span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="c1"># 6. 重新 attach 為 5.7 primary 的 replica（8.0 replica 可 attach 5.7 primary）</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">CHANGE MASTER TO <span class="nv">MASTER_AUTO_POSITION</span><span class="o">=</span>1<span class="p">;</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">START SLAVE<span class="p">;</span></span></span></code></pre></div><p>跑 production read traffic 觀察：</p>
<ul>
<li>Query result 是否跟 5.7 一致（特別 character set 相關）</li>
<li>Replication lag 是否在 baseline 範圍</li>
<li>8.0-specific feature 是否需要（hash join / window function 等）</li>
</ul>
<h3 id="phase-3promote-80-為-primary">Phase 3：Promote 8.0 為 primary</h3>
<p>確認 shadow replica 穩定後：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># 1. 升其他 replica 到 8.0</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="c1"># （per-replica 跑 Phase 2 流程）</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c1"># 2. Application application 改用 8.0-compatible driver</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="c1"># 把 connection string 加 default-authentication-plugin=caching_sha2_password</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="c1"># 或仍用 mysql_native_password（user 端設定）</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="c1"># 3. Failover：promote 8.0 replica 為 primary</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="c1"># 用 Orchestrator / 自管 failover 流程</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="c1"># 4. 5.7 primary 變成 8.0 replica、升 5.7 → 8.0</span></span></span></code></pre></div><p>完成標準：所有 server 都是 8.0、application 連 8.0 endpoint 無 error。</p>
<h3 id="phase-4decommission-57--套用-80-paradigm">Phase 4：Decommission 5.7 + 套用 8.0 paradigm</h3>
<p>完成 binary upgrade 不是真正完成 — 還要逐步遷移 paradigm：</p>
<ul>
<li>
<p><strong>Character set 升級</strong>：歷史 latin1 / utf8 table 改 utf8mb4</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sql" data-lang="sql"><span class="line"><span class="ln">1</span><span class="cl"><span class="k">ALTER</span><span class="w"> </span><span class="k">TABLE</span><span class="w"> </span><span class="n">orders</span><span class="w"> </span><span class="k">CONVERT</span><span class="w"> </span><span class="k">TO</span><span class="w"> </span><span class="nb">CHARACTER</span><span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="n">utf8mb4</span><span class="w"> </span><span class="k">COLLATE</span><span class="w"> </span><span class="n">utf8mb4_0900_ai_ci</span><span class="p">;</span></span></span></code></pre></div><p>每張 table 走 gh-ost / pt-osc（避免 production 阻塞）</p>
</li>
<li>
<p><strong>Authentication 升級</strong>：逐步把 user 從 <code>mysql_native_password</code> 改 <code>caching_sha2_password</code></p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sql" data-lang="sql"><span class="line"><span class="ln">1</span><span class="cl"><span class="k">ALTER</span><span class="w"> </span><span class="k">USER</span><span class="w"> </span><span class="s1">&#39;app&#39;</span><span class="o">@</span><span class="s1">&#39;%&#39;</span><span class="w"> </span><span class="n">IDENTIFIED</span><span class="w"> </span><span class="k">WITH</span><span class="w"> </span><span class="n">caching_sha2_password</span><span class="w"> </span><span class="k">BY</span><span class="w"> </span><span class="s1">&#39;new_password&#39;</span><span class="p">;</span></span></span></code></pre></div><p>需確認 application driver 已支援新 plugin（多數 modern driver OK、legacy 可能要升級）</p>
</li>
<li>
<p><strong>Reserved keyword 處理</strong>：column / table 名稱跟新 reserved word 衝突的、改名</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sql" data-lang="sql"><span class="line"><span class="ln">1</span><span class="cl"><span class="k">ALTER</span><span class="w"> </span><span class="k">TABLE</span><span class="w"> </span><span class="n">events</span><span class="w"> </span><span class="k">RENAME</span><span class="w"> </span><span class="k">COLUMN</span><span class="w"> </span><span class="n">window</span><span class="w"> </span><span class="k">TO</span><span class="w"> </span><span class="n">event_window</span><span class="p">;</span></span></span></code></pre></div></li>
</ul>
<p>多數 org 在 Phase 3 停留更久 — paradigm 升級不是一次 big bang、是漸進。</p>
<h2 id="5-個-production-踩雷">5 個 Production 踩雷</h2>
<h3 id="1-authentication-plugin--application-突然連不上">1. Authentication plugin — Application 突然連不上</h3>
<p>升 8.0 後 <em>new user</em> 預設用 caching_sha2_password、舊 application driver（&lt; 5 年版本）不支援、connect error: <code>Authentication plugin 'caching_sha2_password' cannot be loaded</code>。</p>
<p>修法：</p>
<ul>
<li><em>先升 driver</em>：每個 application 升級 mysql-connector-* 到支援 caching_sha2 的版本（多數 modern release 已支援）</li>
<li>短期 workaround：用 <code>mysql_native_password</code>（new user 顯式 create with <code>IDENTIFIED WITH mysql_native_password</code>）</li>
<li>設 <code>default_authentication_plugin=mysql_native_password</code>、強制保留舊 default</li>
</ul>
<h3 id="2-character-set-4-byte-utf-8--emoji-進不去">2. Character set 4-byte UTF-8 — Emoji 進不去</h3>
<p>5.7 latin1 / utf8（=utf8mb3）column 升 8.0 後 <em>仍是 utf8mb3</em>、不會自動升 utf8mb4。Application 寫入 emoji（4-byte UTF-8）會被 <em>truncate / 拒絕</em>。</p>
<p>修法：</p>
<ul>
<li><em>逐 table CONVERT</em>：gh-ost / pt-osc 跑 <code>ALTER TABLE ... CONVERT TO CHARACTER SET utf8mb4</code></li>
<li>新建 table 預設用 utf8mb4（<code>character_set_server=utf8mb4</code> 設定）</li>
<li>Application 連線 charset 設定一致（<code>character_set_client / connection / results</code>）</li>
</ul>
<h3 id="3-reserved-keyword--application-query-突然-syntax-error">3. Reserved keyword — Application query 突然 syntax error</h3>
<p>5.7 跑得好的 query：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sql" data-lang="sql"><span class="line"><span class="ln">1</span><span class="cl"><span class="k">SELECT</span><span class="w"> </span><span class="n">window</span><span class="p">,</span><span class="w"> </span><span class="n">rank</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">events</span><span class="p">;</span></span></span></code></pre></div><p>8.0 報錯：<code>window</code> 跟 <code>rank</code> 都是 reserved keyword、必須 backtick：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sql" data-lang="sql"><span class="line"><span class="ln">1</span><span class="cl"><span class="k">SELECT</span><span class="w"> </span><span class="o">`</span><span class="n">window</span><span class="o">`</span><span class="p">,</span><span class="w"> </span><span class="o">`</span><span class="n">rank</span><span class="o">`</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">events</span><span class="p">;</span></span></span></code></pre></div><p>修法：</p>
<ul>
<li>Phase 1 upgrade checker 已抓出來、Application code review 改 SQL</li>
<li>推薦 <em>predefer table / column 名 backtick</em> policy（一律加 backtick、避免未來 reserved word 衝突）</li>
<li>ORM 多數會自動 backtick、raw SQL 容易踩</li>
</ul>
<h3 id="4-group-replication--新-feature-開了就不能-rollback">4. Group Replication / 新 feature 開了就不能 rollback</h3>
<p>8.0 升級後 <em>誘惑使用 8.0-only feature</em>：</p>
<ul>
<li>Group Replication（5.7 也有但 8.0 更穩）</li>
<li>Resource Group（5.7 沒有）</li>
<li>Histograms（5.7 沒有）</li>
<li>CTE / window function（5.7 沒有）</li>
</ul>
<p>一旦 application 用了這些 feature、不能 rollback 5.7（feature 不存在、query 失敗）。</p>
<p>修法：</p>
<ul>
<li><em>Phase 1-3 期間禁用 8.0-only feature</em>、保留 rollback option</li>
<li><em>Phase 4 完成</em> 且穩定運作 30+ 天後、才開始 evaluate 8.0-only feature</li>
<li>加 8.0-only feature 時 <em>明確記錄不可 rollback</em></li>
</ul>
<h3 id="5-collation-default-變動--sort-order-跟-unique-行為改變">5. Collation default 變動 — Sort order 跟 unique 行為改變</h3>
<p>5.7 utf8mb4 預設 collation = <code>utf8mb4_general_ci</code>、8.0 預設 = <code>utf8mb4_0900_ai_ci</code>。兩者排序行為不一致：</p>
<ul>
<li><code>utf8mb4_general_ci</code>：簡化 collation、不嚴格遵循 Unicode</li>
<li><code>utf8mb4_0900_ai_ci</code>：Unicode 9.0 compliance、accent-insensitive</li>
</ul>
<p>對 <em>已存在的 table</em>、collation 不會被 8.0 升級改變（保留 5.7 設定）。但 <em>新建 table</em> 預設用 0900_ai_ci、UNION / JOIN 跨不同 collation 的 column 可能 error: <code>Illegal mix of collations</code>。</p>
<p>修法：</p>
<ul>
<li>統一 collation：要麼 <em>所有 table 改 0900_ai_ci</em>、要麼 <em>所有 table 保留 general_ci</em></li>
<li>Schema migration 走 OSC 工具</li>
<li>Application 內 sort-dependent logic（leaderboard / search ranking）要驗證新 collation 結果</li>
</ul>
<h2 id="capability-gap57-有但-80-沒有">Capability gap：5.7 有但 8.0 沒有</h2>
<p>少數 8.0 <em>拿走</em> 的能力：</p>
<ul>
<li><strong>Query Cache</strong>：5.7 內建（但已 deprecated）、8.0 <em>完全移除</em>。Query cache 在高並發場景 actually slowing down、移除是好事</li>
<li><strong>InnoDB MEMORY engine</strong>：5.7 部分支援、8.0 限制更多</li>
<li><strong>Some MyISAM optimizations</strong>：8.0 強制 InnoDB-first、MyISAM-specific 工作流 broken</li>
</ul>
<p>對 Query Cache user：升 8.0 前評估是否依賴、考慮改 application-side cache（Redis）。</p>
<h2 id="容量與成本對照">容量與成本對照</h2>
<table>
  <thead>
      <tr>
          <th>項目</th>
          <th>5.7</th>
          <th>8.0</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Cost</td>
          <td>Free (CE) / Enterprise</td>
          <td>Free (CE) / Enterprise</td>
      </tr>
      <tr>
          <td>升級 hosts × 時間</td>
          <td>-</td>
          <td>per-instance ~30 分鐘 binary upgrade</td>
      </tr>
      <tr>
          <td>Application 改動</td>
          <td>-</td>
          <td>driver upgrade + SQL review</td>
      </tr>
      <tr>
          <td>Character set conversion</td>
          <td>-</td>
          <td>per-table OSC、大表小時級</td>
      </tr>
      <tr>
          <td>Ops headcount</td>
          <td>-</td>
          <td>1-2 個 DBA × 2-4 週</td>
      </tr>
      <tr>
          <td>對 production 影響</td>
          <td>-</td>
          <td>Phase 2-3 漸進升級、無大 downtime</td>
      </tr>
  </tbody>
</table>
<p>5.7 → 8.0 upgrade 整體成本是 <em>1-2 個 FTE 月</em> 規模。對中型 deployment（100+ DB）可能更多。</p>
<h2 id="何時不升">何時不升</h2>
<ul>
<li><strong>App 用 Query Cache 重度</strong>：8.0 沒了、要 application 改造</li>
<li><strong>Old driver 不能升</strong>：legacy enterprise application 用 10 年前 driver、driver vendor 已倒、無法升 8.0-compatible</li>
<li><strong>Compliance freeze</strong>：某些金融 / 醫療場景 freeze technology 多年、升級需要重 audit + recertification</li>
<li><strong>5.7 已 EOL（2023-10）後仍堅持不升</strong>：security risk 高、應該 <em>優先升</em></li>
</ul>
<h2 id="跟-postgresql-major-version-upgrade-對比">跟 PostgreSQL Major Version Upgrade 對比</h2>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>MySQL 5.7 → 8.0</th>
          <th>PostgreSQL N → N+1</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Tool</td>
          <td>binary upgrade + 自動 server-upgrade（8.0.16+；舊版用 mysql_upgrade）</td>
          <td>pg_upgrade（in-place）</td>
      </tr>
      <tr>
          <td>Downtime</td>
          <td>&lt; 5 分鐘 per instance（binary + DD upgrade）</td>
          <td>&lt; 1 分鐘 per instance（pg_upgrade）</td>
      </tr>
      <tr>
          <td>Paradigm shift</td>
          <td>3 條（charset / auth / atomic DDL）</td>
          <td>一般 0-1 條（PG major 多保 compat）</td>
      </tr>
      <tr>
          <td>App 必須改</td>
          <td>多（driver + query）</td>
          <td>少（多數 query 兼容）</td>
      </tr>
      <tr>
          <td>Risk</td>
          <td>高（paradigm 多）</td>
          <td>中-低</td>
      </tr>
      <tr>
          <td>Rollback</td>
          <td>不可（一旦 atomic DDL data 寫入、5.7 不認）</td>
          <td>不可（pg_upgrade 不可逆）</td>
      </tr>
  </tbody>
</table>
<p>PG major upgrade 比 MySQL 簡單。MySQL 5.7 → 8.0 是 <em>特例</em> — Oracle 把多年 deprecated 一次清。8.0 → 8.4 / 9.x 預期更平順。</p>
<h2 id="跟其他模組整合">跟其他模組整合</h2>
<h3 id="跟-replication-topology">跟 Replication topology</h3>
<p>8.0 replica 可 attach 5.7 primary（向下兼容）、但 5.7 replica <em>不能 attach 8.0 primary</em>（向上不兼容）。Upgrade 順序必須 <em>replica 先升、primary 後升</em>。詳見 <a href="/blog/backend/01-database/vendors/mysql/replication-topology/" data-link-title="MySQL Replication Topology：async / semi-sync / GTID 不是三選一、是三個 trade-off 軸的疊加" data-link-desc="MySQL replication 不是「選 async 還是 semi-sync」、是 *durability / latency / consistency* 三個 trade-off 軸的疊加；GTID 是跨 mode 的 infrastructure layer、不是第三種 mode。本文走 3 軸取捨模型 → async / semi-sync 行為對比 → GTID 替代 binlog-position 的好處 → 配置 step-by-step → 5 production 踩雷（lag 暴衝 / semi-sync 退回 async / GTID gap / Loss-Less semi-sync 真的 loss-less / chained replication 雪崩）→ 跟 Aurora MySQL / Vitess / ProxySQL / Orchestrator 整合">Replication Topology</a>。</p>
<h3 id="跟-innodb-tuning">跟 InnoDB Tuning</h3>
<p>8.0 InnoDB 改寫了 redo log（atomic、可動態調整）、<code>innodb_log_file_size</code> 升級後可以 <em>online 改</em>、不必停機。詳見 <a href="/blog/backend/01-database/vendors/mysql/innodb-tuning/" data-link-title="MySQL InnoDB Tuning：為什麼一個 100 GB DB 在 64 GB RAM server 上 query 慢 5 倍" data-link-desc="InnoDB 是 MySQL 預設 storage engine、預設值給 256 MB buffer pool（早期 default）。本文從一個常見痛點開場（DB &gt; RAM 但 server 仍 swap）、走 4 個 critical knob（buffer pool / redo log / flush method / IO capacity）、各自如何影響讀寫吞吐、配置 step-by-step、5 production 踩雷（buffer pool warm-up / log file 大小 / 設 sync_binlog=0 換速度 / IO scheduler / undo log 膨脹）、跟 SSD / NVMe / EBS 的 IO 假設">InnoDB Tuning</a>。</p>
<h3 id="跟-modern-sql-features">跟 Modern SQL Features</h3>
<p>8.0 補 CTE / window / JSON_TABLE / hash join — 是 <em>為什麼要升 8.0</em> 的 driver。詳見 <a href="/blog/backend/01-database/vendors/mysql/modern-sql-features/" data-link-title="MySQL 8.0 Modern SQL：CTE / window function / JSON_TABLE 不是「終於跟上 PG」、是進入 SQL 工程深度的入場券" data-link-desc="MySQL 8.0 在 SQL 特性上 *終於補齊* CTE、window function、lateral derived table、JSON_TABLE、hash join 等現代 SQL 特性。本文走 5 個關鍵特性、各自實際 production 場景、跟 PostgreSQL 對應特性的行為差異（特別是 JSON_TABLE vs PG JSONB / jsonb_path_query）、配置 / migration 注意事項、5 production 踩雷（CTE 不 materialize / window function 大量 sort spill / JSON_TABLE 跟 generated column 取捨 / hash join 預設沒開 / recursive CTE 深度上限）">Modern SQL Features</a>。</p>
<h3 id="跟-group-replication">跟 Group Replication</h3>
<p>GR 在 5.7 有、但 8.0 才成熟。Group Replication 的 <em>MySQL Shell + Router</em> 整套 stack 主要在 8.0 才完整。詳見 <a href="/blog/backend/01-database/vendors/mysql/group-replication/" data-link-title="MySQL Group Replication / InnoDB Cluster：single-primary vs multi-primary mode 對 transaction certification 的影響" data-link-desc="MySQL Group Replication 提供 synchronous multi-primary replication、用 Paxos-like Group Communication Engine（GCE）達成 quorum-based commit。但「multi-primary」不是「single-primary 多開幾個 write 入口」、是 *transaction conflict detection &#43; certification* 整個機制不同。本文走 GR 機制（GCE &#43; certification &#43; applier）、single-primary vs multi-primary mode、InnoDB Cluster 跟 MySQL Shell / Router 整合、5 production 踩雷（cert lag / write conflict / large transaction / network partition / member 加入 catch-up）、何時用 GR 何時用傳統 replication">Group Replication</a>。</p>
<h3 id="跟-aurora--planetscale-等-managed">跟 Aurora / PlanetScale 等 managed</h3>
<p>從 5.7 升 8.0 是個好時機 <em>同時評估</em> 是否要遷 Aurora / PlanetScale — 既然要做 paradigm shift、不如一次到位。詳見 <a href="/blog/backend/01-database/vendors/mysql/migrate-to-aurora/" data-link-title="MySQL → Aurora MySQL：storage layer 轉手到 AWS、replication / HA / backup 全部 outsource" data-link-desc="自管 MySQL → Aurora MySQL 是 Type C operational hybrid migration — wire protocol 一致、ops 責任轉到 AWS。本文走 6 維 audit（Operational High）、Aurora storage architecture 衝擊、4-phase migration、5 production 踩雷、何時維持原路線。">migrate-to-aurora</a> / <a href="/blog/backend/01-database/vendors/mysql/migrate-to-planetscale/" data-link-title="MySQL → PlanetScale：managed Vitess &#43; branch-based schema workflow 的 hybrid shift" data-link-desc="自管 MySQL → PlanetScale 加上 Vitess sharding 跟 branch-based schema workflow。本文走 6 維 audit（Paradigm &#43; Operational &#43; Schema 多軸）、4-phase migration、5 production 踩雷、何時不要遷。">migrate-to-planetscale</a>。</p>
<h2 id="相關連結">相關連結</h2>
<ul>
<li><a href="/blog/backend/01-database/vendors/mysql/" data-link-title="MySQL" data-link-desc="高併發網路服務常用關聯式資料庫、Vitess / PlanetScale 分片生態、GitHub / Shopify / Facebook 規模驗證">MySQL vendor overview</a></li>
<li><a href="/blog/backend/01-database/vendors/mysql/replication-topology/" data-link-title="MySQL Replication Topology：async / semi-sync / GTID 不是三選一、是三個 trade-off 軸的疊加" data-link-desc="MySQL replication 不是「選 async 還是 semi-sync」、是 *durability / latency / consistency* 三個 trade-off 軸的疊加；GTID 是跨 mode 的 infrastructure layer、不是第三種 mode。本文走 3 軸取捨模型 → async / semi-sync 行為對比 → GTID 替代 binlog-position 的好處 → 配置 step-by-step → 5 production 踩雷（lag 暴衝 / semi-sync 退回 async / GTID gap / Loss-Less semi-sync 真的 loss-less / chained replication 雪崩）→ 跟 Aurora MySQL / Vitess / ProxySQL / Orchestrator 整合">MySQL Replication Topology</a>（升級順序 replica-first）</li>
<li><a href="/blog/backend/01-database/vendors/mysql/modern-sql-features/" data-link-title="MySQL 8.0 Modern SQL：CTE / window function / JSON_TABLE 不是「終於跟上 PG」、是進入 SQL 工程深度的入場券" data-link-desc="MySQL 8.0 在 SQL 特性上 *終於補齊* CTE、window function、lateral derived table、JSON_TABLE、hash join 等現代 SQL 特性。本文走 5 個關鍵特性、各自實際 production 場景、跟 PostgreSQL 對應特性的行為差異（特別是 JSON_TABLE vs PG JSONB / jsonb_path_query）、配置 / migration 注意事項、5 production 踩雷（CTE 不 materialize / window function 大量 sort spill / JSON_TABLE 跟 generated column 取捨 / hash join 預設沒開 / recursive CTE 深度上限）">MySQL Modern SQL Features</a>（升 8.0 的主要 driver）</li>
<li><a href="/blog/backend/01-database/vendors/mysql/group-replication/" data-link-title="MySQL Group Replication / InnoDB Cluster：single-primary vs multi-primary mode 對 transaction certification 的影響" data-link-desc="MySQL Group Replication 提供 synchronous multi-primary replication、用 Paxos-like Group Communication Engine（GCE）達成 quorum-based commit。但「multi-primary」不是「single-primary 多開幾個 write 入口」、是 *transaction conflict detection &#43; certification* 整個機制不同。本文走 GR 機制（GCE &#43; certification &#43; applier）、single-primary vs multi-primary mode、InnoDB Cluster 跟 MySQL Shell / Router 整合、5 production 踩雷（cert lag / write conflict / large transaction / network partition / member 加入 catch-up）、何時用 GR 何時用傳統 replication">MySQL Group Replication</a>（8.0 成熟）</li>
<li><a href="/blog/backend/01-database/vendors/mysql/innodb-tuning/" data-link-title="MySQL InnoDB Tuning：為什麼一個 100 GB DB 在 64 GB RAM server 上 query 慢 5 倍" data-link-desc="InnoDB 是 MySQL 預設 storage engine、預設值給 256 MB buffer pool（早期 default）。本文從一個常見痛點開場（DB &gt; RAM 但 server 仍 swap）、走 4 個 critical knob（buffer pool / redo log / flush method / IO capacity）、各自如何影響讀寫吞吐、配置 step-by-step、5 production 踩雷（buffer pool warm-up / log file 大小 / 設 sync_binlog=0 換速度 / IO scheduler / undo log 膨脹）、跟 SSD / NVMe / EBS 的 IO 假設">MySQL InnoDB Tuning</a>（8.0 redo log 改寫）</li>
<li><a href="/blog/backend/01-database/vendors/mysql/migrate-to-aurora/" data-link-title="MySQL → Aurora MySQL：storage layer 轉手到 AWS、replication / HA / backup 全部 outsource" data-link-desc="自管 MySQL → Aurora MySQL 是 Type C operational hybrid migration — wire protocol 一致、ops 責任轉到 AWS。本文走 6 維 audit（Operational High）、Aurora storage architecture 衝擊、4-phase migration、5 production 踩雷、何時維持原路線。">migrate-to-aurora</a> / <a href="/blog/backend/01-database/vendors/mysql/migrate-to-planetscale/" data-link-title="MySQL → PlanetScale：managed Vitess &#43; branch-based schema workflow 的 hybrid shift" data-link-desc="自管 MySQL → PlanetScale 加上 Vitess sharding 跟 branch-based schema workflow。本文走 6 維 audit（Paradigm &#43; Operational &#43; Schema 多軸）、4-phase migration、5 production 踩雷、何時不要遷。">migrate-to-planetscale</a></li>
<li><a href="/blog/backend/01-database/vendors/postgresql/major-version-upgrade/" data-link-title="PostgreSQL major version upgrade (14 → 17)：為什麼這篇不套 5 type migration" data-link-desc="PostgreSQL major version upgrade 是 *5 type 漏類* 的實證 — source/target 同 vendor、5 維度都 Low 但 *upgrade-specific audit* 是核心；本文結構接近 deep article methodology 的 6-section &#43; 額外 upgrade audit 段；涵蓋 pg_upgrade / logical replication / blue-green 三方法、extension 相容性、5 production 踩雷">PostgreSQL Major Version Upgrade</a>（PG sibling）</li>
<li>方法論：<a href="/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">Migration Playbook Methodology</a>（Type E paradigm shift）</li>
<li>官方：<a href="https://dev.mysql.com/doc/refman/8.0/en/upgrading.html">MySQL 8.0 Upgrade Guide</a></li>
</ul>
]]></content:encoded></item><item><title>Cilium Tetragon</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/cilium-tetragon/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/cilium-tetragon/</guid><description>&lt;p>Tetragon 是 Cilium 旗下的 &lt;em>eBPF-based runtime security + enforcement&lt;/em> 元件、Isovalent 主導、2024 年起在 CNCF 屬 Incubating 階段。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/falco/" data-link-title="Falco" data-link-desc="CNCF Graduated runtime cloud-native threat detection、eBPF / kmod driver、Rule YAML &amp;#43; Falcosidekick &amp;#43; Talon、K8s container runtime 偵測為主">Falco&lt;/a> 的核心差異在於 &lt;em>偵測 vs 偵測 + 可 enforce&lt;/em> — Falco 預設 alert-only、Tetragon 設計支援 &lt;em>kernel-level inline enforcement&lt;/em>（直接 kill process、override syscall return value）；對 K8s heavy + 已用 Cilium CNI 的環境、Tetragon 把 &lt;em>network policy + process policy&lt;/em> 收進同一個 eBPF 生態。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Tetragon 的核心定位是 &lt;em>eBPF 為基底的 runtime observability + enforcement&lt;/em>、TracingPolicy CRD 是 first-class concept — 一份 YAML 同時描述 &lt;em>要觀察什麼 syscall / kprobe / tracepoint&lt;/em> 跟 &lt;em>觀察到後要不要 enforce&lt;/em>。底層 hook 點包括 syscall entry/exit、kprobe（任意 kernel function）、tracepoint（穩定 kernel event）、uprobe（user-space function），enforcement action 包括 &lt;code>Sigkill&lt;/code>（kill process）、&lt;code>Override&lt;/code>（override syscall return value）、&lt;code>NotifyEnforcer&lt;/code>、&lt;code>Post&lt;/code>（送 event 出 plane）。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/falco/" data-link-title="Falco" data-link-desc="CNCF Graduated runtime cloud-native threat detection、eBPF / kmod driver、Rule YAML &amp;#43; Falcosidekick &amp;#43; Talon、K8s container runtime 偵測為主">Falco&lt;/a> 比、Falco rule 用 Sysdig filter syntax、Tetragon 用 K8s CRD + JSON schema、對 K8s native 模型更貼近；Falco 主走 &lt;em>alert&lt;/em>、Tetragon 主走 &lt;em>alert + enforce&lt;/em>；Falco 對非 K8s VM-heavy 場景更 mature。跟 &lt;em>Datadog Cloud Workload Security&lt;/em> 比、Datadog 是 SaaS-only + per-host 計費、Tetragon 是 OSS Apache 2.0 + 自管 + Isovalent Enterprise 付費版可選。跟 &lt;em>Prisma Cloud Defender&lt;/em> 比、Prisma 是 CSPM/CWPP 一體化平台、Tetragon 專注 runtime + 跟 Cilium L3-L7 network policy 同 plane。&lt;/p>
&lt;p>關鍵張力：&lt;em>eBPF inline enforcement 的爆炸半徑&lt;/em> ↔ &lt;em>偵測即時性&lt;/em>。在 kernel-level 直接 kill process 比 userspace agent 更難 bypass、但 TracingPolicy 寫錯（match 太寬）可能誤殺合法 workload、且回退路徑只能改 CRD 再 reload。要看清楚自己 &lt;em>能不能承擔 enforcement 規則錯誤的 blast radius&lt;/em>、再決定哪些 policy 進 enforce、哪些只 observe。&lt;/p></description><content:encoded><![CDATA[<p>Tetragon 是 Cilium 旗下的 <em>eBPF-based runtime security + enforcement</em> 元件、Isovalent 主導、2024 年起在 CNCF 屬 Incubating 階段。跟 <a href="/blog/backend/07-security-data-protection/vendors/falco/" data-link-title="Falco" data-link-desc="CNCF Graduated runtime cloud-native threat detection、eBPF / kmod driver、Rule YAML &#43; Falcosidekick &#43; Talon、K8s container runtime 偵測為主">Falco</a> 的核心差異在於 <em>偵測 vs 偵測 + 可 enforce</em> — Falco 預設 alert-only、Tetragon 設計支援 <em>kernel-level inline enforcement</em>（直接 kill process、override syscall return value）；對 K8s heavy + 已用 Cilium CNI 的環境、Tetragon 把 <em>network policy + process policy</em> 收進同一個 eBPF 生態。</p>
<h2 id="服務定位">服務定位</h2>
<p>Tetragon 的核心定位是 <em>eBPF 為基底的 runtime observability + enforcement</em>、TracingPolicy CRD 是 first-class concept — 一份 YAML 同時描述 <em>要觀察什麼 syscall / kprobe / tracepoint</em> 跟 <em>觀察到後要不要 enforce</em>。底層 hook 點包括 syscall entry/exit、kprobe（任意 kernel function）、tracepoint（穩定 kernel event）、uprobe（user-space function），enforcement action 包括 <code>Sigkill</code>（kill process）、<code>Override</code>（override syscall return value）、<code>NotifyEnforcer</code>、<code>Post</code>（送 event 出 plane）。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/falco/" data-link-title="Falco" data-link-desc="CNCF Graduated runtime cloud-native threat detection、eBPF / kmod driver、Rule YAML &#43; Falcosidekick &#43; Talon、K8s container runtime 偵測為主">Falco</a> 比、Falco rule 用 Sysdig filter syntax、Tetragon 用 K8s CRD + JSON schema、對 K8s native 模型更貼近；Falco 主走 <em>alert</em>、Tetragon 主走 <em>alert + enforce</em>；Falco 對非 K8s VM-heavy 場景更 mature。跟 <em>Datadog Cloud Workload Security</em> 比、Datadog 是 SaaS-only + per-host 計費、Tetragon 是 OSS Apache 2.0 + 自管 + Isovalent Enterprise 付費版可選。跟 <em>Prisma Cloud Defender</em> 比、Prisma 是 CSPM/CWPP 一體化平台、Tetragon 專注 runtime + 跟 Cilium L3-L7 network policy 同 plane。</p>
<p>關鍵張力：<em>eBPF inline enforcement 的爆炸半徑</em> ↔ <em>偵測即時性</em>。在 kernel-level 直接 kill process 比 userspace agent 更難 bypass、但 TracingPolicy 寫錯（match 太寬）可能誤殺合法 workload、且回退路徑只能改 CRD 再 reload。要看清楚自己 <em>能不能承擔 enforcement 規則錯誤的 blast radius</em>、再決定哪些 policy 進 enforce、哪些只 observe。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>Tetragon 在 K8s runtime stack 中承擔哪一段（process visibility / file access / network syscall / enforcement）、哪些要外接（<a href="/blog/backend/07-security-data-protection/vendors/falco/" data-link-title="Falco" data-link-desc="CNCF Graduated runtime cloud-native threat detection、eBPF / kmod driver、Rule YAML &#43; Falcosidekick &#43; Talon、K8s container runtime 偵測為主">Falco</a> for VM-heavy、SIEM for log aggregation）</li>
<li>TracingPolicy 的 ownership 設計（誰寫 CRD、enforcement action 誰簽核、staging vs production rollout）</li>
<li><em>Observe</em> vs <em>Enforce</em> 的階段化決策、什麼樣的 policy 適合 inline kill、什麼樣的應該停在 alert</li>
<li>何時用 Tetragon、何時走 Falco / Datadog CWS / Prisma Defender 的取捨</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Tetragon deployment 是否健康、最少看四件事：</p>
<ul>
<li><strong>TracingPolicy 治理</strong>：CRD 是否走 Git + PR review、enforcement action（Sigkill / Override）是否需額外簽核、staging cluster 是否先跑 24-48hr 觀察 false positive 才 promote production</li>
<li><strong>跟 Cilium 整合深度</strong>：Hubble flow + Tetragon process event 是否同 plane export、Pod identity 是否在 process event 自動 enrich、跟 Cilium NetworkPolicy 是否雙層 enforcement 設計</li>
<li><strong>Enforcement coverage 分層</strong>：哪些 policy 處於 observe-only（log JNDI lookup / setuid abuse / unexpected outbound）、哪些升到 enforce（kill known exploit pattern）、升級條件是什麼</li>
<li><strong>Event export pipeline</strong>：Tetragon event 是否進 SIEM（OpenTelemetry / JSON log → Splunk / Elastic）、是否跟 <a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">Detection Coverage and Signal Governance</a> 邊界一致</li>
</ul>
<p>四件事任一缺失、就是 runtime security 邊界的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>TracingPolicy CRD</strong>：Tetragon 的 first-class concept、一份 YAML 描述 hook 點 + match selector + enforcement action。Hook 點包含 <em>syscall</em>（最穩定但 surface 廣）、<em>kprobe</em>（任意 kernel function、版本相依）、<em>tracepoint</em>（穩定 kernel event、首選）、<em>uprobe</em>（user-space function、低層用）。Match selector 支援 K8s namespace / pod label / container image、process credentials（UID / GID / capabilities）、parent process。Production rule 用 <em>pod label selector + 具體 syscall name + 額外 process credentials 條件</em>、避免 cluster-wide 寬鬆 match 誤殺。</p>
<p><strong>kprobe / tracepoint / syscall hook 的選擇</strong>：tracepoint 是 kernel 公開穩定介面、跨版本不變、首選；kprobe 可 hook 任意 kernel function 但跟 kernel build 緊綁、kernel upgrade 後可能要重寫；raw syscall 適合 audit 整類 syscall（如全部 <code>execve</code>）但量大、需要 in-kernel filter 控成本。</p>
<p><strong>Process credentials tracking</strong>：Tetragon 從 process exec 開始 track UID / GID / capabilities / namespace、偵測 <em>privilege escalation</em>（setuid abuse、capabilities drift、container escape）是 first-class use case。跟 audit log 比、credentials drift 是 <em>狀態變遷</em>、不是單一事件、更能 surface lateral movement 早期訊號（process 開始時 UID 1000、跑到一半變 0 是異常）。</p>
<p><strong>Pod identity correlation</strong>：Tetragon 在 K8s 環境會自動把 process event enrich K8s metadata（namespace / pod name / container image / service account）、不用後處理 join；event schema 跟 Hubble flow 同根、可在 Hubble UI 看 <em>某 Pod 的 network flow + process event</em> 同 timeline。</p>
<p><strong>跟 Cilium NetworkPolicy 雙層 enforcement</strong>：Cilium 控 <em>network ingress / egress / L7 HTTP</em>、Tetragon 控 <em>process / syscall / file access</em>。雙層設計的意義是 — network layer 擋不住的（如 process 內部 lateral movement、container escape syscall）由 process layer 補上；process layer 漏的（如合法 process 突然 outbound 異常 destination）由 network layer 補上。對 supply chain 攻擊特別有效、攻擊鏈通常跨 <em>malicious process spawn + outbound C2</em>。</p>
<p><strong>Event export 跟 SIEM 整合</strong>：Tetragon event 預設走 JSON log 到 stdout、可走 OpenTelemetry exporter 進 collector pipeline、再 fanout 到 <a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / <a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-security-operations/" data-link-title="Google Security Operations" data-link-desc="Google 雲原生 SIEM &#43; SOAR &#43; Mandiant threat intel 三合一（前 Chronicle）、UDM &#43; YARA-L、fixed-price by data tier、PB-scale 友善">Google Security Operations</a>。在 SIEM 端做跨來源 correlation（process event + IdP audit + cloud control plane）是 production 標配、不可只看 Tetragon 自家視圖。</p>
<p><strong>Observe → Enforce 階段化</strong>：TracingPolicy 通常 <em>先進 observe-only</em>、跑 1-2 週收 baseline、確認 false positive 可控、再加 enforcement action 進 staging cluster、staging 觀察 24-48hr 才 promote production。對應 <a href="/blog/backend/07-security-data-protection/blue-team/detection-engineering-lifecycle/" data-link-title="7.B5 Detection Engineering Lifecycle" data-link-desc="把偵測規則視為可維護資產，建立從來源、測試、調校到退場的完整生命週期">Detection Engineering Lifecycle</a> 的章節原則 — runtime enforcement 不是 console 直改、是 detection content lifecycle。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Cilium Tetragon</th>
          <th>Falco</th>
          <th>Datadog CWS</th>
          <th>Prisma Cloud Defender</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>偵測技術</td>
          <td>eBPF（kprobe / tracepoint / syscall / uprobe）</td>
          <td>eBPF + kernel module 兩種 driver</td>
          <td>eBPF agent</td>
          <td>eBPF + kernel module</td>
      </tr>
      <tr>
          <td>Enforcement</td>
          <td>內建（Sigkill / Override syscall return）</td>
          <td>預設 alert-only（plugin 可擴 response）</td>
          <td>自動 response（kill / isolate、SaaS 控）</td>
          <td>內建（block process / file / network）</td>
      </tr>
      <tr>
          <td>規則語言</td>
          <td>K8s CRD（TracingPolicy YAML）</td>
          <td>Sysdig filter syntax（YAML rule）</td>
          <td>Datadog Security Rules（JSON / UI）</td>
          <td>Prisma Runtime Rules（UI / JSON）</td>
      </tr>
      <tr>
          <td>計費 / 授權</td>
          <td>OSS Apache 2.0、Isovalent Enterprise 付費</td>
          <td>OSS Apache 2.0、Sysdig Secure 付費</td>
          <td>SaaS per-host</td>
          <td>商業 per-defender</td>
      </tr>
      <tr>
          <td>K8s native</td>
          <td>強 — Pod identity 自動 enrich、跟 Cilium 同源</td>
          <td>中 — K8s metadata 需 audit endpoint</td>
          <td>強 — Datadog Agent 已熟</td>
          <td>強 — Prisma 平台一體</td>
      </tr>
      <tr>
          <td>Network policy</td>
          <td>跟 Cilium L3-L7 雙層（同 plane）</td>
          <td>無 — 純 process / file</td>
          <td>無 — 跟 Datadog Network 分離</td>
          <td>內建 micro-segmentation</td>
      </tr>
      <tr>
          <td>VM / 非 K8s</td>
          <td>弱 — Linux only、K8s-first</td>
          <td>強 — VM / bare metal mature</td>
          <td>中 — 跨環境同 agent</td>
          <td>強 — VM / serverless / container 全覆蓋</td>
      </tr>
      <tr>
          <td>部署模型</td>
          <td>Self-hosted DaemonSet（K8s）</td>
          <td>Self-hosted DaemonSet / VM agent</td>
          <td>SaaS</td>
          <td>商業 self-hosted + SaaS console</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>K8s heavy + 已用 Cilium + 要 inline enforce</td>
          <td>VM-heavy / K8s 混合、需要 mature alert ecosystem</td>
          <td>Datadog 已用、要 unified observability</td>
          <td>多雲 CSPM/CWPP 一體化、合規驅動</td>
      </tr>
      <tr>
          <td>退場成本</td>
          <td>中 — TracingPolicy CRD 跨 cluster 可移植</td>
          <td>中 — Falco rule 跟 Sigma 可互轉</td>
          <td>高 — SaaS lock-in</td>
          <td>高 — 商業平台 lock-in</td>
      </tr>
  </tbody>
</table>
<p>選 Tetragon 的核心訴求：<em>K8s heavy + 已用 Cilium CNI + 想要 kernel-level inline enforcement + OSS 免授權成本</em>、且有 SRE / security team 能維護 TracingPolicy CRD lifecycle。VM-heavy 或 K8s 但用其他 CNI 走 Falco 更划算。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Inline enforcement 的 blast radius 設計</strong>：<code>Sigkill</code> 直接 kill 觸發 process、<code>Override</code> 改寫 syscall return value（讓 process 以為成功但實際沒做）— 兩者都在 kernel-level、攻擊者很難 bypass、但寫錯規則的 blast radius 是 <em>整個 cluster 內 match 到的 process 全死</em>。實務治理：enforcement action 規則進 GitOps、PR 需 security + SRE 雙簽、staging cluster 跑 namespace-scoped 規則先驗證、production rollout 走 canary namespace 再擴散。</p>
<p><strong>Process credentials drift detection</strong>：track UID / GID / capabilities 變遷、偵測 setuid abuse（process 從 uid 1000 變 0）、capabilities 突然新增（特別是 CAP_SYS_ADMIN / CAP_NET_ADMIN）。對 lateral movement 早期警報是 first-class signal — 攻擊者拿到初始 access 後通常要 escalate privilege、credentials drift 是必經訊號。配對 <a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/solarwinds-2020-sunburst/" data-link-title="7.R7.2.1 SolarWinds 2020：更新鏈被濫用" data-link-desc="合法更新流程遭植入後，攻擊者如何長期潛伏與橫向擴散">SolarWinds 2020 Sunburst</a> 的 lesson：簽章驗證通過但 runtime 行為異常需 <em>runtime credentials + process behavior</em> 雙重 baseline。</p>
<p><strong>跟 Cilium L3-L7 雙層 enforcement</strong>：典型 supply chain 攻擊鏈 — <em>malicious dependency loaded → process spawn → C2 outbound</em>、network layer 擋 outbound（Cilium NetworkPolicy 限制 egress destination）、process layer 擋 process（Tetragon KillerAction kill 異常 spawn）。雙層任一通則攻擊鏈中斷。對應 <a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/3cx-2023-desktopapp-supply-chain/" data-link-title="7.R7.2.8 3CX 2023：桌面軟體更新鏈攻擊" data-link-desc="合法更新流程被植入後，桌面端供應鏈事件如何傳到企業端點">3CX 2023 Desktop App Supply Chain</a> 的 case shape。</p>
<p><strong>跟 SBOM / image signing 整合 baseline</strong>：Tetragon 偵測 runtime 行為偏離 baseline、SBOM / image signing 控 build-time 信任、合在一起是 <em>trusted artifact + verified runtime behavior</em> 雙重保障。runtime 行為 baseline 通常從 SBOM 列出的合法 process / syscall set 出發、deviation 進 alert。</p>
<p><strong>Isovalent Enterprise</strong>：商業版加值在 multi-cluster management、policy 集中下發、support SLA、跟 Isovalent Hubble Enterprise / Cilium Service Mesh Enterprise 整合。OSS 版本核心功能完整、Enterprise 主要解 <em>多 cluster 大規模管理</em> 跟 <em>企業 support</em>、不是 feature gating。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>TracingPolicy 誤殺合法 workload</strong>：match selector 太寬、cluster-wide 沒加 namespace / pod label 條件 — 改 namespace-scoped + 加 process credentials 額外條件、staging 跑 48hr 再 promote</li>
<li><strong>kprobe rule kernel upgrade 後壞</strong>：hook 的 kernel function 改名或 signature 變 — 改用 tracepoint（穩定介面）、kprobe 進 staging 版本相依測試</li>
<li><strong>Event volume 爆炸 / SIEM ingestion cost 飆</strong>：raw syscall hook 沒做 in-kernel filter、所有 <code>execve</code> 都進 event — 加 in-kernel filter（按 pod label / process name），讓 filter 在 eBPF 端做、不要事後 drop</li>
<li><strong>Inline enforcement 規則錯誤 blast radius 太大</strong>：production 直接上 <code>Sigkill</code> 沒走 staging — enforcement action 規則一律先 observe-only 1 週、staging cluster 24-48hr、canary namespace、才 production</li>
<li><strong>跟 Cilium NetworkPolicy 重疊或衝突</strong>：同一個 attack pattern 被 network + process 同時阻擋、log 重複、誤判 — 設計時雙層各管 <em>互補面</em>（network 管 destination、process 管 process spawn）、不重複管同一面</li>
<li><strong>non-K8s workload 進不來</strong>：Tetragon DaemonSet 只在 K8s 跑、VM / bare metal 不支援 — VM-heavy 環境改走 <a href="/blog/backend/07-security-data-protection/vendors/falco/" data-link-title="Falco" data-link-desc="CNCF Graduated runtime cloud-native threat detection、eBPF / kmod driver、Rule YAML &#43; Falcosidekick &#43; Talon、K8s container runtime 偵測為主">Falco</a>、K8s + VM 混合走雙 stack</li>
<li><strong>Pod identity enrich 不全</strong>：某些 process event 缺 namespace / pod name — 通常是 process 在 pod sandbox 啟動前 spawn、或 short-lived process 太快結束、調 Tetragon 的 process cache lifetime + K8s API server 連線健康</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>VM-heavy / 非 K8s 為主</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/falco/" data-link-title="Falco" data-link-desc="CNCF Graduated runtime cloud-native threat detection、eBPF / kmod driver、Rule YAML &#43; Falcosidekick &#43; Talon、K8s container runtime 偵測為主">Falco</a></td>
      </tr>
      <tr>
          <td>Datadog observability 已用</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &#43; CSPM &#43; CWS &#43; AAP &#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Security</a>（Cloud Workload Security）</td>
      </tr>
      <tr>
          <td>多雲 CSPM/CWPP 一體化、合規驅動</td>
          <td>Prisma Cloud Defender（商業）</td>
      </tr>
      <tr>
          <td>SIEM 偵測為主、不需 inline kill</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / <a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a></td>
      </tr>
      <tr>
          <td>Endpoint EDR（user laptop / VDI）</td>
          <td>CrowdStrike Falcon / Microsoft Defender for Endpoint</td>
      </tr>
      <tr>
          <td>偵測覆蓋率治理</td>
          <td><a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">7.13 偵測覆蓋率與訊號治理</a></td>
      </tr>
      <tr>
          <td>Incident routing</td>
          <td><a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>TracingPolicy CRD 完整欄位 reference 跟 kprobe / tracepoint 寫法 cookbook</li>
<li>Cilium NetworkPolicy 寫法（屬 network 治理、跨章節）</li>
<li>eBPF kernel programming 內部原理跟 verifier 限制</li>
<li>Isovalent Enterprise 跟 Cilium Service Mesh 商業整合細節</li>
<li>Hubble UI 操作（屬 observability 視角、跨章節）</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>Tetragon 在 07 案例庫沒有直接 vendor-level 事件、但所有 runtime detection + supply chain case 都是 eBPF inline enforcement 的對照：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 Tetragon 的關係（對照啟示）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/log4shell-cve-2021-44228-component-chain/" data-link-title="7.R7.2.7 Log4Shell 2021：共用元件風險與修補鏈" data-link-desc="共用元件漏洞如何同步影響多服務，並迫使團隊建立依賴治理 workflow">Log4Shell CVE-2021-44228</a></td>
          <td>TracingPolicy 可 hook JNDI lookup 相關 syscall、配 <code>Sigkill</code> 直接 kill exploit process、比 userspace WAF 更難 bypass</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/solarwinds-2020-sunburst/" data-link-title="7.R7.2.1 SolarWinds 2020：更新鏈被濫用" data-link-desc="合法更新流程遭植入後，攻擊者如何長期潛伏與橫向擴散">SolarWinds 2020 Sunburst</a></td>
          <td>process credentials drift detection 對 lateral movement 早期警報、簽章驗證通過但 runtime 行為異常需 runtime baseline 補位</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/3cx-2023-desktopapp-supply-chain/" data-link-title="7.R7.2.8 3CX 2023：桌面軟體更新鏈攻擊" data-link-desc="合法更新流程被植入後，桌面端供應鏈事件如何傳到企業端點">3CX 2023 Desktop App Supply Chain</a></td>
          <td>偵測 desktop app 異常 outbound、Tetragon 抓 process + Cilium NetworkPolicy 同層擋 destination、雙層 enforcement 中斷攻擊鏈</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/blue-team/detection-engineering-lifecycle/" data-link-title="7.B5 Detection Engineering Lifecycle" data-link-desc="把偵測規則視為可維護資產，建立從來源、測試、調校到退場的完整生命週期">Detection Engineering Lifecycle (section)</a></td>
          <td>TracingPolicy CRD 走 GitOps + PR review + staging tune + canary rollout、inline enforcement 不可 console 直改</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/blue-team/alert-fatigue-and-signal-quality/" data-link-title="7.B10 Alert Fatigue and Signal Quality" data-link-desc="建立告警疲勞治理方法，讓訊號品質、分級一致性與處置效率同步提升">Alert Fatigue and Signal Quality (section)</a></td>
          <td>observe-only 階段先收 baseline、in-kernel filter 控 event volume、enforcement 只升給高 confidence pattern、避免 alert / log 雙重 fatigue</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">7.13 偵測覆蓋率與訊號治理</a>、<a href="/blog/backend/07-security-data-protection/blue-team/detection-engineering-lifecycle/" data-link-title="7.B5 Detection Engineering Lifecycle" data-link-desc="把偵測規則視為可維護資產，建立從來源、測試、調校到退場的完整生命週期">Detection Engineering Lifecycle</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/falco/" data-link-title="Falco" data-link-desc="CNCF Graduated runtime cloud-native threat detection、eBPF / kmod driver、Rule YAML &#43; Falcosidekick &#43; Talon、K8s container runtime 偵測為主">Falco</a>、<a href="/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &#43; CSPM &#43; CWS &#43; AAP &#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Security</a></li>
<li>下游：<a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / <a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a>（Tetragon event 進 SIEM 做跨來源 correlation）</li>
<li>跨類：<a href="/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &#43; DDoS &#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF</a>（network edge 擋 + process 層補位）、<a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a>（credentials drift 配 secret rotation）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（runtime alert → IR routing）、<a href="/blog/backend/04-observability/" data-link-title="模組四：可觀測性平台" data-link-desc="整理 log、metric、trace、dashboard 與 alert 的後端操作實務">4 observability</a>（Hubble + Tetragon event pipeline 共用）</li>
<li>官方：<a href="https://tetragon.io/">Tetragon Documentation</a>、<a href="https://cilium.io/">Cilium Project</a></li>
</ul>
]]></content:encoded></item><item><title>MySQL → Aurora MySQL：storage layer 轉手到 AWS、replication / HA / backup 全部 outsource</title><link>https://tarrragon.github.io/blog/backend/01-database/vendors/mysql/migrate-to-aurora/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/01-database/vendors/mysql/migrate-to-aurora/</guid><description>&lt;blockquote>
&lt;p>本文是跨 vendor &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/migration/" data-link-title="Migration" data-link-desc="說明系統如何把資料、流量或結構從舊狀態移到新狀態">migration&lt;/a> playbook、cross-link 到 &lt;a href="https://tarrragon.github.io/blog/backend/01-database/vendors/mysql/" data-link-title="MySQL" data-link-desc="高併發網路服務常用關聯式資料庫、Vitess / PlanetScale 分片生態、GitHub / Shopify / Facebook 規模驗證">MySQL&lt;/a> 跟 &lt;a href="https://tarrragon.github.io/blog/backend/01-database/vendors/aurora/" data-link-title="AWS Aurora" data-link-desc="AWS managed PostgreSQL / MySQL、storage / compute 分離、&amp;#43;75% 效能改善的 production 證據">Aurora&lt;/a>。走 &lt;a href="https://tarrragon.github.io/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">Migration playbook methodology&lt;/a> Type C operational hybrid 結構。每階段切換用 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/migration-gate/" data-link-title="Migration Gate" data-link-desc="說明遷移流程何時可以進入下一階段或正式切換">migration gate&lt;/a> 把關。&lt;/p>&lt;/blockquote>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Ops 責任&lt;/th>
 &lt;th>自管 MySQL&lt;/th>
 &lt;th>Aurora MySQL&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Storage&lt;/td>
 &lt;td>EBS / local SSD、自己選 + 監控&lt;/td>
 &lt;td>Aurora distributed storage（自動 6 份跨 3 AZ）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Replication setup&lt;/td>
 &lt;td>binlog + semi-sync 自己配&lt;/td>
 &lt;td>Storage layer 自動、無 binlog replication&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Failover&lt;/td>
 &lt;td>Orchestrator + VIP + fence script&lt;/td>
 &lt;td>Aurora 內建、&amp;lt; 30 秒 RTO&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Backup&lt;/td>
 &lt;td>mysqldump / Percona XtraBackup&lt;/td>
 &lt;td>自動 continuous backup、PITR&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Parameter tuning&lt;/td>
 &lt;td>my.cnf 自己改&lt;/td>
 &lt;td>Parameter group（部分 knob 鎖）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Connection limit&lt;/td>
 &lt;td>max_connections 自己設&lt;/td>
 &lt;td>看 instance class、有上限&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Auto scaling&lt;/td>
 &lt;td>不適用&lt;/td>
 &lt;td>Aurora Serverless v2 + read replica auto-scaling&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Multi-region&lt;/td>
 &lt;td>自己配 chained replication&lt;/td>
 &lt;td>Aurora Global Database&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Per-month cost&lt;/td>
 &lt;td>EC2 + EBS + 自己管 ops&lt;/td>
 &lt;td>Higher per-GB / per-IOPS、但 ops headcount saving&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>從 &lt;em>MySQL 角度&lt;/em> 看 Aurora MySQL：wire protocol 一致、SQL 一致、ORM 不必改、application 連 endpoint 字串以外幾乎不必動。從 &lt;em>Ops 角度&lt;/em> 看 Aurora MySQL：所有 storage / replication / failover knob 都 &lt;em>看不到也改不了&lt;/em>、整個 ops 心智模型重寫。&lt;/p>
&lt;p>這是 Type C operational hybrid 的典型 signature — &lt;em>schema / paradigm 接近、operational 完全不同&lt;/em>。&lt;/p></description><content:encoded><![CDATA[<blockquote>
<p>本文是跨 vendor <a href="/blog/backend/knowledge-cards/migration/" data-link-title="Migration" data-link-desc="說明系統如何把資料、流量或結構從舊狀態移到新狀態">migration</a> playbook、cross-link 到 <a href="/blog/backend/01-database/vendors/mysql/" data-link-title="MySQL" data-link-desc="高併發網路服務常用關聯式資料庫、Vitess / PlanetScale 分片生態、GitHub / Shopify / Facebook 規模驗證">MySQL</a> 跟 <a href="/blog/backend/01-database/vendors/aurora/" data-link-title="AWS Aurora" data-link-desc="AWS managed PostgreSQL / MySQL、storage / compute 分離、&#43;75% 效能改善的 production 證據">Aurora</a>。走 <a href="/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">Migration playbook methodology</a> Type C operational hybrid 結構。每階段切換用 <a href="/blog/backend/knowledge-cards/migration-gate/" data-link-title="Migration Gate" data-link-desc="說明遷移流程何時可以進入下一階段或正式切換">migration gate</a> 把關。</p></blockquote>
<table>
  <thead>
      <tr>
          <th>Ops 責任</th>
          <th>自管 MySQL</th>
          <th>Aurora MySQL</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Storage</td>
          <td>EBS / local SSD、自己選 + 監控</td>
          <td>Aurora distributed storage（自動 6 份跨 3 AZ）</td>
      </tr>
      <tr>
          <td>Replication setup</td>
          <td>binlog + semi-sync 自己配</td>
          <td>Storage layer 自動、無 binlog replication</td>
      </tr>
      <tr>
          <td>Failover</td>
          <td>Orchestrator + VIP + fence script</td>
          <td>Aurora 內建、&lt; 30 秒 RTO</td>
      </tr>
      <tr>
          <td>Backup</td>
          <td>mysqldump / Percona XtraBackup</td>
          <td>自動 continuous backup、PITR</td>
      </tr>
      <tr>
          <td>Parameter tuning</td>
          <td>my.cnf 自己改</td>
          <td>Parameter group（部分 knob 鎖）</td>
      </tr>
      <tr>
          <td>Connection limit</td>
          <td>max_connections 自己設</td>
          <td>看 instance class、有上限</td>
      </tr>
      <tr>
          <td>Auto scaling</td>
          <td>不適用</td>
          <td>Aurora Serverless v2 + read replica auto-scaling</td>
      </tr>
      <tr>
          <td>Multi-region</td>
          <td>自己配 chained replication</td>
          <td>Aurora Global Database</td>
      </tr>
      <tr>
          <td>Per-month cost</td>
          <td>EC2 + EBS + 自己管 ops</td>
          <td>Higher per-GB / per-IOPS、但 ops headcount saving</td>
      </tr>
  </tbody>
</table>
<p>從 <em>MySQL 角度</em> 看 Aurora MySQL：wire protocol 一致、SQL 一致、ORM 不必改、application 連 endpoint 字串以外幾乎不必動。從 <em>Ops 角度</em> 看 Aurora MySQL：所有 storage / replication / failover knob 都 <em>看不到也改不了</em>、整個 ops 心智模型重寫。</p>
<p>這是 Type C operational hybrid 的典型 signature — <em>schema / paradigm 接近、operational 完全不同</em>。</p>
<h2 id="為什麼是-type-coperational-為主">為什麼是 Type C（operational 為主）</h2>
<p>跑 <a href="/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/#%e5%af%ab%e5%89%8d%e7%9a%84-diff-dimension-audit" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">6 維 diff dimension audit</a>：</p>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>評</th>
          <th>說明</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Schema</td>
          <td>Low</td>
          <td>MySQL wire protocol + SQL 完全一致</td>
      </tr>
      <tr>
          <td>Operational</td>
          <td>High</td>
          <td>storage / replication / failover / backup ops 全部轉到 AWS</td>
      </tr>
      <tr>
          <td>Paradigm</td>
          <td>Low</td>
          <td>同 OLTP relational paradigm</td>
      </tr>
      <tr>
          <td>Components</td>
          <td>Medium</td>
          <td>Aurora 加 storage layer / cluster endpoint / reader endpoint</td>
      </tr>
      <tr>
          <td>App change</td>
          <td>Low</td>
          <td>主要 connection string + connection pool 設定</td>
      </tr>
      <tr>
          <td>Topology</td>
          <td>Low-Medium</td>
          <td>single-region scaling、跨 region 走 Global Database</td>
      </tr>
  </tbody>
</table>
<p>Operational = High（其他 Low） → <strong>Type C operational hybrid</strong>。Migration 路徑用 <em>4-phase drop-in cutover</em> + <em>operational re-onboarding</em>。</p>
<h2 id="drivertco--multi-az-ha--aws-integration">Driver：TCO + Multi-AZ HA + AWS integration</h2>
<p>從自管 MySQL 遷到 Aurora MySQL 的核心 driver：</p>
<ul>
<li><strong>TCO</strong>：自管 MySQL 真實 cost = EC2 + EBS + ops headcount（1-3 個 FTE 撐大 MySQL deployment）。Aurora per-GB / per-IOPS 比 EC2+EBS 貴 30-50%、但省 ops headcount、總帳通常 break-even 或更便宜</li>
<li><strong>Multi-AZ HA</strong>：Aurora storage 自動 6 份跨 3 AZ、failover &lt; 30 秒、不需要自管 Orchestrator + VIP + fence script</li>
<li><strong>AWS ecosystem integration</strong>：跟 Lambda / SAM / CloudFormation / IAM / Secrets Manager 整合、給 cloud-native architecture 加分</li>
<li><strong>Read scaling</strong>：Aurora 最多 15 個 read replica、storage layer 共享（不 replicate data、僅 replicate page cache）、read latency &lt; 10ms inter-replica</li>
</ul>
<p>不適合 <em>已用 Percona Server fork</em> 或 <em>需要 cross-cloud portability</em> 的 org — Aurora MySQL 是 AWS-only、且 fork 自 MySQL 5.7/8.0、跟 Percona 特性不完全一致。</p>
<h2 id="4-phase-migration">4-phase migration</h2>
<h3 id="phase-1aurora-cluster-起來作為-read-replica">Phase 1：Aurora cluster 起來作為 read replica</h3>
<p>最低風險入口：建 Aurora cluster、用 MySQL binlog 把 production 資料 stream 進 Aurora。Application 仍寫自管 MySQL primary、Aurora 作為 <em>external read replica</em>。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># 1. 在 AWS 建 Aurora MySQL cluster</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">aws rds create-db-cluster <span class="se">\
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="se"></span>  --db-cluster-identifier prod-aurora <span class="se">\
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="se"></span>  --engine aurora-mysql <span class="se">\
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="se"></span>  --engine-version 8.0.mysql_aurora.3.04.0 <span class="se">\
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="se"></span>  --master-username admin <span class="se">\
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="se"></span>  --master-user-password ... <span class="se">\
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="se"></span>  --database-name production <span class="se">\
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="se"></span>  --vpc-security-group-ids sg-xxx <span class="se">\
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="se"></span>  --db-subnet-group-name prod-subnet
</span></span><span class="line"><span class="ln">11</span><span class="cl">
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="c1"># 2. 用 mysqldump 或 Percona XtraBackup 拿 baseline</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">mysqldump --single-transaction --master-data<span class="o">=</span><span class="m">2</span> --triggers --routines --events <span class="se">\
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="se"></span>  --all-databases &gt; baseline.sql
</span></span><span class="line"><span class="ln">15</span><span class="cl">
</span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="c1"># 3. Restore 到 Aurora</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">mysql -h prod-aurora.cluster-xxx.us-east-1.rds.amazonaws.com -u admin -p &lt; baseline.sql
</span></span><span class="line"><span class="ln">18</span><span class="cl">
</span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="c1"># 4. 設定 Aurora 從自管 MySQL 接 binlog</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">CALL mysql.rds_set_external_master<span class="o">(</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">  <span class="s1">&#39;self-managed-primary.example.com&#39;</span>, 3306,
</span></span><span class="line"><span class="ln">22</span><span class="cl">  <span class="s1">&#39;replication_user&#39;</span>, <span class="s1">&#39;password&#39;</span>,
</span></span><span class="line"><span class="ln">23</span><span class="cl">  <span class="s1">&#39;mysql-bin.000123&#39;</span>, 12345, <span class="m">0</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl"><span class="o">)</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">CALL mysql.rds_start_replication<span class="p">;</span></span></span></code></pre></div><p>完成標準：Aurora replica lag &lt; 1 秒、跟 production primary 同步。</p>
<h3 id="phase-2application-read-切到-aurora-reader-endpoint">Phase 2：Application read 切到 Aurora reader endpoint</h3>
<p>Application 仍寫自管 primary、但讀 query 切到 Aurora reader endpoint：</p>
<ul>
<li>Aurora reader endpoint：<code>prod-aurora.cluster-ro-xxx.us-east-1.rds.amazonaws.com</code></li>
<li>自動 round-robin 多個 read replica</li>
<li>ProxySQL 或 application config 改 read connection string</li>
</ul>
<p>跑 1-2 週、確認：</p>
<ul>
<li>Aurora read latency 跟自管 replica latency 接近（通常 Aurora 略好）</li>
<li>Aurora replication lag 穩定 &lt; 1 秒</li>
<li>Aurora query 結果跟自管 primary 一致（spot-check critical query）</li>
</ul>
<p>完成標準：所有 read traffic 都進 Aurora、no application bug。</p>
<h3 id="phase-3cutover--promote-aurora-primary">Phase 3：Cutover — promote Aurora primary</h3>
<p>Cutover window 內：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># 1. 停 application 寫入（feature flag / scheduled maintenance）</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="c1"># 2. 等自管 primary 跟 Aurora 同步完成（檢查 Aurora replica lag = 0）</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="c1"># 3. 把 Aurora 從 external replica 提升為獨立 primary</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">CALL mysql.rds_stop_replication<span class="p">;</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">CALL mysql.rds_reset_external_master<span class="p">;</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="c1"># 4. Application 寫 connection string 切到 Aurora writer endpoint</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="c1"># prod-aurora.cluster-xxx.us-east-1.rds.amazonaws.com</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="c1"># 5. 開始 application traffic</span></span></span></code></pre></div><p>完成標準：寫入流量 100% 進 Aurora、自管 primary 變 idle。Cutover 通常需要 30-60 分鐘 maintenance window。</p>
<h3 id="phase-4decommission-自管-mysql">Phase 4：Decommission 自管 MySQL</h3>
<p>跑 1-2 週確認 Aurora 穩定後 <em>慢慢退役自管</em>：</p>
<ul>
<li>自管 primary 保留作 <em>cold backup</em>（1-3 個月）、不接 traffic、可隨時 rollback</li>
<li>Replica 一個一個關掉</li>
<li>監控 Aurora cost vs 預估、確認 break-even</li>
</ul>
<p>完成標準：自管 EC2 instance terminate、EBS volume snapshot 後 delete、cost 對比驗證符合預期。</p>
<h2 id="5-個-production-踩雷">5 個 Production 踩雷</h2>
<h3 id="1-parameter-group-沒對齊--innodb_flush_log_at_trx_commit-等行為差">1. Parameter group 沒對齊 — <code>innodb_flush_log_at_trx_commit</code> 等行為差</h3>
<p>Aurora 的 <em>parameter group</em> 取代 my.cnf。預設 parameter group 不一定跟自管 MySQL 一致：</p>
<ul>
<li><code>innodb_flush_log_at_trx_commit</code>：自管常設 1（zero loss）、Aurora 預設仍 1 但走 <em>Aurora storage durability</em>（行為等價但不同 mechanism）</li>
<li><code>sync_binlog</code>：自管 1、Aurora <em>沒有 binlog 寫 disk</em> 概念（Aurora 不用 binlog 做 replication、binlog 是 <em>optional output</em>）</li>
<li><code>time_zone</code>：Aurora 預設 UTC、自管常設 local time、TIMESTAMP query 行為可能不同</li>
<li><code>character_set_*</code>：自管常設 utf8mb4、Aurora 預設可能是 latin1（看 cluster create 命令）</li>
</ul>
<p>修法：</p>
<ul>
<li>
<p>Phase 1 完成後 <em>逐 row 對比 parameter group</em>：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sql" data-lang="sql"><span class="line"><span class="ln">1</span><span class="cl"><span class="k">SELECT</span><span class="w"> </span><span class="o">@@</span><span class="k">global</span><span class="p">.</span><span class="n">variable_name</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="p">...</span></span></span></code></pre></div></li>
<li>
<p>建 <em>custom DB cluster parameter group</em>、匹配自管設定</p>
</li>
<li>
<p>重啟 Aurora primary 套 parameter group 改變（部分 parameter 需要重啟）</p>
</li>
</ul>
<h3 id="2-iam-authentication--application-沒準備">2. IAM authentication — application 沒準備</h3>
<p>Aurora 提供 <em>IAM authentication</em>（不用 password、用 AWS IAM role + temporary token）。Application 用 IAM auth 不必管 password rotation、但程式碼必須 <em>call AWS SDK 取 token、放 connection 設定</em>。</p>
<p>如果 Phase 2-3 期間沒 reverse engineer application connection logic、cutover 後 application 仍試用 password auth、Aurora 拒絕、production down。</p>
<p>修法：</p>
<ul>
<li>評估是否啟用 IAM auth — <em>簡單情況保留 password</em>、整合 AWS Secrets Manager 自動 rotation</li>
<li>啟用 IAM 必須 application code 改：
<ul>
<li>Java：<code>com.amazonaws.services.rds.auth.RdsIamAuthTokenGenerator</code></li>
<li>Python：<code>boto3.client('rds').generate_db_auth_token(...)</code></li>
<li>Go：<code>aws-sdk-go-v2/feature/rds/auth</code></li>
</ul>
</li>
<li>Phase 2 期間 application 對 Aurora 用 IAM token、self-managed 仍 password — 雙 path code</li>
</ul>
<h3 id="3-aurora-only-feature-寫進-applicationrollback-成本升高">3. Aurora-only feature 寫進 application、rollback 成本升高</h3>
<p>Migration 過程開發發現 Aurora 有 <em>Aurora-only feature</em>（Backtrack、Performance Insights、Aurora Global Database）、誘惑使用。一旦 application 用了 Aurora-only feature、要 rollback 自管 MySQL 變不可能（feature 不存在、query 失敗）。</p>
<p>常見 Aurora-only feature：</p>
<ul>
<li><em>Backtrack</em>：72 小時內 in-place rollback 整個 DB（不同於 PITR）</li>
<li><em>Aurora ML</em>：SQL function 內接 SageMaker / Comprehend</li>
<li><em>Aurora Parallel Query</em>：analytical query 跨 storage node 並行</li>
<li><em>Aurora Auto Scaling</em>：read replica 數量按 CPU 自動加減</li>
</ul>
<p>修法：</p>
<ul>
<li><em>Phase 1-3 期間禁用 Aurora-only feature</em>、保留 rollback option</li>
<li><em>Phase 4 完成後</em> 才開始 evaluate Aurora-only feature、加進來時 <em>明確記錄不可 rollback decision</em></li>
<li>把 Aurora-only feature 跟 <em>Aurora 特定 cluster</em> 綁定，避免 application 邏輯依賴 Aurora-only</li>
</ul>
<h3 id="4-read-replica-endpoint-behavior--application-不知道-reader-endpoint-round-robin">4. Read replica endpoint behavior — Application 不知道 reader endpoint round-robin</h3>
<p>Aurora reader endpoint（<code>prod-aurora.cluster-ro-xxx</code>）是 <em>DNS-based load balancer</em>、每次 DNS query 給不同 replica IP。Application connection pool 連續開 10 個 connection、可能全部連同一個 replica（DNS cache）、不均勻。</p>
<p>修法：</p>
<ul>
<li>Application connection pool 強制 <em>DNS re-resolve</em>（避免長時間 cache）</li>
<li>或用 <em>RDS Proxy</em>（managed connection pool）放在前面、不直接連 reader endpoint</li>
<li>或用 <em>Route 53 latency-based routing</em> 配 Aurora reader endpoint per AZ、application 連最近 AZ</li>
</ul>
<h3 id="5-region-failover--aurora-global-database-vs-自管-chained-replication">5. Region failover — Aurora Global Database vs 自管 chained replication</h3>
<p>自管 cross-region replication 是 <em>chained replication</em>（primary → region2 replica → region2 cascading replica）。Aurora Global Database 是 <em>storage-level replication</em>（storage page 直接 ship，而非 binlog）、跨 region &lt; 1 秒 lag、failover &lt; 1 分鐘。</p>
<p>但 Aurora Global Database 是 <em>active-passive</em>（primary region 可寫、secondary region 只讀）。如果原本自管已經 cross-region active-active write（用 multi-master 或應用層 sharding）、Aurora Global Database 的寫入模型會成為限制。</p>
<p>修法：</p>
<ul>
<li>評估 cross-region 是 <em>DR</em> 用途還是 <em>active write</em> 用途</li>
<li>純 DR + read scaling：Aurora Global Database 直接 cover</li>
<li>Active-active write：要 <em>Aurora DSQL</em>（2024 新推出、跟 Aurora 不同 product）或 distributed SQL（CockroachDB / Spanner）</li>
</ul>
<h2 id="capability-gap自管-mysql-有但-aurora-沒有">Capability gap：自管 MySQL 有但 Aurora 沒有</h2>
<table>
  <thead>
      <tr>
          <th>能力</th>
          <th>自管 MySQL</th>
          <th>Aurora MySQL</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Plugin 自己裝</td>
          <td>任意</td>
          <td>受限（Aurora 只允許官方支援）</td>
      </tr>
      <tr>
          <td>OS-level access</td>
          <td>完整 SSH access</td>
          <td>managed service，無 SSH access</td>
      </tr>
      <tr>
          <td>MySQL 8.0 latest patch</td>
          <td>你決定</td>
          <td>跟 Aurora major version 對應、有滯後</td>
      </tr>
      <tr>
          <td>InnoDB log_file_size</td>
          <td>自己改</td>
          <td>Aurora 內建 storage path</td>
      </tr>
      <tr>
          <td>Custom storage engine</td>
          <td>可（MyRocks / TokuDB）</td>
          <td>只 InnoDB（Aurora optimized）</td>
      </tr>
      <tr>
          <td>Cross-cloud DR</td>
          <td>自配 binlog ship</td>
          <td>Aurora-only (AWS region)</td>
      </tr>
  </tbody>
</table>
<p>評估時必須確認 <em>當前自管功能</em> 沒用到 Aurora 不支援的能力。如果在用 MyRocks 等 storage engine、Aurora migration 不可行。</p>
<h2 id="容量與成本對照">容量與成本對照</h2>
<p>對 100 GB DB、5K WPS、20 個 application instance 的 deployment：</p>
<table>
  <thead>
      <tr>
          <th>項目</th>
          <th>自管 MySQL（EC2）</th>
          <th>Aurora MySQL</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Primary instance</td>
          <td>r5.2xlarge（$0.50/hr）</td>
          <td>db.r6g.2xlarge（$0.83/hr）</td>
      </tr>
      <tr>
          <td>EBS / Aurora storage</td>
          <td>io2 100 GB + 5000 IOPS = ~$70/mo</td>
          <td>Aurora storage 100 GB = ~$10/mo + I/O $0.20/M</td>
      </tr>
      <tr>
          <td>Replica × 3</td>
          <td>3 × r5.2xlarge = $1080/mo</td>
          <td>3 × db.r6g.large = $540/mo</td>
      </tr>
      <tr>
          <td>Backup storage</td>
          <td>S3 + 自己 cron mysqldump ~$50/mo</td>
          <td>Aurora backup 100 GB 免費 + 額外 $0.021/GB</td>
      </tr>
      <tr>
          <td>Ops headcount</td>
          <td>1-2 FTE × $150K = $300-500K/yr</td>
          <td>&lt; 0.5 FTE × $150K = $75K/yr</td>
      </tr>
      <tr>
          <td><strong>Total infra</strong></td>
          <td>~$1500/mo + 大 ops cost</td>
          <td>~$2000-3000/mo + 小 ops cost</td>
      </tr>
  </tbody>
</table>
<p>Pure infra cost Aurora 貴 30-50%、但 <em>ops cost 降幅大過 infra increase</em> — 200 人 eng team 養 1.5 FTE DBA 是 $300K-400K/yr、Aurora 換成 0.3 FTE 是 $60K-100K/yr、差距 $200K+ 抵 infra increase。</p>
<p>小團隊 / 小 deployment Aurora 不一定划算 — 50 人 eng team 沒有 dedicated DBA、自管 MySQL 也只佔某人 20% 時間、Aurora migration 的 ops saving 不存在。</p>
<h2 id="production-casenetflix-aurora-consolidation">Production case：Netflix Aurora consolidation</h2>
<p>MySQL → Aurora migration 的 production 責任是把自管 database operation 轉移成 managed SQL 的契約，而非只搬 schema 與資料。<a href="/blog/backend/09-performance-capacity/cases/netflix-aurora-consolidation/" data-link-title="9.C23 Netflix：把關聯式 DB 統一到 Aurora、效能 &#43;75%、成本 -28%" data-link-desc="Netflix 把多套關聯式 DB 統一到 Aurora、效能提升 75%、成本下降 28%、串流數十億小時">9.C23 Netflix Aurora consolidation</a> 提供的工程訊號是多套 RDBMS 整併到 Aurora 後，效能、成本與操作責任一起改變。</p>
<p>這個案例要回收到三個操作判準。第一，migration driver 應寫成 operation transfer，例如 backup、failover、storage growth、patching 與 observability 由誰承擔。第二，效能與成本要一起看，因為 Aurora 的 storage / compute / I/O 計費會把原本藏在 DBA 操作裡的成本攤開。第三，整併多套 RDBMS 時要先做 feature inventory，確認 plugin、storage engine、charset、replication topology 與 SQL mode 都能落到 Aurora MySQL 支援範圍。</p>
<p>Netflix case 的 sibling 路由是 <a href="/blog/backend/01-database/vendors/aurora/" data-link-title="AWS Aurora" data-link-desc="AWS managed PostgreSQL / MySQL、storage / compute 分離、&#43;75% 效能改善的 production 證據">Aurora vendor page</a> 與 <a href="/blog/backend/01-database/vendors/postgresql/migrate-to-aurora/" data-link-title="PostgreSQL → Aurora Migration：protocol 相容、operational 重設計" data-link-desc="Aurora 號稱 PostgreSQL-compatible 但 operational model 不同（storage decouple / cluster endpoint / instance class / 自家備份）；遷移流程是混合（protocol drop-in &#43; operational phased）、5 個 production 踩雷（extension 不支援 / replication slot 不直通 / autovacuum 行為差 / IAM 認證強制 / cost model 換算）、跟 Patroni / read replica / DR 對位">PostgreSQL → Aurora</a>。若 migration 目標從 managed SQL 變成 multi-region active-active write，應改接 <a href="/blog/backend/01-database/global-distributed-oltp/" data-link-title="1.11 全球分散式 OLTP" data-link-desc="Spanner / Aurora DSQL / Cosmos DB multi-region write / CockroachDB / TiDB 的全球一致性取捨">1.11 全球分散式 OLTP</a>。</p>
<h2 id="何時維持原路線">何時維持原路線</h2>
<ul>
<li><strong>Cross-cloud portability 是 requirement</strong>：Aurora AWS-only、要 cross-cloud 用 PlanetScale 或 自管</li>
<li><strong>用 Percona Server fork / MyRocks 等非標準 engine</strong>：Aurora 不支援</li>
<li><strong>需要 OS-level customization</strong>：Aurora 完全 managed、無 SSH</li>
<li><strong>規模太小</strong>：&lt; 100 GB / &lt; 1K WPS、自管 MySQL EC2 spot instance 已經夠便宜</li>
<li><strong>規模太大</strong>：&gt; 50 TB single DB / &gt; 100K WPS、Aurora single-instance 仍是 ceiling、考慮 Vitess 或 Aurora DSQL</li>
</ul>
<h2 id="相關連結">相關連結</h2>
<ul>
<li>平行 batch：→ PlanetScale migration playbook（同 MySQL backlog、不同 target paradigm）</li>
<li>上游：<a href="/blog/backend/01-database/vendors/mysql/" data-link-title="MySQL" data-link-desc="高併發網路服務常用關聯式資料庫、Vitess / PlanetScale 分片生態、GitHub / Shopify / Facebook 規模驗證">MySQL vendor overview</a> / <a href="/blog/backend/01-database/vendors/aurora/" data-link-title="AWS Aurora" data-link-desc="AWS managed PostgreSQL / MySQL、storage / compute 分離、&#43;75% 效能改善的 production 證據">Aurora vendor page</a></li>
<li>跨章節：<a href="/blog/backend/09-performance-capacity/capacity-planning/" data-link-title="9.6 容量規劃模型" data-link-desc="peak forecast、headroom budget、growth curve、autoscaling sizing">9.6 容量規劃模型</a> — Aurora cost forecast</li>
<li>既有 case：<a href="/blog/backend/09-performance-capacity/cases/netflix-aurora-consolidation/" data-link-title="9.C23 Netflix：把關聯式 DB 統一到 Aurora、效能 &#43;75%、成本 -28%" data-link-desc="Netflix 把多套關聯式 DB 統一到 Aurora、效能提升 75%、成本下降 28%、串流數十億小時">9.C23 Netflix Aurora consolidation</a> — Netflix 從多套 RDBMS 統一到 Aurora 的 migration evidence</li>
<li>方法論：<a href="/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">Migration Playbook Methodology</a>（Type C operational hybrid 結構說明）</li>
<li>官方：<a href="https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Migrating.html">Aurora MySQL Migration Guide</a></li>
</ul>
]]></content:encoded></item><item><title>GitGuardian</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/gitguardian/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/gitguardian/</guid><description>&lt;p>GitGuardian 是 &lt;em>secret scanning + remediation&lt;/em> SaaS、起家於 GitHub public repo scan、現延伸到 internal SCM、CI 系統與 collaboration / chat 工具。它跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &amp;#43; Secret Scanning &amp;#43; Dependency Review &amp;#43; Dependabot、跟 PR / Security tab 深度整合">GHAS Secret Scanning&lt;/a> 的根本差異不在「能不能抓到 secret」、而在 &lt;em>偵測邊界跟 remediation workflow 的 shape&lt;/em> — GHAS 是 GitHub-only、partner pattern 強但 push protection 鎖在 GitHub repo；GitGuardian 把 detection 邊界擴到跨 SCM 跟 SaaS workspace、然後用 &lt;em>Incident&lt;/em> 物件管整個生命週期。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>GitGuardian 的核心定位是 &lt;em>跨工具的 secret leak detection + incident workflow&lt;/em>、不只是「pre-commit grep」。底層是一組 &lt;em>Detector&lt;/em>（350+ specific detector、覆蓋 AWS / GCP / Stripe / Slack / 自家 token 等）+ &lt;em>Validation endpoint&lt;/em>（call 該 service 確認 secret live 中），上層是 &lt;em>Incident&lt;/em> 物件（assign / resolve / ignore / share with developer）跟 &lt;em>Source&lt;/em> 抽象（GitHub / GitLab / Bitbucket / Azure DevOps / Slack / Jira / Confluence / Notion）。本機側用 &lt;em>ggshield&lt;/em> CLI 做 pre-commit hook 跟 CI scan。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &amp;#43; Secret Scanning &amp;#43; Dependency Review &amp;#43; Dependabot、跟 PR / Security tab 深度整合">GHAS Secret Scanning&lt;/a> 比、GitGuardian 走 &lt;em>cross-tool detection + remediation workflow&lt;/em>、GHAS 走 &lt;em>deep integration in GitHub&lt;/em>：GHAS 的 push protection 在 GitHub server-side 直接攔 push、partner pattern（AWS / Stripe / Slack）廣度高；但只要組織有 GitLab self-hosted、Bitbucket、或 developer 習慣把 token 貼 Slack / Confluence，GHAS 看不到的就是 GitGuardian 的場域。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/gitleaks/" data-link-title="Gitleaks" data-link-desc="OSS CLI secret scanner、Go 寫、Rule TOML &amp;#43; regex &amp;#43; entropy、SARIF output、跨 SCM、pre-commit &amp;#43; CI 友善">Gitleaks&lt;/a> / TruffleHog OSS 比、GitGuardian 走 &lt;em>managed SaaS + validation + workflow&lt;/em>、OSS 走 &lt;em>self-hosted + 你自己接 incident pipeline&lt;/em>；OSS 適合預算敏感 + 已有 SOC / IR tooling、GitGuardian 適合直接買 incident workflow 不想自建。&lt;/p></description><content:encoded><![CDATA[<p>GitGuardian 是 <em>secret scanning + remediation</em> SaaS、起家於 GitHub public repo scan、現延伸到 internal SCM、CI 系統與 collaboration / chat 工具。它跟 <a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GHAS Secret Scanning</a> 的根本差異不在「能不能抓到 secret」、而在 <em>偵測邊界跟 remediation workflow 的 shape</em> — GHAS 是 GitHub-only、partner pattern 強但 push protection 鎖在 GitHub repo；GitGuardian 把 detection 邊界擴到跨 SCM 跟 SaaS workspace、然後用 <em>Incident</em> 物件管整個生命週期。</p>
<h2 id="服務定位">服務定位</h2>
<p>GitGuardian 的核心定位是 <em>跨工具的 secret leak detection + incident workflow</em>、不只是「pre-commit grep」。底層是一組 <em>Detector</em>（350+ specific detector、覆蓋 AWS / GCP / Stripe / Slack / 自家 token 等）+ <em>Validation endpoint</em>（call 該 service 確認 secret live 中），上層是 <em>Incident</em> 物件（assign / resolve / ignore / share with developer）跟 <em>Source</em> 抽象（GitHub / GitLab / Bitbucket / Azure DevOps / Slack / Jira / Confluence / Notion）。本機側用 <em>ggshield</em> CLI 做 pre-commit hook 跟 CI scan。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GHAS Secret Scanning</a> 比、GitGuardian 走 <em>cross-tool detection + remediation workflow</em>、GHAS 走 <em>deep integration in GitHub</em>：GHAS 的 push protection 在 GitHub server-side 直接攔 push、partner pattern（AWS / Stripe / Slack）廣度高；但只要組織有 GitLab self-hosted、Bitbucket、或 developer 習慣把 token 貼 Slack / Confluence，GHAS 看不到的就是 GitGuardian 的場域。跟 <a href="/blog/backend/07-security-data-protection/vendors/gitleaks/" data-link-title="Gitleaks" data-link-desc="OSS CLI secret scanner、Go 寫、Rule TOML &#43; regex &#43; entropy、SARIF output、跨 SCM、pre-commit &#43; CI 友善">Gitleaks</a> / TruffleHog OSS 比、GitGuardian 走 <em>managed SaaS + validation + workflow</em>、OSS 走 <em>self-hosted + 你自己接 incident pipeline</em>；OSS 適合預算敏感 + 已有 SOC / IR tooling、GitGuardian 適合直接買 incident workflow 不想自建。</p>
<p>關鍵張力：<em>validation endpoint 是 FP 降噪核心</em>、但也是 <em>vendor 風險點</em>。Detector 抓到字串後 GitGuardian <em>call 該 service API live verify</em>（AWS access key 試 <code>sts:GetCallerIdentity</code>、Stripe key 試 retrieve event）、活躍 secret 才升 Incident。意義是 noise 從 OSS gitleaks 的 70-80% FP 降到 個位數 FP；風險是 GitGuardian <em>本身會 call 你的 cloud account</em> — vendor trust 跟 <a href="/blog/backend/07-security-data-protection/cases/failure-credential-rotation-without-scope/" data-link-title="7.C9 反例：憑證輪替未分 Scope" data-link-desc="憑證輪替若未分域分批，容易造成跨系統連鎖中斷。">Failure: Credential Rotation Without Scope</a> 的 scope map 需要在 onboarding 就釐清。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>GitGuardian 在 secret scanning stack 中承擔哪一段（pre-commit / SCM scan / SaaS scan / honeytoken）、哪些要外接（<a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a> 管 rotation、IR tool 接 incident）</li>
<li>Detector / Validation / Incident / Source 的 ownership 設計（誰 assign、誰 resolve、developer 怎麼參與）</li>
<li>跨 SCM + SaaS coverage 該開哪些 source、historical scan 多久跑一次</li>
<li>何時用 GitGuardian、何時走 GHAS / Gitleaks / TruffleHog 的取捨</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 GitGuardian deployment 是否健康、最少看四件事：</p>
<ul>
<li><strong>Source coverage 廣度</strong>：除 GitHub / GitLab 外、Slack / Jira / Confluence / Notion 是否也納入掃 — developer 把 token 貼 Slack DM 是常見 leak vector</li>
<li><strong>Validation endpoint 是否開</strong>：FP 降噪靠 live verify、未開等於回到 OSS gitleaks 的 noise 水位</li>
<li><strong>Incident remediation SLA</strong>：valid incident 從偵測到 rotation 完成的時間、是否串 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a> 自動 rotation、是否進 PagerDuty / Slack alert</li>
<li><strong>ggshield 在 CI 跟 pre-commit 的覆蓋率</strong>：是否所有 repo 走 pre-commit hook、CI step 是否阻擋 commit-with-secret merge</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/07-security-data-protection/secrets-and-machine-credential-governance/" data-link-title="7.6 秘密管理與機器憑證治理" data-link-desc="以問題驅動方式整理 secret、token、key 與機器身份治理">Secrets Management at Scale</a> 邊界的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>Detector library</strong>：350+ specific detector（AWS Access Key / Stripe Live Key / Slack Bot Token / GitHub PAT / 自家 API key pattern 等）+ generic high-entropy detector。Specific detector 走 vendor-specific pattern + validation endpoint、FP 個位數；generic detector 抓 unknown pattern、FP 較高、通常 routing 到 manual triage queue。Production tenant 應該全開 specific、generic 視 noise budget 開。</p>
<p><strong>Validation endpoint</strong>：detector 抓到字串後、GitGuardian backend <em>call 該 service API live verify</em>。AWS key 試 <code>sts:GetCallerIdentity</code>、Stripe key 試 retrieve test event、GitHub PAT 試 <code>GET /user</code>。verify 結果 <em>Valid</em> / <em>Invalid</em> / <em>Unknown</em> 三態、決定 incident severity。意義是 <em>只有 active secret 升 incident</em>、已 revoke 的舊 commit history 不再 noise。</p>
<p><strong>Incident workflow</strong>：偵測命中後會建 <em>Incident</em> 物件（而非直接 alert）、含 source location / detector / validation status / suggested remediation。Incident 可 <em>assign 給 developer</em>（developer 在 GitGuardian dashboard 自助 acknowledge / rotate / mark FP）、SecOps 只 review escalated case。對應 <a href="/blog/backend/07-security-data-protection/security-as-risk-routing-system/" data-link-title="7.15 資安作為風險路由系統" data-link-desc="建立資安作為風險路由系統的導讀大綱，串接問題節點、控制面與跨模組交接">Security Workflow as Code</a> 的 shift-left 模式 — developer 是 first responder、不是 SecOps 全包。</p>
<p><strong>Source coverage</strong>：GitGuardian 預設掃 SCM（GitHub / GitLab / Bitbucket / Azure DevOps / 自管 Git），但 <em>差異化價值在 SaaS scan</em> — Slack workspace（message / DM / file upload）、Jira issue / comment、Confluence page、Notion workspace、Microsoft Teams 都可接 source connector。Developer 在 Slack 貼 prod DB password 是真實常見 case、SCM-only 工具看不到。</p>
<p><strong>ggshield CLI</strong>：本地 / CI 端的 detection engine。<em>pre-commit hook</em> 攔住 push 前 leak（developer 機器、可被 bypass 但成本提高）、<em>CI step</em> 在 PR 跑 historical scan（不可 bypass、阻擋 merge）。跟 GHAS Push Protection 同類、但跨 SCM、且 detector pool 來自同一個 GitGuardian backend、跟 dashboard incident 走同一條 lineage。</p>
<p><strong>Historical scan</strong>：onboarding 第一次跑 <em>full git history scan</em>、回填過去所有 commit 的 leak。意義是 <em>已 leaked 多年的 secret 被找出來、強制 rotation</em>。對應 <a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/circleci-2023-secrets-rotation/" data-link-title="7.R7.2.3 CircleCI 2023：CI secrets 輪替壓力" data-link-desc="工程端點入侵後，CI 平台 secrets 如何成為高風險擴散點">CircleCI 2023 Secrets Rotation</a> 的場景：CI 環境 compromise 後、historical scan 在數小時內找出 CI 環境曾接觸過的所有 secret、配合 secret store API 自動 rotation。</p>
<p><strong>Honeytokens</strong>：散佈假 AWS / Stripe / GitHub token 到 repo 角落 / Confluence page / internal doc、attacker 拿到後試用會觸發 alert。是 <em>早期偵測 unauthorized access</em> 的工程化做法、不依賴 detection model 抓 attacker behavior、而是讓 attacker 自己 trigger 自己。對應 <a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/github-oauth-2022-token-supply-chain/" data-link-title="7.R7.2.2 GitHub OAuth 2022：第三方 token 供應鏈風險" data-link-desc="第三方整合 token 被竊後，如何形成跨組織存取風險">GitHub OAuth 2022 Token Supply Chain</a> — attacker 拿到 OAuth token 後試 GitHub API、honeytoken 在 attacker map 環境時就 trigger。</p>
<p><strong>Rotation 整合</strong>：detect 完不是工作結束、要 <em>rotate the secret</em>。GitGuardian 自身不存 secret，rotation 走 webhook / API 拉 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a> / AWS Secrets Manager / Azure Key Vault 觸發 rotation workflow。意義是 <em>偵測跟 remediation 解耦</em>、但需要組織側先把 secret store 接好、否則 incident 只能 manual rotation。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>GitGuardian</th>
          <th>GHAS Secret Scanning</th>
          <th>Gitleaks (OSS)</th>
          <th>TruffleHog</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>部署模型</td>
          <td>SaaS（self-hosted 有 enterprise tier）</td>
          <td>GitHub-only（SaaS / GHES）</td>
          <td>Self-hosted CLI / CI</td>
          <td>Self-hosted CLI / CI / SaaS tier</td>
      </tr>
      <tr>
          <td>Source 範圍</td>
          <td>GitHub / GitLab / Bitbucket / ADO / SaaS</td>
          <td>GitHub repo only</td>
          <td>Git repo（任何 host）</td>
          <td>Git / S3 / Docker / 多 source</td>
      </tr>
      <tr>
          <td>Validation</td>
          <td>內建、350+ detector live verify</td>
          <td>Partner pattern validation（部分）</td>
          <td>無（regex match only）</td>
          <td>有（verified mode）</td>
      </tr>
      <tr>
          <td>Push 攔截</td>
          <td>ggshield pre-commit + CI</td>
          <td>Push Protection（server-side、強制）</td>
          <td>pre-commit hook</td>
          <td>pre-commit hook</td>
      </tr>
      <tr>
          <td>Incident workflow</td>
          <td>內建 Incident + assign + dashboard</td>
          <td>GitHub Alert + Dependabot-like UI</td>
          <td>無（自接 SIEM）</td>
          <td>SaaS tier 有、OSS 無</td>
      </tr>
      <tr>
          <td>Honeytokens</td>
          <td>內建</td>
          <td>無</td>
          <td>無</td>
          <td>無</td>
      </tr>
      <tr>
          <td>計費</td>
          <td>Per developer / contributor（年訂）</td>
          <td>Per active committer（GitHub Enterprise）</td>
          <td>免費</td>
          <td>OSS 免費、SaaS 按 contributor</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>跨 SCM + SaaS、要 workflow + honeytoken</td>
          <td>GitHub-only + 已買 GHAS</td>
          <td>預算敏感 + 自建 IR pipeline</td>
          <td>多 source（含 S3 / Docker）、OSS-friendly</td>
      </tr>
      <tr>
          <td>退場成本</td>
          <td>中 — Incident 歷史在 vendor、detector 通用</td>
          <td>中 — 綁 GitHub UI、export 有限</td>
          <td>低 — 規則自有</td>
          <td>低 — 規則自有</td>
      </tr>
  </tbody>
</table>
<p>選 GitGuardian 的核心訴求：<em>跨 SCM + SaaS coverage + 內建 incident workflow + honeytoken</em>、且能投入 per-developer 訂閱（大型公司 contributor 數會放大成本）+ 有 SecOps 跟 developer 分工承接 incident。GitHub-only 環境且已買 GHAS、重疊不必要、直接用 GHAS；預算敏感且自家有 IR pipeline、走 <a href="/blog/backend/07-security-data-protection/vendors/gitleaks/" data-link-title="Gitleaks" data-link-desc="OSS CLI secret scanner、Go 寫、Rule TOML &#43; regex &#43; entropy、SARIF output、跨 SCM、pre-commit &#43; CI 友善">Gitleaks</a> 或 TruffleHog OSS。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Honeytokens 散佈策略</strong>：honeytoken 的效果取決於 <em>放在哪裡 + 看起來多真</em>。放 repo README、Confluence runbook、Slack <code>#engineering</code> 過期附件、舊 backup script — attacker reconnaissance 會優先看的地方。token 的命名要跟組織 naming convention 一致（<code>prod-db-readonly-2024</code>）、避免一看就是假的。每個 honeytoken 配 unique ID、trigger 時能定位 <em>attacker 從哪個位置拿到</em>、反推 leak surface。</p>
<p><strong>Validation endpoint 的 trade-off</strong>：validation 是 FP 降噪核心、但代價是 <em>GitGuardian 會 call 你的 cloud account</em>。AWS key 命中時 GitGuardian 從自家 IP call <code>sts:GetCallerIdentity</code>、log 留在你的 CloudTrail。Onboarding 要 <em>把 GitGuardian IP range allowlist 進 SIEM whitelist</em>、避免被自家 detection 誤判為 unauthorized access；同時要評估 vendor trust — 2020 年 GitGuardian 自家 source code 透過第三方 SaaS leak、提醒 vendor 不是 detection-only 的零信任邊界。</p>
<p><strong>IR workflow 整合</strong>：Incident 不應該停在 GitGuardian dashboard、要 routing 到組織既有 IR tooling — PagerDuty for on-call、Slack channel for SecOps、Jira ticket for tracking。Webhook 是標準做法、payload 含 incident metadata + validation status、由組織側決定升級邏輯（valid + prod scope → PagerDuty page；invalid + dev scope → Slack info）。</p>
<p><strong>Historical scan + scope map</strong>：偵測到 leaked secret 後、要回答 <em>這個 secret 還在哪裡用</em>。GitGuardian 的 historical scan 找出 <em>所有 commit 提到該 pattern 的位置</em>、配合組織側 secret store 的 <em>who uses this secret</em> metadata、形成 scope map。對應 <a href="/blog/backend/07-security-data-protection/cases/failure-credential-rotation-without-scope/" data-link-title="7.C9 反例：憑證輪替未分 Scope" data-link-desc="憑證輪替若未分域分批，容易造成跨系統連鎖中斷。">Failure: Credential Rotation Without Scope</a> — rotation 不能只換一個地方、要全 scope 一起換、否則舊 secret 還在某個 service 用、rotation 沒生效。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Incident volume 爆炸 / developer 看不完</strong>：generic high-entropy detector 全開 + 沒 assign 到 developer — 縮 generic detector scope、incident 走 assign-to-author、SecOps 只 review escalated</li>
<li><strong>Valid incident rotation 慢 / SLA 跑掉</strong>：沒接 secret store rotation API、停在 manual rotation — 接 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a> / Secrets Manager webhook、自動觸發 rotation workflow</li>
<li><strong>Slack / Confluence 沒掃進來</strong>：以為 SCM-only 就夠 — 接 SaaS source connector、developer 貼 token 在 Slack DM 是常見 leak vector</li>
<li><strong>ggshield 被 bypass</strong>：pre-commit 在 developer 機器、可 <code>--no-verify</code> — 同步在 CI step 跑 ggshield、CI 不可 bypass、阻擋 merge</li>
<li><strong>Validation FP 不降</strong>：validation endpoint 沒開、或被 firewall 擋 — 確認 GitGuardian IP range 在 cloud account allowlist、validation status 是 <em>Valid</em> 不是 <em>Unknown</em></li>
<li><strong>Honeytoken 沒 trigger / 假警報</strong>：token 放錯位置（attacker 不會看的 deep nested folder）或命名一看就假 — 散佈到 reconnaissance hot spot、命名跟組織 convention 一致</li>
<li><strong>Per-developer 計費暴衝</strong>：contractor / bot account 也算 developer — review billing report、排除 service account / read-only viewer、跟 vendor 談 contributor 定義</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>GitHub-only + 已買 GHAS</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GHAS Secret Scanning</a></td>
      </tr>
      <tr>
          <td>預算敏感 + 自建 IR pipeline</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/gitleaks/" data-link-title="Gitleaks" data-link-desc="OSS CLI secret scanner、Go 寫、Rule TOML &#43; regex &#43; entropy、SARIF output、跨 SCM、pre-commit &#43; CI 友善">Gitleaks</a> OSS / TruffleHog OSS</td>
      </tr>
      <tr>
          <td>多 source（S3 / Docker image）</td>
          <td>TruffleHog（覆蓋更多 non-Git source）</td>
      </tr>
      <tr>
          <td>Secret store / rotation</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a> / AWS Secrets Manager / Azure Key Vault</td>
      </tr>
      <tr>
          <td>SIEM correlation / cross-source</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / <a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a></td>
      </tr>
      <tr>
          <td>Supply chain build provenance</td>
          <td><a href="https://docs.sigstore.dev/">Sigstore / SLSA vendor 群</a>（同 vendor 章）</td>
      </tr>
      <tr>
          <td>Incident routing</td>
          <td><a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>ggshield 完整 CLI flag reference 跟 custom detector YAML schema</li>
<li>GitGuardian Internal Monitoring (self-hosted enterprise) 的部署架構細節</li>
<li>Honeytoken 在 active deception / canary token 廣義生態的位置（屬 deception engineering、不在本頁）</li>
<li>Detector pattern 的 regex / entropy 細節（屬 detection engineering）</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>GitGuardian 在 07 案例庫沒有直接 vendor-level 事件、但所有 secret leak / supply chain case 都是它的偵測對照：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 GitGuardian 的關係（對照啟示）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/circleci-2023-secrets-rotation/" data-link-title="7.R7.2.3 CircleCI 2023：CI secrets 輪替壓力" data-link-desc="工程端點入侵後，CI 平台 secrets 如何成為高風險擴散點">CircleCI 2023 Secrets Rotation</a></td>
          <td>Historical scan 在 CI compromise 後數小時內找出 CI 環境曾接觸過的所有 secret、配合 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a> 自動 rotation、不是 console manual rotation</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/github-oauth-2022-token-supply-chain/" data-link-title="7.R7.2.2 GitHub OAuth 2022：第三方 token 供應鏈風險" data-link-desc="第三方整合 token 被竊後，如何形成跨組織存取風險">GitHub OAuth 2022 Token Supply Chain</a></td>
          <td>Honeytokens 散佈在 repo 跟 Confluence、attacker 拿到 OAuth token 後試 GitHub API 時 trigger、不靠 detection model 抓 attacker behavior</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/cases/failure-credential-rotation-without-scope/" data-link-title="7.C9 反例：憑證輪替未分 Scope" data-link-desc="憑證輪替若未分域分批，容易造成跨系統連鎖中斷。">Failure: Credential Rotation Without Scope</a></td>
          <td>GitGuardian historical scan 找出 leaked secret 的 <em>scope map</em>（哪些 service 共用同一個 secret）、配合 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a> 分域 rotation 才完整</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/solarwinds-2020-sunburst/" data-link-title="7.R7.2.1 SolarWinds 2020：更新鏈被濫用" data-link-desc="合法更新流程遭植入後，攻擊者如何長期潛伏與橫向擴散">SolarWinds 2020 Sunburst</a></td>
          <td>secret scanning 抓不到 build pipeline 內 malicious code 注入、要靠 <a href="https://docs.sigstore.dev/">Sigstore / SLSA</a> provenance；secret scanning 是覆蓋一段、不是全部</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/secrets-and-machine-credential-governance/" data-link-title="7.6 秘密管理與機器憑證治理" data-link-desc="以問題驅動方式整理 secret、token、key 與機器身份治理">7.x Secrets Management at Scale</a>、<a href="/blog/backend/07-security-data-protection/security-as-risk-routing-system/" data-link-title="7.15 資安作為風險路由系統" data-link-desc="建立資安作為風險路由系統的導讀大綱，串接問題節點、控制面與跨模組交接">Security Workflow as Code</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GHAS Secret Scanning</a>、<a href="/blog/backend/07-security-data-protection/vendors/gitleaks/" data-link-title="Gitleaks" data-link-desc="OSS CLI secret scanner、Go 寫、Rule TOML &#43; regex &#43; entropy、SARIF output、跨 SCM、pre-commit &#43; CI 友善">Gitleaks</a>、TruffleHog</li>
<li>下游：<a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a>（rotation 接點）、<a href="/blog/backend/07-security-data-protection/vendors/aws-secrets-manager/" data-link-title="AWS Secrets Manager" data-link-desc="AWS 原生 secret store &#43; 內建 RDS / Redshift rotation Lambda、Resource Policy 跨帳號共享、KMS 加密">AWS Secrets Manager</a> / <a href="/blog/backend/07-security-data-protection/vendors/azure-key-vault/" data-link-title="Azure Key Vault" data-link-desc="Azure 三合一 service（Secret &#43; Key &#43; Certificate）、整合 Managed Identity &#43; Entra ID RBAC、Premium tier 走 HSM">Azure Key Vault</a></li>
<li>跨類：<a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a>（Incident webhook → SIEM）、<a href="https://docs.sigstore.dev/">Sigstore</a>（build provenance 覆蓋 secret scanning 抓不到的段）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（Incident → IR routing）</li>
<li>官方：<a href="https://docs.gitguardian.com/">GitGuardian Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>MySQL → PlanetScale：managed Vitess + branch-based schema workflow 的 hybrid shift</title><link>https://tarrragon.github.io/blog/backend/01-database/vendors/mysql/migrate-to-planetscale/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/01-database/vendors/mysql/migrate-to-planetscale/</guid><description>&lt;blockquote>
&lt;p>本文是跨 vendor migration playbook、cross-link 到 &lt;a href="https://tarrragon.github.io/blog/backend/01-database/vendors/mysql/" data-link-title="MySQL" data-link-desc="高併發網路服務常用關聯式資料庫、Vitess / PlanetScale 分片生態、GitHub / Shopify / Facebook 規模驗證">MySQL&lt;/a> 跟 PlanetScale。走 &lt;a href="https://tarrragon.github.io/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">Migration playbook methodology&lt;/a> Type E paradigm shift 結構。&lt;/p>&lt;/blockquote>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>維度&lt;/th>
 &lt;th>自管 MySQL&lt;/th>
 &lt;th>PlanetScale&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Sharding&lt;/td>
 &lt;td>自己配 Vitess 或不 shard&lt;/td>
 &lt;td>Vitess 透明（即使單 keyspace 也走 Vitess）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Schema migration&lt;/td>
 &lt;td>gh-ost / pt-osc 跑 ALTER&lt;/td>
 &lt;td>&lt;strong>Branch + Deploy Request&lt;/strong> workflow&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Failover&lt;/td>
 &lt;td>Orchestrator 自管&lt;/td>
 &lt;td>PlanetScale 自動&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Branching&lt;/td>
 &lt;td>不存在概念&lt;/td>
 &lt;td>&lt;strong>DB branch（git-like）+ revert&lt;/strong>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Connection limit&lt;/td>
 &lt;td>max_connections 自己設&lt;/td>
 &lt;td>PlanetScale connection pool / per-plan limit&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Foreign key&lt;/td>
 &lt;td>支援&lt;/td>
 &lt;td>有限支援（Vitess 18+ / 2023 起、需明確啟用）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>SUPER&lt;/code> privilege&lt;/td>
 &lt;td>自己有&lt;/td>
 &lt;td>&lt;strong>無&lt;/strong>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Multi-region&lt;/td>
 &lt;td>自己配 binlog ship&lt;/td>
 &lt;td>PlanetScale 內建（Boost feature）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Per-month cost&lt;/td>
 &lt;td>EC2 + EBS + ops&lt;/td>
 &lt;td>per-row-read + per-row-written + storage&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>從 &lt;em>application 連線&lt;/em> 視角：跟 &lt;a href="https://tarrragon.github.io/blog/backend/01-database/vendors/mysql/migrate-to-aurora/" data-link-title="MySQL → Aurora MySQL：storage layer 轉手到 AWS、replication / HA / backup 全部 outsource" data-link-desc="自管 MySQL → Aurora MySQL 是 Type C operational hybrid migration — wire protocol 一致、ops 責任轉到 AWS。本文走 6 維 audit（Operational High）、Aurora storage architecture 衝擊、4-phase migration、5 production 踩雷、何時維持原路線。">Aurora MySQL migration&lt;/a> 一樣低、connection string 換就完事。從 &lt;em>schema management&lt;/em> 視角：PlanetScale 強推 &lt;em>branch-based workflow&lt;/em> — 改 schema 不再是「跑 gh-ost」、是「開 branch → Deploy Request → review → merge」。整個 schema change 工作流跟 git 同型、跟 application code review 同 workflow。&lt;/p>
&lt;p>這是 &lt;em>workflow + schema-tooling shift&lt;/em> — Aurora 是「同 workflow + managed」、PlanetScale 是「同 protocol + 不同 schema workflow + branch tooling」。Database paradigm（OLTP relational）跟 application change 都 Low、主要 shift 在 DBA / dev 操作介面。&lt;/p></description><content:encoded><![CDATA[<blockquote>
<p>本文是跨 vendor migration playbook、cross-link 到 <a href="/blog/backend/01-database/vendors/mysql/" data-link-title="MySQL" data-link-desc="高併發網路服務常用關聯式資料庫、Vitess / PlanetScale 分片生態、GitHub / Shopify / Facebook 規模驗證">MySQL</a> 跟 PlanetScale。走 <a href="/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">Migration playbook methodology</a> Type E paradigm shift 結構。</p></blockquote>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>自管 MySQL</th>
          <th>PlanetScale</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Sharding</td>
          <td>自己配 Vitess 或不 shard</td>
          <td>Vitess 透明（即使單 keyspace 也走 Vitess）</td>
      </tr>
      <tr>
          <td>Schema migration</td>
          <td>gh-ost / pt-osc 跑 ALTER</td>
          <td><strong>Branch + Deploy Request</strong> workflow</td>
      </tr>
      <tr>
          <td>Failover</td>
          <td>Orchestrator 自管</td>
          <td>PlanetScale 自動</td>
      </tr>
      <tr>
          <td>Branching</td>
          <td>不存在概念</td>
          <td><strong>DB branch（git-like）+ revert</strong></td>
      </tr>
      <tr>
          <td>Connection limit</td>
          <td>max_connections 自己設</td>
          <td>PlanetScale connection pool / per-plan limit</td>
      </tr>
      <tr>
          <td>Foreign key</td>
          <td>支援</td>
          <td>有限支援（Vitess 18+ / 2023 起、需明確啟用）</td>
      </tr>
      <tr>
          <td><code>SUPER</code> privilege</td>
          <td>自己有</td>
          <td><strong>無</strong></td>
      </tr>
      <tr>
          <td>Multi-region</td>
          <td>自己配 binlog ship</td>
          <td>PlanetScale 內建（Boost feature）</td>
      </tr>
      <tr>
          <td>Per-month cost</td>
          <td>EC2 + EBS + ops</td>
          <td>per-row-read + per-row-written + storage</td>
      </tr>
  </tbody>
</table>
<p>從 <em>application 連線</em> 視角：跟 <a href="/blog/backend/01-database/vendors/mysql/migrate-to-aurora/" data-link-title="MySQL → Aurora MySQL：storage layer 轉手到 AWS、replication / HA / backup 全部 outsource" data-link-desc="自管 MySQL → Aurora MySQL 是 Type C operational hybrid migration — wire protocol 一致、ops 責任轉到 AWS。本文走 6 維 audit（Operational High）、Aurora storage architecture 衝擊、4-phase migration、5 production 踩雷、何時維持原路線。">Aurora MySQL migration</a> 一樣低、connection string 換就完事。從 <em>schema management</em> 視角：PlanetScale 強推 <em>branch-based workflow</em> — 改 schema 不再是「跑 gh-ost」、是「開 branch → Deploy Request → review → merge」。整個 schema change 工作流跟 git 同型、跟 application code review 同 workflow。</p>
<p>這是 <em>workflow + schema-tooling shift</em> — Aurora 是「同 workflow + managed」、PlanetScale 是「同 protocol + 不同 schema workflow + branch tooling」。Database paradigm（OLTP relational）跟 application change 都 Low、主要 shift 在 DBA / dev 操作介面。</p>
<h2 id="為什麼是-type-eparadigm--operational--schema-多軸">為什麼是 Type E（Paradigm + Operational + Schema 多軸）</h2>
<p>跑 <a href="/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/#%e5%af%ab%e5%89%8d%e7%9a%84-diff-dimension-audit" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">6 維 diff dimension audit</a>：</p>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>評</th>
          <th>說明</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Schema</td>
          <td>Medium-High</td>
          <td>MySQL wire protocol 一致、FK 有限支援（Vitess 18+）、部分 INSTANT DDL 行為差</td>
      </tr>
      <tr>
          <td>Operational</td>
          <td>High</td>
          <td>branch lifecycle、Deploy Request workflow、connection pooler 不同</td>
      </tr>
      <tr>
          <td>Paradigm</td>
          <td>High</td>
          <td>branch-based schema management、跟自管 gh-ost / pt-osc 思維完全不同</td>
      </tr>
      <tr>
          <td>Components</td>
          <td>Medium</td>
          <td>PlanetScale CLI / Console / API / connection pooler 都進團隊工具</td>
      </tr>
      <tr>
          <td>App change</td>
          <td>Low</td>
          <td>connection string + 移除 FK 約束</td>
      </tr>
      <tr>
          <td>Topology</td>
          <td>Low-Medium</td>
          <td>Vitess 透明 sharding 即使單 keyspace</td>
      </tr>
  </tbody>
</table>
<p>Paradigm + Operational + Schema 三軸 High。按優先序 Schema &gt; Paradigm &gt; Operational、預設選 Type A。但 <em>讀者最關心</em> 的是 schema workflow paradigm 轉變、不是 schema field translation — Type E 結構更貼合「不收斂、部分 adopt」的真實 migration 流程。</p>
<p>→ <strong>Type E paradigm shift</strong>、4-phase partial migration（多數 org 停 Phase 2-3 hybrid）。</p>
<h2 id="driverbranch-based-workflow--vitess-transparent-sharding--zero-dba">Driver：Branch-based workflow + Vitess transparent sharding + zero DBA</h2>
<p>從自管 MySQL 遷 PlanetScale 的核心 driver 有三條：</p>
<p><strong>Branch-based schema workflow</strong>：</p>
<ul>
<li>改 schema 開 branch（<code>pscale branch create</code>）、在 branch 上跑 ALTER、跑 application code 改、merge 進 main 前 Deploy Request review</li>
<li>Deploy Request 顯示 schema diff、跟 GitHub PR 同概念</li>
<li>Merge 後 PlanetScale 自動跑 <em>no-downtime schema migration</em>（內部 VReplication）</li>
<li>出問題可 <em>revert</em>（48 小時內、用 Vitess VReplication 反向 ship 資料）</li>
</ul>
<p>這條 workflow 對 <em>developer ergonomic</em> 拉力大 — schema change 不再是「DBA 工作」、是「dev 自己處理、跟 code review 同流程」。</p>
<p><strong>Vitess transparent sharding</strong>：</p>
<ul>
<li>PlanetScale 強制每個 cluster 走 Vitess（即使單 keyspace 看似 unsharded）</li>
<li>寫吞吐成長到需要 shard 時、加 shard 是 PlanetScale internal 操作、application 看不到</li>
<li>不用養 Vitess SRE 團隊</li>
</ul>
<p><strong>Zero DBA</strong>：</p>
<ul>
<li>PlanetScale 接管所有 ops（failover / backup / parameter / scaling）</li>
<li>跟 Aurora 同等級「managed」、加上 branch workflow</li>
</ul>
<p>FK 處理：早期 Vitess（&lt; 18）不支援 FK、PlanetScale 對應期間建議全 drop FK + 改 application enforcement。Vitess 18（2023 末）後加 FK 支援、PlanetScale 在合適 plan 內可啟用、但 <em>cross-shard FK</em> 仍受限。Phase 1 audit 重點不再是「全 drop FK」、而是「驗證 FK 行為（特別 cascade / cross-shard）跟自管 MySQL 預期一致」。</p>
<h2 id="4-phase-partial-migration不收斂">4-phase partial migration（不收斂）</h2>
<h3 id="phase-1fk-行為驗證--schema-auditplanetscale-shadow-cluster-起來">Phase 1：FK 行為驗證 + schema audit、PlanetScale shadow cluster 起來</h3>
<p>第一步是 <em>FK 行為驗證</em> + schema layout audit。Vitess 18+ / PlanetScale 已支援 FK、但行為跟自管 MySQL 有差異：</p>
<ul>
<li>列所有 FK：<code>SELECT * FROM information_schema.KEY_COLUMN_USAGE WHERE REFERENCED_TABLE_NAME IS NOT NULL</code></li>
<li>對每個 FK 評估：
<ul>
<li><em>Cross-shard FK</em>：PlanetScale 不允許 FK 跨 shard、parent 跟 child 必須同 shard（透過 Vindex 設計）</li>
<li><em>Cascade 行為</em>：cross-shard DELETE cascade 在 PlanetScale 不執行、改 application 層處理</li>
<li><em>Native FK 啟用 vs application enforcement</em>：依 Vitess 18+ 行為決定保留 FK 或改 app-level</li>
</ul>
</li>
<li><em>PlanetScale shadow cluster</em> 起來、跑 application schema、用 Vitess Connector 從自管 binlog ship 資料</li>
</ul>
<p>工作主要塊：</p>
<ul>
<li>FK 行為 audit + 改 cross-shard cascade（依 FK 數量、weeks 工作量）</li>
<li>Schema dump → PlanetScale import（用 <code>pscale shell</code>）</li>
<li>Vitess Connector 設定 binlog stream</li>
</ul>
<p>完成標準：PlanetScale shadow cluster 有完整 production schema、cross-shard FK 已處理、binlog stream lag &lt; 1 秒。</p>
<h3 id="phase-2read-traffic-切-planetscale">Phase 2：Read traffic 切 PlanetScale</h3>
<p>跟 <a href="/blog/backend/01-database/vendors/mysql/migrate-to-aurora/" data-link-title="MySQL → Aurora MySQL：storage layer 轉手到 AWS、replication / HA / backup 全部 outsource" data-link-desc="自管 MySQL → Aurora MySQL 是 Type C operational hybrid migration — wire protocol 一致、ops 責任轉到 AWS。本文走 6 維 audit（Operational High）、Aurora storage architecture 衝擊、4-phase migration、5 production 踩雷、何時維持原路線。">Aurora migration</a> Phase 2 同概念：read query 切 PlanetScale connection string、寫入仍自管 MySQL。</p>
<p>差異：</p>
<ul>
<li>PlanetScale connection 有 <em>per-plan rate limit</em>（Scaler Plan: 10K connections、Enterprise: 100K）</li>
<li>必須走 <em>PlanetScale connection pool</em>（不是直接連、有 SSL handshake overhead）</li>
<li>監控 <code>pscale_io_read_query_throttled_total</code> 確認沒撞 plan limit</li>
</ul>
<p>跑 2-4 週、確認：</p>
<ul>
<li>PlanetScale read latency 跟自管 replica latency 接近（PlanetScale Boost cache 可能比自管快）</li>
<li>Vitess Connector stream 穩定</li>
<li>Application 對 PlanetScale row read 量符合 cost forecast</li>
</ul>
<h3 id="phase-3schema-workflow-切-planetscale--write-cutover">Phase 3：Schema workflow 切 PlanetScale + write cutover</h3>
<p>關鍵 paradigm shift：<em>停 gh-ost / pt-osc</em>、改用 PlanetScale branch workflow。</p>
<p>訓練步驟：</p>
<ol>
<li><em>第一個 small schema change</em> 用 PlanetScale branch + Deploy Request 跑</li>
<li>開發團隊熟悉 <code>pscale branch create</code> / <code>pscale deploy-request create</code> CLI</li>
<li>CI integration：把 PlanetScale CLI 加進 deploy pipeline</li>
<li>退役 gh-ost / pt-osc CI integration</li>
</ol>
<p>完成 schema workflow 訓練後 write cutover：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 1. PlanetScale 把 shadow cluster promote 為 primary（用 PlanetScale console / API）</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># 透過 PlanetScale Console 啟用 production write 或用 `pscale` CLI 對應 promotion 命令</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="c1"># （CLI 命令名稱隨 pscale 版本變動、以 pscale --help 為準）</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="c1"># 2. Application connection string 切 PlanetScale writer</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="c1"># 自管 → mysql://primary.example.com:3306/production</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="c1"># PlanetScale → mysql://...@xxx.connect.psdb.cloud/production?sslaccept=strict</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl">
</span></span><span class="line"><span class="ln">9</span><span class="cl"><span class="c1"># 3. Vitess Connector 反向（PlanetScale → 自管）作為 rollback insurance</span></span></span></code></pre></div><p>完成標準：寫入流量 100% 進 PlanetScale、自管 MySQL 接 PlanetScale binlog（rollback buffer）。</p>
<h3 id="phase-4自管-mysql-退役--保留作-rollback-buffer">Phase 4：自管 MySQL 退役 / 保留作 rollback buffer</h3>
<p>跟 Aurora migration Phase 4 同模式：</p>
<ul>
<li>自管保留 30-90 天作 cold buffer</li>
<li>確認 PlanetScale cost forecast 跟 actual 一致（per-row read / write 計費可能超預期）</li>
<li>確認 branch workflow 在 production team 內 adopt（不是「PlanetScale 在用、但團隊還是用 gh-ost on staging」這種 stuck 狀態）</li>
</ul>
<p>多數 org 在 <em>Phase 3</em> 停留更久（半年-一年）— Vitess Connector 反向 binlog ship 是穩定 rollback path、Phase 4 不急。</p>
<h2 id="5-個-production-踩雷">5 個 Production 踩雷</h2>
<h3 id="1-cross-shard-fk--planetscale-跟-native-mysql-行為不同">1. Cross-shard FK — PlanetScale 跟 native MySQL 行為不同</h3>
<p>Vitess 18+ / PlanetScale 已支援 FK、但 <em>cross-shard cascade</em> 不執行。同 shard 內 FK 跟 native MySQL 一致；parent 跟 child 跨 shard 時、<code>ON DELETE CASCADE</code> 在 PlanetScale 不會跨 shard 觸發 child delete、結果 application 看到 <em>orphan row</em>。</p>
<p>修法：</p>
<ul>
<li>Phase 1 audit 出哪些 FK 跨 shard（Vindex 設計決定 parent / child 是否同 shard）</li>
<li>同 shard FK：直接保留、行為跟自管 MySQL 一致</li>
<li>Cross-shard cascade：改 application 層 transaction 內 explicit DELETE child、或 <em>background reconciliation job</em>（定期掃 orphan）</li>
<li>把 <em>parent / child 強制同 shard</em>（用相同 Vindex column）是預防 cross-shard FK 議題的根本解</li>
</ul>
<h3 id="2-deploy-request-思維轉換不到位--團隊仍用跑-alter心智模型">2. Deploy Request 思維轉換不到位 — 團隊仍用「跑 ALTER」心智模型</h3>
<p>DBA / SRE 習慣 <em>直接連 PlanetScale 跑 ALTER</em> —但 PlanetScale 在 production branch 上 <em>禁止 DDL</em>（必須走 Deploy Request）。失敗訊息 <em>not actionable</em>（ERROR: not authorized）、DBA 找不到原因、production maintenance 卡住。</p>
<p>修法：</p>
<ul>
<li>Phase 3 <em>訓練步驟</em> 不能跳：找一個 small schema change 在 staging 走完整 branch workflow、團隊每個 DBA / SRE 都 hands-on 過</li>
<li>在 ops runbook 寫明 <em>production schema change must go through Deploy Request</em>、列 CLI 命令模板</li>
<li>緊急 schema change（事故中）也走 branch + Deploy Request、PlanetScale 可加速 Deploy（不能 bypass workflow）</li>
</ul>
<h3 id="3-schema-diff-邊界--planetscale-看不到-application-level-insert-changes">3. Schema diff 邊界 — PlanetScale 看不到 application-level INSERT changes</h3>
<p>Deploy Request 顯示 <em>schema-level diff</em>（CREATE / ALTER / DROP）、不顯示 <em>data diff</em>。如果 branch 上有 INSERT 進去（測試資料 / seed data）、merge 進 main 時 <em>資料不會搬</em>（只搬 schema）、application 預期有資料但 production 沒。</p>
<p>修法：</p>
<ul>
<li>把 <em>seed data INSERT</em> 放 application migration / fixture、不在 PlanetScale branch 內</li>
<li>用 PlanetScale CLI <em>export branch data</em> 跟 <em>import to main</em>（手動操作）作為 escape hatch</li>
<li>教育團隊：PlanetScale branch = <em>schema branch</em>、不是 git-like <em>data branch</em></li>
</ul>
<h3 id="4-branch-lifecycle-ops-cost--100-個-stale-branch">4. Branch lifecycle ops cost — 100 個 stale branch</h3>
<p>每個 PR 都開一個 PlanetScale branch、PR merge 後忘記刪、累積 100 個 stale branch。每個 branch 佔 storage cost、PlanetScale plan limit 也限制 branch 數量。</p>
<p>修法：</p>
<ul>
<li>CI integration：PR close 自動 <code>pscale branch delete &lt;branch-name&gt;</code></li>
<li>設 <em>branch retention policy</em>（30 天無活動自動刪）</li>
<li>監控 <code>pscale branch list | wc -l</code> 數量、超 threshold alert</li>
<li>把 branch lifecycle 寫進 <em>team playbook</em>（不是 PlanetScale 教、是團隊內部規範）</li>
</ul>
<h3 id="5-無-super-privilege--部分操作不可行">5. 無 <code>SUPER</code> privilege — 部分操作不可行</h3>
<p>PlanetScale connection 拿到的 MySQL user 沒有 <code>SUPER</code> privilege。需要 <code>SUPER</code> 的操作直接失敗：</p>
<ul>
<li><code>SET GLOBAL</code>（不能改 runtime variable）</li>
<li><code>KILL</code> 別人的 query（PlanetScale console 提供 alt 介面）</li>
<li><code>SHOW MASTER STATUS</code> / <code>SHOW SLAVE STATUS</code>（PlanetScale 抽象掉、不暴露）</li>
<li><code>INSTALL PLUGIN</code>（managed、不允許）</li>
<li><code>STOP SLAVE</code> / <code>START SLAVE</code>（Vitess 內部）</li>
</ul>
<p>修法：</p>
<ul>
<li>評估 application 跟 ops tool 是否依賴 <code>SUPER</code> privilege</li>
<li>改用 PlanetScale console / API 等價操作</li>
<li>部分監控 query（<code>SHOW SLAVE STATUS</code>）用 <em>PlanetScale 內建 dashboard</em> 代替</li>
</ul>
<h2 id="schema-translation-主要工作量塊">Schema translation 主要工作量塊</h2>
<p>雖然 Type E 結構不以 schema translation 為主、但 schema diff 在 Phase 1 仍佔多數時間：</p>
<table>
  <thead>
      <tr>
          <th>自管 MySQL</th>
          <th>PlanetScale (Vitess)</th>
          <th>翻譯難度</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>FOREIGN KEY constraint</td>
          <td>（無）+ application enforcement</td>
          <td>高</td>
      </tr>
      <tr>
          <td>INSTANT DDL</td>
          <td>部分支援、其他走 Vitess online DDL</td>
          <td>低-中</td>
      </tr>
      <tr>
          <td>Stored procedure</td>
          <td>支援</td>
          <td>低</td>
      </tr>
      <tr>
          <td>Trigger</td>
          <td>支援</td>
          <td>低</td>
      </tr>
      <tr>
          <td>User-defined function</td>
          <td>受限</td>
          <td>中</td>
      </tr>
      <tr>
          <td>INSERT 跨表（CTE）</td>
          <td>支援</td>
          <td>低</td>
      </tr>
      <tr>
          <td>Cross-shard JOIN</td>
          <td>必須用 Vindex（user_id 等 shard key 同表）</td>
          <td>中-高</td>
      </tr>
      <tr>
          <td><code>SUPER</code> 行為</td>
          <td>不支援</td>
          <td>中（ops tool 改）</td>
      </tr>
      <tr>
          <td><code>RELOAD</code> privilege</td>
          <td>不支援</td>
          <td>中</td>
      </tr>
  </tbody>
</table>
<h2 id="容量與成本對照">容量與成本對照</h2>
<p>PlanetScale 計費 <em>很不同</em>：</p>
<table>
  <thead>
      <tr>
          <th>項目</th>
          <th>自管 MySQL（EC2）</th>
          <th>PlanetScale Scaler Pro</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Per-row read</td>
          <td>不計費</td>
          <td>按量計費、$1 per 1B row read</td>
      </tr>
      <tr>
          <td>Per-row written</td>
          <td>不計費</td>
          <td>按量計費、$1.50 per 1M row write</td>
      </tr>
      <tr>
          <td>Storage</td>
          <td>EBS、$0.10/GB-month</td>
          <td>$1.50/GB-month + replication overhead</td>
      </tr>
      <tr>
          <td>Connection limit</td>
          <td>max_connections 自己設</td>
          <td>per-plan limit、可加 Connection pooler</td>
      </tr>
      <tr>
          <td>Branch</td>
          <td>不適用</td>
          <td>每 branch 含 storage cost</td>
      </tr>
      <tr>
          <td>Boost cache</td>
          <td>不適用</td>
          <td>additional cost</td>
      </tr>
      <tr>
          <td>Ops headcount</td>
          <td>1-2 FTE</td>
          <td>&lt; 0.2 FTE</td>
      </tr>
  </tbody>
</table>
<p>PlanetScale 適合 <em>小-中規模 + high developer productivity priority</em>：</p>
<ul>
<li>流量 &lt; 10K WPS：cost 接近自管、developer productivity 顯著提升</li>
<li>流量 10-50K WPS：cost 開始貴、但 ops saving 仍大於 cost increase</li>
<li>流量 &gt; 100K WPS：PlanetScale Enterprise 議價、要 commit pricing</li>
</ul>
<p>對 high-traffic 場景 cost forecast 必須跑 <em>真實 workload trace</em> — PlanetScale 提供 <code>pscale analytics</code> 預估 read / write 量、用 production binlog replay 在 staging 跑、估算 row read / write 計費。</p>
<h2 id="何時不要遷">何時不要遷</h2>
<ul>
<li><strong>FK 是 application core constraint</strong>：cascade DELETE / SET NULL 廣泛使用、application 改不動</li>
<li><strong>大量 <code>SUPER</code>-required ops 自動化</strong>：DBA tools / monitoring 寫死 <code>SUPER</code>、改不動</li>
<li><strong>OS-level customization 需求</strong>：跟 Aurora 一樣、PlanetScale 完全 managed</li>
<li><strong>流量極大 + 預算敏感</strong>：&gt; 100K WPS row read 計費可能比 EC2 貴 5x、需要 Enterprise commit pricing</li>
<li><strong>跨雲 portability 是 requirement</strong>：PlanetScale 跑在自家 cloud（背後 AWS / GCP）、不像自管 Vitess 可跨雲</li>
</ul>
<h2 id="跟-aurora-mysql-對比同-batch-的選擇">跟 Aurora MySQL 對比（同 batch 的選擇）</h2>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>Aurora MySQL</th>
          <th>PlanetScale</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Type</td>
          <td>C operational hybrid</td>
          <td>E paradigm shift</td>
      </tr>
      <tr>
          <td>工作量主軸</td>
          <td>parameter group + IAM + endpoint</td>
          <td>FK audit + branch workflow</td>
      </tr>
      <tr>
          <td>Sharding</td>
          <td>不 shard、single-region scaling</td>
          <td>Vitess 透明 sharding</td>
      </tr>
      <tr>
          <td>Schema workflow</td>
          <td>仍用 gh-ost / pt-osc</td>
          <td>Branch + Deploy Request</td>
      </tr>
      <tr>
          <td>FK</td>
          <td>支援</td>
          <td>不支援</td>
      </tr>
      <tr>
          <td>Cost model</td>
          <td>per-hour instance + per-GB storage</td>
          <td>per-row read / write + per-GB storage</td>
      </tr>
      <tr>
          <td>適合規模</td>
          <td>100 GB - 50 TB</td>
          <td>100 GB - 1 PB</td>
      </tr>
      <tr>
          <td>跨雲</td>
          <td>AWS-only</td>
          <td>PlanetScale 背後 AWS / GCP</td>
      </tr>
  </tbody>
</table>
<p>選擇邏輯：</p>
<ul>
<li><em>AWS-heavy ecosystem + 不想 schema workflow paradigm shift</em> → Aurora</li>
<li><em>Developer-first culture + 想 branch-based schema workflow + 接受 FK 限制</em> → PlanetScale</li>
</ul>
<p>兩者不互斥、有 org 用 Aurora 給 OLTP core、PlanetScale 給 newer microservices（branch workflow 帶價值）。</p>
<h2 id="相關連結">相關連結</h2>
<ul>
<li>平行 batch：→ Aurora MySQL migration playbook（同 batch、不同 paradigm）</li>
<li>上游：<a href="/blog/backend/01-database/vendors/mysql/" data-link-title="MySQL" data-link-desc="高併發網路服務常用關聯式資料庫、Vitess / PlanetScale 分片生態、GitHub / Shopify / Facebook 規模驗證">MySQL vendor overview</a> / <a href="/blog/backend/01-database/vendors/mysql/vitess-sharding/" data-link-title="MySQL Vitess Sharding：VTGate / VTTablet / VReplication / VSchema 四件套協作" data-link-desc="Vitess 不只是 MySQL sharding proxy、是 4 個 component 協作的完整 sharding 系統 — VTGate（query routing layer）、VTTablet（per-MySQL agent）、VReplication（跨 shard 資料移動）、VSchema（sharding metadata）。本文走 4 件套各自責任、keyspace / shard / tablet 架構、shard key 設計（Vindex）、配置 step-by-step、5 production 踩雷（cross-shard transaction / VStream lag / Vindex 不均勻 / resharding 切流 / VReplication 卡住）、跟自管 sharding 跟 PlanetScale 的對比">Vitess sharding 設計</a></li>
<li>跨章節：<a href="/blog/backend/06-reliability/performance-regression-gate/" data-link-title="6.13 Performance Regression Gate" data-link-desc="把效能 baseline 從一次性壓測變成持續對齊的 release gate，涵蓋 baseline 設定、判讀方法、variance 控制與退化定位">6.13 Performance Regression Gate</a> — Deploy Request workflow 對 release gate 的影響</li>
<li>既有 vendor 對照：<a href="/blog/backend/01-database/vendors/aurora/" data-link-title="AWS Aurora" data-link-desc="AWS managed PostgreSQL / MySQL、storage / compute 分離、&#43;75% 效能改善的 production 證據">Aurora vendor page</a> / <a href="https://planetscale.com/">PlanetScale 官方</a></li>
<li>方法論：<a href="/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">Migration Playbook Methodology</a>（Type E paradigm shift 結構說明）</li>
<li>官方：<a href="https://planetscale.com/docs/imports/migrate-from-mysql">PlanetScale Migration Guide</a></li>
</ul>
]]></content:encoded></item><item><title>Gitleaks</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/gitleaks/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/gitleaks/</guid><description>&lt;p>Gitleaks 是 &lt;em>純 CLI 的 OSS secret scanner&lt;/em>、MIT License、Go 寫、單一 binary 跑遍 macOS / Linux / Windows。它只做一件事 — 對 git history、working tree 或 staged changes 跑 regex + entropy + path filter 找 secret、輸出 JSON / SARIF / CSV 給下游消化。它沒有 dashboard、沒有 SaaS、沒有 cross-platform scan、也沒有 incident workflow — 這些刻意拿掉的東西是它跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/gitguardian/" data-link-title="GitGuardian" data-link-desc="Secret scanning &amp;#43; remediation SaaS、350&amp;#43; Detector &amp;#43; Validation endpoint、跨 SCM &amp;#43; SaaS（Slack / Notion）、Honeytokens decoy">GitGuardian&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &amp;#43; Secret Scanning &amp;#43; Dependency Review &amp;#43; Dependabot、跟 PR / Security tab 深度整合">GHAS Secret Scanning&lt;/a> 的核心分界。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Gitleaks 的核心定位是 &lt;em>git-aware secret scan 的 CLI 原語&lt;/em>、不是 secret 治理平台。Rule 寫在 &lt;code>.gitleaks.toml&lt;/code>、輸出走標準格式（SARIF / JSON / CSV）、跟下游 pipeline（CI、SIEM、GHAS Code Scanning）解耦。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/gitguardian/" data-link-title="GitGuardian" data-link-desc="Secret scanning &amp;#43; remediation SaaS、350&amp;#43; Detector &amp;#43; Validation endpoint、跨 SCM &amp;#43; SaaS（Slack / Notion）、Honeytokens decoy">GitGuardian&lt;/a> 比、GitGuardian 是 SaaS + dashboard + remediation workflow + validation endpoint（呼叫真實 API 驗證 secret 是否有效降 FP）+ honeytoken decoy、Gitleaks 沒有任一項 — 它只回答「這個 string 看起來像不像 secret」。GitGuardian 適合大型組織 + 預算允許 + 要跨 Slack / Jira / Notion 等 SaaS scan；Gitleaks 適合預算敏感 + 只需要 git scope + 內部已有 CI / SIEM 接 SARIF 的場景。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &amp;#43; Secret Scanning &amp;#43; Dependency Review &amp;#43; Dependabot、跟 PR / Security tab 深度整合">GHAS Secret Scanning&lt;/a> 比、GHAS 限 GitHub 平台、提供 push protection（partner pattern 在 push 前直接擋）跟 partner 自動 revoke 等深度整合、但只覆蓋 GitHub repo；Gitleaks 跨 GitHub / GitLab / Bitbucket / 自架 Gitea、CLI 跑哪都行、缺點是沒有 partner revoke 跟 push protection 要自己用 hook 接。&lt;/p></description><content:encoded><![CDATA[<p>Gitleaks 是 <em>純 CLI 的 OSS secret scanner</em>、MIT License、Go 寫、單一 binary 跑遍 macOS / Linux / Windows。它只做一件事 — 對 git history、working tree 或 staged changes 跑 regex + entropy + path filter 找 secret、輸出 JSON / SARIF / CSV 給下游消化。它沒有 dashboard、沒有 SaaS、沒有 cross-platform scan、也沒有 incident workflow — 這些刻意拿掉的東西是它跟 <a href="/blog/backend/07-security-data-protection/vendors/gitguardian/" data-link-title="GitGuardian" data-link-desc="Secret scanning &#43; remediation SaaS、350&#43; Detector &#43; Validation endpoint、跨 SCM &#43; SaaS（Slack / Notion）、Honeytokens decoy">GitGuardian</a> / <a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GHAS Secret Scanning</a> 的核心分界。</p>
<h2 id="服務定位">服務定位</h2>
<p>Gitleaks 的核心定位是 <em>git-aware secret scan 的 CLI 原語</em>、不是 secret 治理平台。Rule 寫在 <code>.gitleaks.toml</code>、輸出走標準格式（SARIF / JSON / CSV）、跟下游 pipeline（CI、SIEM、GHAS Code Scanning）解耦。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/gitguardian/" data-link-title="GitGuardian" data-link-desc="Secret scanning &#43; remediation SaaS、350&#43; Detector &#43; Validation endpoint、跨 SCM &#43; SaaS（Slack / Notion）、Honeytokens decoy">GitGuardian</a> 比、GitGuardian 是 SaaS + dashboard + remediation workflow + validation endpoint（呼叫真實 API 驗證 secret 是否有效降 FP）+ honeytoken decoy、Gitleaks 沒有任一項 — 它只回答「這個 string 看起來像不像 secret」。GitGuardian 適合大型組織 + 預算允許 + 要跨 Slack / Jira / Notion 等 SaaS scan；Gitleaks 適合預算敏感 + 只需要 git scope + 內部已有 CI / SIEM 接 SARIF 的場景。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GHAS Secret Scanning</a> 比、GHAS 限 GitHub 平台、提供 push protection（partner pattern 在 push 前直接擋）跟 partner 自動 revoke 等深度整合、但只覆蓋 GitHub repo；Gitleaks 跨 GitHub / GitLab / Bitbucket / 自架 Gitea、CLI 跑哪都行、缺點是沒有 partner revoke 跟 push protection 要自己用 hook 接。</p>
<p>跟 TruffleHog OSS 比、兩者都是 OSS CLI secret scanner、TruffleHog 強在 <em>verifier</em>（對 200+ secret type 呼叫對應 API 驗證真偽）、Gitleaks 強在 <em>rule TOML 表達力跟 SARIF output 成熟度</em>。實務上很多組織兩個一起跑、用不同的 rule 覆蓋面互補。</p>
<p>關鍵張力：<em>Allowlist 治理</em> ↔ <em>FP 噪音</em> 是 Gitleaks 客戶最大的長期問題。OSS 沒有 validation endpoint、entropy + path filter 一定會誤判 test fixture / mock token / sample config、allowlist 不持續 review 會膨脹成「全部都白名單」最後 rule 失效。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>Gitleaks 在 secret scan stack 中承擔哪一段（pre-commit / CI scan / historical audit）、哪些要外接（<a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a> rotate、<a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GHAS Code Scanning</a> 收 SARIF dashboard）</li>
<li>Custom rule 跟 allowlist 的 ownership 設計（誰寫 rule、誰核准 allowlist、定期 review 週期）</li>
<li><code>detect</code> vs <code>protect</code> 兩個子命令的職責切分、跟 pre-commit framework / CI 整合的位置</li>
<li>何時用 Gitleaks、何時升級到 <a href="/blog/backend/07-security-data-protection/vendors/gitguardian/" data-link-title="GitGuardian" data-link-desc="Secret scanning &#43; remediation SaaS、350&#43; Detector &#43; Validation endpoint、跨 SCM &#43; SaaS（Slack / Notion）、Honeytokens decoy">GitGuardian</a> / <a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GHAS Secret Scanning</a> 的取捨</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Gitleaks 部署是否健康、最少看四件事：</p>
<ul>
<li><strong>誰能改 <code>.gitleaks.toml</code></strong>：rule 跟 allowlist 是否走 Git PR review、commit message 是否帶 allowlist 原因、是否有 owner 簽核</li>
<li><strong><code>detect</code> vs <code>protect</code> 是否都接</strong>：CI 跑 <code>gitleaks detect</code>（掃 history + working tree）、pre-commit hook 跑 <code>gitleaks protect</code>（只掃 staged changes）— 缺 protect 等於 leak 進 history 才知道、缺 detect 等於既有 leak 永遠不發現</li>
<li><strong>SARIF 是否上傳 dashboard</strong>：CI output 是否 upload 到 <a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GHAS Code Scanning</a> 或內部 SIEM、不然 finding 散在 CI log 沒人看</li>
<li><strong>Allowlist 是否定期 review</strong>：allowlist entry 是否帶 expire date / reason / owner、每季是否 revisit 把過期項目刪掉、不然 allowlist 會膨脹到掩蓋真實 leak</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">Detection Coverage and Signal Governance</a> 邊界的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>Rule TOML / JSON</strong>：rule 結構是 <code>id</code> + <code>regex pattern</code> + 可選 <code>entropy threshold</code>（高熵字串通常是 secret、避開 lorem ipsum FP）+ 可選 <code>path filter</code>（限定 / 排除路徑）。預設 rule library 涵蓋 AWS / GCP / Azure / Stripe / Slack token 等 100+ pattern；organization 通常 <em>先 import 預設、再加自家 token format custom rule</em>。Custom rule 必須給 valid + invalid sample 跑 unit test、不然 regex 寫錯會大量 FP。</p>
<p><strong><code>gitleaks detect</code>（historical scan）</strong>：掃整個 git history + working tree、CI 跑、適合 <em>發現既有 leak</em>。預設掃 HEAD 到根、可用 <code>--log-opts</code> 限定 commit range 加速。實務上 PR scan 限定 <code>--log-opts=&quot;--since=...$(git merge-base origin/main HEAD)&quot;</code> 只看本 PR 新增 commit、避免每次跑整個 history 慢死。</p>
<p><strong><code>gitleaks protect</code>（pre-commit）</strong>：只掃 staged changes、pre-commit hook 跑、適合 <em>攔住未來 leak</em>。它不掃 history、意義是 <em>commit 前的最後一道閘</em>；配合 pre-commit framework（<code>pre-commit-hooks</code> 或 <a href="https://pre-commit.com/">pre-commit.com</a>）的 <code>repos: gitleaks</code> 配置直接接入。</p>
<p><strong>Report 格式（JSON / SARIF / CSV）</strong>：JSON 是 raw 結構、適合 script 處理；SARIF 是 OASIS 標準、跟 GHAS Code Scanning / 商業 SAST dashboard 共用；CSV 適合人讀 / Excel 二次處理。Production 通常 <em>CI 輸出 SARIF + 上傳 GHAS Code Scanning</em>、把 OSS scanner 的 finding 跟商業 SAST 同 dashboard、SOC 不用切多工具。</p>
<p><strong>跟 CI 整合</strong>：GitHub Actions 用 <code>gitleaks/gitleaks-action</code>、GitLab CI 用 official Docker image、Jenkins 用 binary download + shell step。CI 失敗策略要決定 — <em>block PR</em> 還是 <em>warn only</em>：嚴格組織 block PR、寬鬆組織 warn + 上 SARIF 讓 SOC 自行 triage、避免初期高 FP 阻塞所有 merge。</p>
<p><strong>跟 pre-commit framework 整合</strong>：<code>.pre-commit-config.yaml</code> 加 <code>- repo: https://github.com/gitleaks/gitleaks</code> 條目、<code>pre-commit install</code> 後每次 commit 自動跑。注意 <em>pre-commit 只在開發者 machine 跑</em>、繞過很簡單（<code>git commit --no-verify</code>）、所以一定要配 CI scan 兜底、不能只信 pre-commit。</p>
<p><strong>Allowlist 治理</strong>：<code>.gitleaks.toml</code> 裡 <code>[allowlist]</code> section 寫 <code>paths</code> / <code>regexes</code> / <code>commits</code> / <code>stopwords</code>。每個 entry 應該帶 reason（<code># allowlist reason: test fixture for OAuth flow, expire 2026-Q4</code>）、PR review 時要問「為什麼這個是 FP、什麼時候會過期」。Quarterly 跑 audit 把過期項目刪掉、避免 allowlist 變成「全部都白名單」。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Gitleaks</th>
          <th>GitGuardian</th>
          <th>GHAS Secret Scanning</th>
          <th>TruffleHog OSS</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>License</td>
          <td>MIT OSS</td>
          <td>Proprietary SaaS（free tier 限個人）</td>
          <td>GitHub Enterprise add-on</td>
          <td>AGPL OSS（Enterprise 商業）</td>
      </tr>
      <tr>
          <td>Scope</td>
          <td>Git only（history + tree + staged）</td>
          <td>Git + Slack + Jira + Notion + 自訂 source</td>
          <td>GitHub repo only</td>
          <td>Git + S3 + filesystem + more</td>
      </tr>
      <tr>
          <td>Dashboard</td>
          <td>無、輸出 SARIF / JSON 自己接</td>
          <td>內建 incident workflow + remediation</td>
          <td>GitHub Security tab</td>
          <td>無（CLI / API）</td>
      </tr>
      <tr>
          <td>Validation</td>
          <td>無（只看 regex + entropy）</td>
          <td>有（呼叫 API 驗證真偽）</td>
          <td>Partner pattern 自動 revoke</td>
          <td>有（200+ verifier）</td>
      </tr>
      <tr>
          <td>Push protection</td>
          <td>無、要自己 wire pre-commit</td>
          <td>有（透過 ggshield）</td>
          <td>有（partner pattern、push 前擋）</td>
          <td>無</td>
      </tr>
      <tr>
          <td>部署模型</td>
          <td>CLI binary、跑哪都行</td>
          <td>SaaS only</td>
          <td>GitHub SaaS / Enterprise Server</td>
          <td>CLI binary</td>
      </tr>
      <tr>
          <td>計費</td>
          <td>免費</td>
          <td>Per-developer / per-repo</td>
          <td>Per-committer</td>
          <td>免費（OSS） / 商業另計</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>OSS-friendly、預算敏感、CI / SARIF 已有</td>
          <td>跨 SaaS scan + remediation workflow</td>
          <td>GitHub-only + push protection 為主</td>
          <td>多 source + verifier 為主</td>
      </tr>
      <tr>
          <td>退場成本</td>
          <td>低 — rule TOML 可移植到 GitGuardian</td>
          <td>高 — incident history / workflow 綁定</td>
          <td>中 — SARIF 可移植但 push protection 限 GHAS</td>
          <td>低</td>
      </tr>
  </tbody>
</table>
<p>選 Gitleaks 的核心訴求：<em>OSS + 預算敏感 + 只需要 git scope + 內部 CI / SIEM 已能消化 SARIF</em>、且願意自己投入 rule / allowlist 治理。要跨 SaaS scan + incident workflow 升 GitGuardian、要 push protection + partner revoke 走 GHAS Secret Scanning。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Custom rule 寫法（regex + entropy + path）</strong>：自家 internal token 通常有特定 prefix（<code>xy_live_</code> / <code>int_token_</code>）、寫 custom rule 就是 <code>regex = '''xy_live_[A-Za-z0-9]{32}'''</code> + <code>entropy = 4.0</code> + <code>path = '''.*\.go$'''</code>。Entropy threshold 越高 FP 越少但 FN 越多、實務值 3.5–4.5 之間 tune。每個 rule 一定要在 repo 加 unit test fixture（valid + invalid sample）、CI 跑 rule 自我驗證、避免 regex 寫錯後 silent break。</p>
<p><strong>跟 SARIF + GHAS Code Scanning 整合補位</strong>：Gitleaks CI 跑完輸出 SARIF、用 <code>github/codeql-action/upload-sarif</code> 上傳到 GHAS Code Scanning。GHAS Code Scanning 不限 CodeQL 來源、任何 SARIF tool 都收。意義是 <em>OSS scanner + GHAS dashboard</em> 是預算友善組合 — 不買 GHAS Secret Scanning license、但 finding 集中在 Security tab 跟 SAST 共看。對應 <a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GHAS Advanced Security</a> 的 Code Scanning section。</p>
<p><strong>跟 Vault 自動 rotation pipeline</strong>：Gitleaks 找到 leak 不是終點、是 <em>rotation trigger</em>。CI 把 finding 推 SOAR（或自家 webhook）、SOAR 呼叫 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a> API 對該 credential type rotate（dynamic credential 直接 revoke、static secret 換新版本）、再 broadcast 給依賴該 secret 的 service rolling restart。沒這條 pipeline、Gitleaks 只是 finding 列表沒實際治理價值。</p>
<p><strong>Allowlist 治理（FP 不能無限）</strong>：OSS 沒 validation endpoint、test fixture / mock token / sample config 一定觸發 FP。allowlist 治理三原則 — <em>每個 entry 帶 reason + owner + expire date</em>、<em>PR review 必問「為什麼 FP」</em>、<em>quarterly audit 刪過期項目</em>。沒這個治理 allowlist 會在 6–12 個月內膨脹到「半個 repo 都在白名單」、那時候 rule 已經沒用、refactor 成本比一開始嚴格更高。</p>
<p><strong>跟 Trivy secret scan 重疊</strong>：<a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> 內建 secret scanner（用同樣的 regex pattern）、container image / filesystem 都掃。Gitleaks 跟 Trivy secret scan 在 <em>container build pipeline</em> 階段會重疊 — 實務分工：Gitleaks 掃 source repo（git history + working tree）、Trivy 掃 built artifact（image layer + filesystem）。兩者覆蓋不同階段、不衝突。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>FP 太多、開發者開始忽略 Gitleaks finding</strong>：rule 沒 tune entropy threshold 或 path filter — 對 high-FP rule 加 <code>entropy = 4.0</code> 跟 <code>paths = ['''!test/.*''']</code>、staging branch 跑 1 週統計 FP 再 promote</li>
<li><strong>Pre-commit 被繞過（<code>--no-verify</code>）</strong>：開發者本機跑不過直接 bypass — pre-commit 不能當唯一防線、CI <code>gitleaks detect</code> block PR 才是真實 gate</li>
<li><strong>Historical scan 太慢、CI timeout</strong>：每次掃整個 git history — PR scan 限定 <code>--log-opts=&quot;$(git merge-base origin/main HEAD)..HEAD&quot;</code> 只看本 PR commit、nightly job 才跑 full history</li>
<li><strong>SARIF 上傳失敗 / GHAS dashboard 沒 finding</strong>：<code>github/codeql-action/upload-sarif</code> 權限不足或 <code>security-events: write</code> permission 沒給 — 補 GitHub Actions permission、或改 upload 內部 SIEM</li>
<li><strong>Allowlist 膨脹、規則失效</strong>：FP 全部塞 allowlist、沒 reason 沒 expire — quarterly audit、刪過期項目、把高 FP rule 改寫成更窄的 regex 而不是 allowlist 蓋過</li>
<li><strong>既有 leak 沒被發現、新 commit 攔得很乾淨</strong>：只接 <code>protect</code> 沒接 <code>detect</code> — CI 加 <code>detect</code> job、找出 history 中已 leak 的 secret 一次性 rotate（<a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a> 自動化）</li>
<li><strong>Custom rule 寫錯、silent skip 真 leak</strong>：rule regex 沒 unit test fixture、production 才發現 — 強制 custom rule 加 valid + invalid sample、CI 跑 rule 自驗</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>跨 Slack / Jira / Notion / 自架 SaaS scan</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/gitguardian/" data-link-title="GitGuardian" data-link-desc="Secret scanning &#43; remediation SaaS、350&#43; Detector &#43; Validation endpoint、跨 SCM &#43; SaaS（Slack / Notion）、Honeytokens decoy">GitGuardian</a></td>
      </tr>
      <tr>
          <td>Push protection + partner auto-revoke</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GHAS Secret Scanning</a></td>
      </tr>
      <tr>
          <td>Validation endpoint（驗證 secret 真偽）</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/gitguardian/" data-link-title="GitGuardian" data-link-desc="Secret scanning &#43; remediation SaaS、350&#43; Detector &#43; Validation endpoint、跨 SCM &#43; SaaS（Slack / Notion）、Honeytokens decoy">GitGuardian</a> 或 TruffleHog Enterprise</td>
      </tr>
      <tr>
          <td>Honeytoken decoy 主動防禦</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/gitguardian/" data-link-title="GitGuardian" data-link-desc="Secret scanning &#43; remediation SaaS、350&#43; Detector &#43; Validation endpoint、跨 SCM &#43; SaaS（Slack / Notion）、Honeytokens decoy">GitGuardian</a>（內建 honeytoken）</td>
      </tr>
      <tr>
          <td>Container image secret scan</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a>（內建 secret scanner）</td>
      </tr>
      <tr>
          <td>Secret 找到後自動 rotate</td>
          <td>配 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a> dynamic credential</td>
      </tr>
      <tr>
          <td>SAST / SCA dashboard 整合</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GHAS Code Scanning</a>（收 SARIF）</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Gitleaks v8 跟 v7 的 rule 格式遷移細節</li>
<li>Gitleaks 內部 git odb 解析跟性能 tuning（large monorepo 加速）</li>
<li>Pre-commit framework 本身的安裝跟治理（屬開發者工作流、不在資安範圍）</li>
<li>Rotation playbook 完整實作（屬 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a> / <a href="/blog/backend/07-security-data-protection/vendors/aws-secrets-manager/" data-link-title="AWS Secrets Manager" data-link-desc="AWS 原生 secret store &#43; 內建 RDS / Redshift rotation Lambda、Resource Policy 跨帳號共享、KMS 加密">AWS Secrets Manager</a> 章節）</li>
<li>Secret 治理整體政策（屬 <a href="/blog/backend/07-security-data-protection/secrets-and-machine-credential-governance/" data-link-title="7.6 秘密管理與機器憑證治理" data-link-desc="以問題驅動方式整理 secret、token、key 與機器身份治理">Secrets Management section</a> 上層原則）</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>Gitleaks 在 07 案例庫沒有直接 vendor-level 事件、所有 secret leak case 都是 git history scan + rotation pipeline 的對照：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 Gitleaks 的關係（對照啟示）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/circleci-2023-secrets-rotation/" data-link-title="7.R7.2.3 CircleCI 2023：CI secrets 輪替壓力" data-link-desc="工程端點入侵後，CI 平台 secrets 如何成為高風險擴散點">CircleCI 2023 Secrets Rotation</a></td>
          <td>Gitleaks <code>detect</code> 跑整個 git history 找出已 leaked secret、配合 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a> rotation 流程清乾淨</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/github-oauth-2022-token-supply-chain/" data-link-title="7.R7.2.2 GitHub OAuth 2022：第三方 token 供應鏈風險" data-link-desc="第三方整合 token 被竊後，如何形成跨組織存取風險">GitHub OAuth 2022 Token Supply Chain</a></td>
          <td>Pre-commit <code>protect</code> 攔未來 leak、但對既有 leak 要 historical scan 補位、單一防線不夠</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/cases/failure-credential-rotation-without-scope/" data-link-title="7.C9 反例：憑證輪替未分 Scope" data-link-desc="憑證輪替若未分域分批，容易造成跨系統連鎖中斷。">Failure: Credential Rotation Without Scope</a></td>
          <td>Gitleaks 找出 leaked static secret 是第一步、長期解是 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a> dynamic credential 取代 long-lived secret</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/secrets-and-machine-credential-governance/" data-link-title="7.6 秘密管理與機器憑證治理" data-link-desc="以問題驅動方式整理 secret、token、key 與機器身份治理">7 章 Secrets Management section</a>、<a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">Detection Coverage and Signal Governance</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/gitguardian/" data-link-title="GitGuardian" data-link-desc="Secret scanning &#43; remediation SaaS、350&#43; Detector &#43; Validation endpoint、跨 SCM &#43; SaaS（Slack / Notion）、Honeytokens decoy">GitGuardian</a>、<a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GHAS Secret Scanning</a>、<a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a></li>
<li>下游：<a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a>（找到 leak 後 rotate）、<a href="/blog/backend/07-security-data-protection/vendors/aws-secrets-manager/" data-link-title="AWS Secrets Manager" data-link-desc="AWS 原生 secret store &#43; 內建 RDS / Redshift rotation Lambda、Resource Policy 跨帳號共享、KMS 加密">AWS Secrets Manager</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-secret-manager/" data-link-title="Google Secret Manager" data-link-desc="GCP 原生 secret store、CMEK &#43; Workload Identity Federation 整合、rotation 走自寫 Cloud Function 而非 built-in Lambda">Google Secret Manager</a> / <a href="/blog/backend/07-security-data-protection/vendors/azure-key-vault/" data-link-title="Azure Key Vault" data-link-desc="Azure 三合一 service（Secret &#43; Key &#43; Certificate）、整合 Managed Identity &#43; Entra ID RBAC、Premium tier 走 HSM">Azure Key Vault</a></li>
<li>跨類：<a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GHAS Code Scanning</a>（收 SARIF dashboard）、<a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / <a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a>（finding 進 SIEM）</li>
<li>官方：<a href="https://github.com/gitleaks/gitleaks">Gitleaks GitHub</a>、<a href="https://github.com/gitleaks/gitleaks/blob/master/README.md">Gitleaks Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>自管 Vitess → PlanetScale：Vitess component ops outsource、加 schema workflow shift</title><link>https://tarrragon.github.io/blog/backend/01-database/vendors/mysql/migrate-vitess-to-planetscale/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/01-database/vendors/mysql/migrate-vitess-to-planetscale/</guid><description>&lt;blockquote>
&lt;p>本文是跨 vendor migration playbook、cross-link 到 &lt;a href="https://tarrragon.github.io/blog/backend/01-database/vendors/mysql/vitess-sharding/" data-link-title="MySQL Vitess Sharding：VTGate / VTTablet / VReplication / VSchema 四件套協作" data-link-desc="Vitess 不只是 MySQL sharding proxy、是 4 個 component 協作的完整 sharding 系統 — VTGate（query routing layer）、VTTablet（per-MySQL agent）、VReplication（跨 shard 資料移動）、VSchema（sharding metadata）。本文走 4 件套各自責任、keyspace / shard / tablet 架構、shard key 設計（Vindex）、配置 step-by-step、5 production 踩雷（cross-shard transaction / VStream lag / Vindex 不均勻 / resharding 切流 / VReplication 卡住）、跟自管 sharding 跟 PlanetScale 的對比">Vitess sharding&lt;/a> 跟 PlanetScale。走 &lt;a href="https://tarrragon.github.io/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">Migration playbook methodology&lt;/a> Type C operational hybrid 結構。&lt;/p>&lt;/blockquote>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>元件&lt;/th>
 &lt;th>自管 Vitess&lt;/th>
 &lt;th>PlanetScale&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>VTGate&lt;/td>
 &lt;td>自己部署 + LB&lt;/td>
 &lt;td>Managed、隱藏在 PlanetScale endpoint 後&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>VTTablet&lt;/td>
 &lt;td>自己 per-MySQL deploy&lt;/td>
 &lt;td>Managed&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>VReplication&lt;/td>
 &lt;td>自己 trigger workflow&lt;/td>
 &lt;td>Managed、透過 Console / API&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>VSchema&lt;/td>
 &lt;td>自己維護（YAML / API）&lt;/td>
 &lt;td>Managed、Console UI 編輯&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>MySQL backend&lt;/td>
 &lt;td>自己 EC2 / on-prem&lt;/td>
 &lt;td>Managed (Aurora-like underlying)&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Schema migration&lt;/td>
 &lt;td>gh-ost / pt-osc 或 Vitess online DDL&lt;/td>
 &lt;td>&lt;strong>Branch + Deploy Request workflow&lt;/strong>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Failover&lt;/td>
 &lt;td>自己用 VTOrc&lt;/td>
 &lt;td>Managed&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Multi-region&lt;/td>
 &lt;td>自己配 VReplication 跨 region&lt;/td>
 &lt;td>Boost / per-region cluster&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Cost model&lt;/td>
 &lt;td>EC2 + EBS + ops headcount&lt;/td>
 &lt;td>Per-row read / write + storage&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>這條 migration 跟 &lt;a href="https://tarrragon.github.io/blog/backend/01-database/vendors/mysql/migrate-to-aurora/" data-link-title="MySQL → Aurora MySQL：storage layer 轉手到 AWS、replication / HA / backup 全部 outsource" data-link-desc="自管 MySQL → Aurora MySQL 是 Type C operational hybrid migration — wire protocol 一致、ops 責任轉到 AWS。本文走 6 維 audit（Operational High）、Aurora storage architecture 衝擊、4-phase migration、5 production 踩雷、何時維持原路線。">→ Aurora MySQL&lt;/a> 相似（self-managed → managed），但 &lt;em>target 是 Vitess-native managed&lt;/em>、保留 sharding 能力。同時加上 &lt;a href="https://tarrragon.github.io/blog/backend/01-database/vendors/mysql/migrate-to-planetscale/" data-link-title="MySQL → PlanetScale：managed Vitess &amp;#43; branch-based schema workflow 的 hybrid shift" data-link-desc="自管 MySQL → PlanetScale 加上 Vitess sharding 跟 branch-based schema workflow。本文走 6 維 audit（Paradigm &amp;#43; Operational &amp;#43; Schema 多軸）、4-phase migration、5 production 踩雷、何時不要遷。">→ PlanetScale from self-managed MySQL&lt;/a> 的 branch workflow paradigm。&lt;/p></description><content:encoded><![CDATA[<blockquote>
<p>本文是跨 vendor migration playbook、cross-link 到 <a href="/blog/backend/01-database/vendors/mysql/vitess-sharding/" data-link-title="MySQL Vitess Sharding：VTGate / VTTablet / VReplication / VSchema 四件套協作" data-link-desc="Vitess 不只是 MySQL sharding proxy、是 4 個 component 協作的完整 sharding 系統 — VTGate（query routing layer）、VTTablet（per-MySQL agent）、VReplication（跨 shard 資料移動）、VSchema（sharding metadata）。本文走 4 件套各自責任、keyspace / shard / tablet 架構、shard key 設計（Vindex）、配置 step-by-step、5 production 踩雷（cross-shard transaction / VStream lag / Vindex 不均勻 / resharding 切流 / VReplication 卡住）、跟自管 sharding 跟 PlanetScale 的對比">Vitess sharding</a> 跟 PlanetScale。走 <a href="/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">Migration playbook methodology</a> Type C operational hybrid 結構。</p></blockquote>
<table>
  <thead>
      <tr>
          <th>元件</th>
          <th>自管 Vitess</th>
          <th>PlanetScale</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>VTGate</td>
          <td>自己部署 + LB</td>
          <td>Managed、隱藏在 PlanetScale endpoint 後</td>
      </tr>
      <tr>
          <td>VTTablet</td>
          <td>自己 per-MySQL deploy</td>
          <td>Managed</td>
      </tr>
      <tr>
          <td>VReplication</td>
          <td>自己 trigger workflow</td>
          <td>Managed、透過 Console / API</td>
      </tr>
      <tr>
          <td>VSchema</td>
          <td>自己維護（YAML / API）</td>
          <td>Managed、Console UI 編輯</td>
      </tr>
      <tr>
          <td>MySQL backend</td>
          <td>自己 EC2 / on-prem</td>
          <td>Managed (Aurora-like underlying)</td>
      </tr>
      <tr>
          <td>Schema migration</td>
          <td>gh-ost / pt-osc 或 Vitess online DDL</td>
          <td><strong>Branch + Deploy Request workflow</strong></td>
      </tr>
      <tr>
          <td>Failover</td>
          <td>自己用 VTOrc</td>
          <td>Managed</td>
      </tr>
      <tr>
          <td>Multi-region</td>
          <td>自己配 VReplication 跨 region</td>
          <td>Boost / per-region cluster</td>
      </tr>
      <tr>
          <td>Cost model</td>
          <td>EC2 + EBS + ops headcount</td>
          <td>Per-row read / write + storage</td>
      </tr>
  </tbody>
</table>
<p>這條 migration 跟 <a href="/blog/backend/01-database/vendors/mysql/migrate-to-aurora/" data-link-title="MySQL → Aurora MySQL：storage layer 轉手到 AWS、replication / HA / backup 全部 outsource" data-link-desc="自管 MySQL → Aurora MySQL 是 Type C operational hybrid migration — wire protocol 一致、ops 責任轉到 AWS。本文走 6 維 audit（Operational High）、Aurora storage architecture 衝擊、4-phase migration、5 production 踩雷、何時維持原路線。">→ Aurora MySQL</a> 相似（self-managed → managed），但 <em>target 是 Vitess-native managed</em>、保留 sharding 能力。同時加上 <a href="/blog/backend/01-database/vendors/mysql/migrate-to-planetscale/" data-link-title="MySQL → PlanetScale：managed Vitess &#43; branch-based schema workflow 的 hybrid shift" data-link-desc="自管 MySQL → PlanetScale 加上 Vitess sharding 跟 branch-based schema workflow。本文走 6 維 audit（Paradigm &#43; Operational &#43; Schema 多軸）、4-phase migration、5 production 踩雷、何時不要遷。">→ PlanetScale from self-managed MySQL</a> 的 branch workflow paradigm。</p>
<p>對 <em>已花心力建 Vitess team 但 ops cost 太大</em> 的 org 來說、這條 migration 比 <em>Vitess → distributed SQL</em> 風險低、保留 sharding investment。</p>
<h2 id="為什麼是-type-c不是-type-a-或-type-e">為什麼是 Type C（不是 Type A 或 Type E）</h2>
<p>跑 <a href="/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/#%e5%af%ab%e5%89%8d%e7%9a%84-diff-dimension-audit" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">6 維 diff dimension audit</a>：</p>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>評</th>
          <th>說明</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Schema</td>
          <td>Low</td>
          <td>Vitess wire protocol + VSchema 概念一致</td>
      </tr>
      <tr>
          <td>Operational</td>
          <td>High</td>
          <td>4 個 component 的 ops 全部 outsource、branch workflow 是新 paradigm</td>
      </tr>
      <tr>
          <td>Paradigm</td>
          <td>Medium</td>
          <td>Vitess paradigm 不變、但加 branch workflow</td>
      </tr>
      <tr>
          <td>Components</td>
          <td>Low</td>
          <td>同 Vitess engine</td>
      </tr>
      <tr>
          <td>App change</td>
          <td>Low</td>
          <td>Connection string 改、無 schema rewrite</td>
      </tr>
      <tr>
          <td>Topology</td>
          <td>Low</td>
          <td>Vitess sharding 結構保留</td>
      </tr>
  </tbody>
</table>
<p>Operational = High（其他 Low / Medium） → <strong>Type C operational hybrid</strong>。Branch workflow 是 <em>Medium paradigm shift</em> 但不是 dominant — 主要工作量在 <em>operational ownership 轉移</em>。</p>
<p>跟 <a href="/blog/backend/01-database/vendors/mysql/migrate-to-planetscale/" data-link-title="MySQL → PlanetScale：managed Vitess &#43; branch-based schema workflow 的 hybrid shift" data-link-desc="自管 MySQL → PlanetScale 加上 Vitess sharding 跟 branch-based schema workflow。本文走 6 維 audit（Paradigm &#43; Operational &#43; Schema 多軸）、4-phase migration、5 production 踩雷、何時不要遷。">自管 MySQL → PlanetScale</a>（Type E paradigm shift）對比：那條 path 是 <em>no-Vitess → Vitess + branch</em>、要學 Vitess 概念 + branch；本條是 <em>已有 Vitess + 加 branch</em>、只學 branch、複雜度低很多。</p>
<h2 id="driverops-headcount--branch-workflow--vitess-feature-加速">Driver：Ops headcount + Branch workflow + Vitess feature 加速</h2>
<p>從自管 Vitess 遷 PlanetScale 的核心 driver：</p>
<p><strong>Ops headcount 削減</strong>：</p>
<ul>
<li>自管 Vitess 通常需要 <em>2-5 個 SRE/DBA 撐 production</em> —VTGate / VTTablet / VReplication / VSchema 各有議題</li>
<li>PlanetScale 把這層全部 outsource、團隊 ops headcount 可降到 &lt; 1 FTE</li>
<li>對 50-200 人 eng team、ops cost saving 是顯著 driver</li>
</ul>
<p><strong>Branch workflow paradigm</strong>：</p>
<ul>
<li>自管 Vitess 仍用 gh-ost / pt-osc 或 Vitess online DDL 跑 schema migration、是 DBA 主導</li>
<li>PlanetScale branch workflow 把 schema migration 變 <em>developer self-service</em>、開 branch / Deploy Request / merge、跟 git workflow 同節奏</li>
<li>對 <em>high-velocity engineering culture</em> 是文化升級</li>
</ul>
<p><strong>Vitess upstream feature</strong>：</p>
<ul>
<li>PlanetScale team 是 Vitess 的主要 contributor、新 feature 通常 PlanetScale 先 ship</li>
<li>自管 Vitess 升級慢、PlanetScale 用戶看到新 feature 早 3-6 個月</li>
</ul>
<p>不適合 <em>跨雲 portability priority high</em> 或 <em>strict on-prem deployment</em> 的 org — PlanetScale 是 cloud-only。</p>
<h2 id="4-phase-migration">4-phase migration</h2>
<h3 id="phase-1topology--vschema-audit">Phase 1：Topology + VSchema audit</h3>
<p>把當前自管 Vitess cluster 完整盤點：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># Vitess cluster topology</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">vtctldclient GetKeyspaces
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">vtctldclient GetShards &lt;keyspace&gt;
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">vtctldclient GetTablets
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="c1"># VSchema</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">vtctldclient GetVSchema &lt;keyspace&gt;
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="c1"># 跨 keyspace VReplication workflow</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">vtctldclient GetWorkflows</span></span></code></pre></div><p>對每個 keyspace 檢查：</p>
<ul>
<li><em>Shard 數量</em>：PlanetScale plan 對 shard 數量有 limit（Enterprise 才能超大規模）</li>
<li><em>VSchema features</em>：自管可能用 <em>PlanetScale 不支援的 Vindex</em>（custom Vindex）</li>
<li><em>Foreign key</em>：Vitess 18+（2023 末）才支援 FK、自管 Vitess 大多 &lt; 18、cluster 內已 application-enforced；遷 PlanetScale 後可選擇啟用 native FK（同 shard 內）或繼續 application enforcement</li>
<li><em>Stored procedure / trigger</em>：PlanetScale 受限、確認是否 application 依賴</li>
</ul>
<p>完成標準：寫 <em>blocker list</em>（PlanetScale 不支援的功能）+ <em>compatibility list</em>（功能對應）。</p>
<h3 id="phase-2dual-cluster--binlog-stream">Phase 2：Dual cluster + binlog stream</h3>
<p>PlanetScale 內建 <em>Vitess Connector</em>、從外部 MySQL（包括其他 Vitess cluster）binlog stream import：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 1. 用 PlanetScale CLI 建 cluster</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">pscale database create production --region us-east
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 2. Import schema（從自管 Vitess export）</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">pscale shell production main &lt; schema.sql
</span></span><span class="line"><span class="ln">6</span><span class="cl">
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="c1"># 3. 設 Vitess Connector 從自管 cluster import 資料</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="c1"># （透過 PlanetScale Console）</span></span></span></code></pre></div><p>Vitess Connector 從自管 VTTablet 的 MySQL primary 讀 binlog、寫進 PlanetScale。Lag 通常 &lt; 1 秒。</p>
<p>跑 1-2 週、確認：</p>
<ul>
<li>Schema 完整 migrate</li>
<li>VSchema 對應正確（Vindex 行為一致）</li>
<li>Lag 穩定</li>
</ul>
<h3 id="phase-3application-read-切-planetscale">Phase 3：Application read 切 PlanetScale</h3>
<p>跟 Aurora migration Phase 2 同概念。Application read query 切 PlanetScale endpoint：</p>
<ul>
<li>連 PlanetScale connection string（<code>xxx.connect.psdb.cloud</code>）</li>
<li>仍寫自管 Vitess、Vitess Connector 同步 PlanetScale</li>
</ul>
<p>跑 2-4 週、驗證：</p>
<ul>
<li>Query result 一致</li>
<li>PlanetScale read latency 接近自管（PlanetScale Boost cache 可能加速）</li>
<li>PlanetScale row read 計費跟預估一致</li>
</ul>
<h3 id="phase-4write-cutover--自管-vitess-退役">Phase 4：Write cutover + 自管 Vitess 退役</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># 1. PlanetScale 把 cluster promote 為 primary（透過 Console）</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="c1"># 透過 PlanetScale Console 啟用 production write 或用 `pscale` CLI 對應 promotion 命令</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="c1"># （CLI 命令名稱隨 pscale 版本變動、以 pscale --help 為準）</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="c1"># 2. Application 寫 connection string 切 PlanetScale</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="c1"># 自管 Vitess → PlanetScale</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="c1"># 3. Vitess Connector 反向（PlanetScale → 自管）作為 rollback buffer</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="c1"># 4. 跑 1-2 週確認、開始 decommission 自管 Vitess</span></span></span></code></pre></div><p>Decommission 自管 Vitess 是大工程：</p>
<ul>
<li>VTGate / VTTablet pods 一個個關</li>
<li>VReplication workflow 停掉</li>
<li>MySQL backend 保留作 cold backup 1-3 月、然後 EBS snapshot + terminate</li>
</ul>
<p>完成標準：所有 traffic 在 PlanetScale、自管 Vitess 資源全 release、ops headcount confirm 下降。</p>
<h2 id="5-個-production-踩雷">5 個 Production 踩雷</h2>
<h3 id="1-vschema-不完全兼容--custom-vindex-必須改">1. VSchema 不完全兼容 — Custom Vindex 必須改</h3>
<p>自管 Vitess 可能用了 <em>custom Vindex</em>（自寫 Go plugin）、PlanetScale 不支援 custom Vindex（只支援 built-in：hash / lookup_hash / unicode 等）。</p>
<p>修法：</p>
<ul>
<li>Phase 1 audit 出所有 custom Vindex</li>
<li>對每個 custom Vindex 評估能否用 built-in 替代</li>
<li>不能替代的、考慮 <em>application 層 logic 取代 Vindex</em>（application 自己算 shard key）</li>
<li>或 <em>暫不遷該 keyspace</em>、保留自管 Vitess 跑 custom Vindex keyspace、其他遷 PlanetScale</li>
</ul>
<h3 id="2-branch-workflow-訓練不到位--dba-仍用vitess-online-ddl心智模型">2. Branch workflow 訓練不到位 — DBA 仍用「Vitess online DDL」心智模型</h3>
<p>自管 Vitess team 習慣 <code>vtctldclient ApplySchema --strategy=vitess</code> 跑 online DDL、遷 PlanetScale 後仍想直接這樣 — 但 PlanetScale production branch 禁止 schema change、必須走 Deploy Request。</p>
<p>修法：</p>
<ul>
<li>Phase 3 <em>訓練步驟</em>：team 每個 DBA / SRE 都跑過完整 branch + Deploy Request workflow</li>
<li>寫 <em>team runbook</em>：production schema change must 走 branch</li>
<li>緊急 schema change（事故中）也走 branch、PlanetScale 可加速 Deploy</li>
</ul>
<h3 id="3-super-privilege-移除--自管-admin-tool-失效">3. SUPER privilege 移除 — 自管 admin tool 失效</h3>
<p>自管 Vitess 用 <code>SUPER</code> privilege 跑 admin script、PlanetScale 沒給 SUPER。常見失效：</p>
<ul>
<li>自寫 monitor script 跑 <code>SHOW SLAVE STATUS</code>、PlanetScale 抽象掉</li>
<li>自寫 backup script 跑 <code>FLUSH TABLES WITH READ LOCK</code>、PlanetScale 不允許</li>
<li>自寫 cleanup script 跑 <code>KILL QUERY</code>、PlanetScale 受限</li>
</ul>
<p>修法：</p>
<ul>
<li>Phase 1 audit 所有 admin script</li>
<li>改用 <em>PlanetScale Console / CLI / API</em> 等價操作</li>
<li>PlanetScale 提供的 monitoring 介面替代自管監控</li>
</ul>
<h3 id="4-connection-limit--planetscale-plan-比預期緊">4. Connection limit — PlanetScale plan 比預期緊</h3>
<p>PlanetScale Scaler Plan: 10K connection、Enterprise: 100K。自管 Vitess VTGate 通常設 50K-200K connection、遷 PlanetScale 後 hit limit。</p>
<p>修法：</p>
<ul>
<li>Phase 1 <em>connection forecast</em>：peak hour 多少 active connection</li>
<li>升 PlanetScale plan（Scaler Pro / Enterprise）</li>
<li>或在 application 端加 connection pool（HikariCP / pgBouncer 等價）降低 connection count</li>
</ul>
<h3 id="5-cost-model-翻盤--per-row-read-計費超預期">5. Cost model 翻盤 — Per-row read 計費超預期</h3>
<p>PlanetScale 計費是 <em>per row read / written</em>。自管 Vitess cost = EC2 + EBS（線性 with infrastructure scale）。遷 PlanetScale 後計費跟 <em>application access pattern</em> 直接相關。</p>
<p>常見 surprise：</p>
<ul>
<li>Heavy analytics query（COUNT *、aggregation）讀大量 row、計費高</li>
<li>N+1 query pattern（application 跑很多小 SELECT）讀很多 row、計費高</li>
<li>Read-heavy workload 沒 Boost cache、每次 query 都 hit billing</li>
</ul>
<p>修法：</p>
<ul>
<li>Phase 1 <em>cost forecast</em>：用 <code>pscale analytics</code> 預估 row read / write 量、估算月帳</li>
<li>Phase 2 期間實際對 PlanetScale 跑 traffic、看實際 billing</li>
<li>Heavy analytics 改 <em>材料化 view</em> / <em>async aggregation</em>、不是每次 query</li>
<li>高 read frequency 開 Boost cache（額外 cost、但比 row read 便宜）</li>
</ul>
<h2 id="capability-mapping">Capability mapping</h2>
<table>
  <thead>
      <tr>
          <th>自管 Vitess</th>
          <th>PlanetScale 對應</th>
          <th>兼容度</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>VTGate</td>
          <td>PlanetScale endpoint</td>
          <td>100%</td>
      </tr>
      <tr>
          <td>VTTablet</td>
          <td>PlanetScale managed</td>
          <td>100%</td>
      </tr>
      <tr>
          <td>VReplication</td>
          <td>PlanetScale Console + Deploy Request</td>
          <td>90%（內部使用更受限）</td>
      </tr>
      <tr>
          <td>VSchema</td>
          <td>PlanetScale Console / pscale CLI</td>
          <td>95%（custom Vindex 不支援）</td>
      </tr>
      <tr>
          <td>Vitess online DDL</td>
          <td>Deploy Request workflow</td>
          <td>不同 paradigm、功能等價</td>
      </tr>
      <tr>
          <td>Backup</td>
          <td>PlanetScale 自動</td>
          <td>100%（且更好）</td>
      </tr>
      <tr>
          <td>Failover</td>
          <td>PlanetScale 自動</td>
          <td>100%</td>
      </tr>
      <tr>
          <td>Multi-region</td>
          <td>PlanetScale Boost / per-region cluster</td>
          <td>90%</td>
      </tr>
      <tr>
          <td>Custom plugin</td>
          <td>不支援</td>
          <td>0%</td>
      </tr>
      <tr>
          <td>SUPER privilege</td>
          <td>不支援</td>
          <td>0%</td>
      </tr>
  </tbody>
</table>
<h2 id="容量與成本對照">容量與成本對照</h2>
<p>對 200 人 eng team 用自管 Vitess（10 shard、20 TB 資料、50K WPS）：</p>
<table>
  <thead>
      <tr>
          <th>項目</th>
          <th>自管 Vitess（自管 EC2）</th>
          <th>PlanetScale Scaler Pro</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Infrastructure</td>
          <td>~$15K-25K / mo（EC2 + EBS + LB）</td>
          <td>Variable（per row read / write）</td>
      </tr>
      <tr>
          <td>Ops headcount</td>
          <td>2-3 FTE × $150K / yr = $300K-450K / yr</td>
          <td>&lt; 0.5 FTE × $150K = $75K / yr</td>
      </tr>
      <tr>
          <td>Vitess upgrade cost</td>
          <td>每年 1-2 個 SRE × 2 週</td>
          <td>自動</td>
      </tr>
      <tr>
          <td>Per-row read</td>
          <td>不計費</td>
          <td>$1 per 1B row read</td>
      </tr>
      <tr>
          <td>Per-row written</td>
          <td>不計費</td>
          <td>$1.50 per 1M row write</td>
      </tr>
      <tr>
          <td>Storage</td>
          <td>EBS $2K-5K / mo</td>
          <td>$1.50 / GB / mo</td>
      </tr>
      <tr>
          <td><strong>總帳</strong></td>
          <td>~$400K-550K / yr</td>
          <td>~$200K-350K / yr（看 traffic）</td>
      </tr>
  </tbody>
</table>
<p>對中型規模、PlanetScale 通常 break-even 或更便宜。對極大規模（&gt; 200K WPS / &gt; 100 TB）PlanetScale Enterprise 需要 commit pricing、不一定划算。</p>
<h2 id="何時不要遷">何時不要遷</h2>
<ul>
<li><strong>跨雲 / on-prem 是 requirement</strong>：PlanetScale cloud-only</li>
<li><strong>Custom Vindex / 特殊 plugin</strong> 大量使用：兼容度低、改造工作量大</li>
<li><strong>規模極大</strong> &gt; 500K WPS / &gt; 200 TB：PlanetScale plan 對應 Enterprise commit、議價辛苦</li>
<li><strong>強合規 / 資料主權限制</strong>：金融 / 政府 / 醫療場景、PlanetScale 不一定能 cover compliance</li>
<li><strong>既有 Vitess team 強 + ops cost 低</strong>：如果 ops 已經精實、不必為 outsource 而 outsource</li>
</ul>
<h2 id="跟其他模組整合">跟其他模組整合</h2>
<h3 id="跟-vitess-sharding">跟 <a href="/blog/backend/01-database/vendors/mysql/vitess-sharding/" data-link-title="MySQL Vitess Sharding：VTGate / VTTablet / VReplication / VSchema 四件套協作" data-link-desc="Vitess 不只是 MySQL sharding proxy、是 4 個 component 協作的完整 sharding 系統 — VTGate（query routing layer）、VTTablet（per-MySQL agent）、VReplication（跨 shard 資料移動）、VSchema（sharding metadata）。本文走 4 件套各自責任、keyspace / shard / tablet 架構、shard key 設計（Vindex）、配置 step-by-step、5 production 踩雷（cross-shard transaction / VStream lag / Vindex 不均勻 / resharding 切流 / VReplication 卡住）、跟自管 sharding 跟 PlanetScale 的對比">Vitess sharding</a></h3>
<p>本 migration 保留 Vitess sharding 概念、application code 視角幾乎不變。Phase 1 audit 是 <em>Vitess concept 對應 PlanetScale concept</em>、不是 <em>拆 Vitess 換 distributed SQL</em>。</p>
<h3 id="跟--planetscale-from-self-managed-mysql">跟 <a href="/blog/backend/01-database/vendors/mysql/migrate-to-planetscale/" data-link-title="MySQL → PlanetScale：managed Vitess &#43; branch-based schema workflow 的 hybrid shift" data-link-desc="自管 MySQL → PlanetScale 加上 Vitess sharding 跟 branch-based schema workflow。本文走 6 維 audit（Paradigm &#43; Operational &#43; Schema 多軸）、4-phase migration、5 production 踩雷、何時不要遷。">→ PlanetScale (from self-managed MySQL)</a></h3>
<p>本 migration 是 <em>Vitess → PlanetScale</em>、前者是 <em>MySQL → PlanetScale</em>。差異：</p>
<ul>
<li><em>MySQL → PlanetScale</em> (Type E)：要學 Vitess 概念 + branch workflow + FK 處理</li>
<li><em>Vitess → PlanetScale</em> (Type C)：只學 branch workflow + ops outsource、保留所有 Vitess investment</li>
</ul>
<p>選哪條 path 取決於起點。</p>
<h3 id="跟-major-version-upgrade">跟 <a href="/blog/backend/01-database/vendors/mysql/major-version-upgrade/" data-link-title="MySQL 5.7 → 8.0 Major Version Upgrade：character set / authentication / atomic DDL 三條 paradigm 同時換軌" data-link-desc="MySQL 5.7 → 8.0 三條 default 同時改：charset utf8 → utf8mb4、auth plugin native_password → caching_sha2_password、DDL non-atomic → atomic。本文走 Type E paradigm shift 結構、6 維 audit、4-phase upgrade、5 production 踩雷、何時不要升級。">Major Version Upgrade</a></h3>
<p>從自管 Vitess 上 MySQL 5.7 遷 PlanetScale 也是 <em>同時跨 major version</em>（PlanetScale 跑 8.0+ Vitess）。Application 必須同時處理 5.7 → 8.0 paradigm shift（charset / auth）。</p>
<h2 id="相關連結">相關連結</h2>
<ul>
<li><a href="/blog/backend/01-database/vendors/mysql/" data-link-title="MySQL" data-link-desc="高併發網路服務常用關聯式資料庫、Vitess / PlanetScale 分片生態、GitHub / Shopify / Facebook 規模驗證">MySQL vendor overview</a></li>
<li><a href="/blog/backend/01-database/vendors/mysql/vitess-sharding/" data-link-title="MySQL Vitess Sharding：VTGate / VTTablet / VReplication / VSchema 四件套協作" data-link-desc="Vitess 不只是 MySQL sharding proxy、是 4 個 component 協作的完整 sharding 系統 — VTGate（query routing layer）、VTTablet（per-MySQL agent）、VReplication（跨 shard 資料移動）、VSchema（sharding metadata）。本文走 4 件套各自責任、keyspace / shard / tablet 架構、shard key 設計（Vindex）、配置 step-by-step、5 production 踩雷（cross-shard transaction / VStream lag / Vindex 不均勻 / resharding 切流 / VReplication 卡住）、跟自管 sharding 跟 PlanetScale 的對比">Vitess Sharding</a>（self-managed source）</li>
<li><a href="/blog/backend/01-database/vendors/mysql/migrate-to-planetscale/" data-link-title="MySQL → PlanetScale：managed Vitess &#43; branch-based schema workflow 的 hybrid shift" data-link-desc="自管 MySQL → PlanetScale 加上 Vitess sharding 跟 branch-based schema workflow。本文走 6 維 audit（Paradigm &#43; Operational &#43; Schema 多軸）、4-phase migration、5 production 踩雷、何時不要遷。">→ PlanetScale from self-managed MySQL</a>（不同起點）</li>
<li><a href="/blog/backend/01-database/vendors/mysql/migrate-to-aurora/" data-link-title="MySQL → Aurora MySQL：storage layer 轉手到 AWS、replication / HA / backup 全部 outsource" data-link-desc="自管 MySQL → Aurora MySQL 是 Type C operational hybrid migration — wire protocol 一致、ops 責任轉到 AWS。本文走 6 維 audit（Operational High）、Aurora storage architecture 衝擊、4-phase migration、5 production 踩雷、何時維持原路線。">→ Aurora MySQL</a>（另一條 self-managed → managed path）</li>
<li><a href="/blog/backend/01-database/vendors/mysql/major-version-upgrade/" data-link-title="MySQL 5.7 → 8.0 Major Version Upgrade：character set / authentication / atomic DDL 三條 paradigm 同時換軌" data-link-desc="MySQL 5.7 → 8.0 三條 default 同時改：charset utf8 → utf8mb4、auth plugin native_password → caching_sha2_password、DDL non-atomic → atomic。本文走 Type E paradigm shift 結構、6 維 audit、4-phase upgrade、5 production 踩雷、何時不要升級。">Major Version Upgrade</a>（5.7 → 8.0 同期考量）</li>
<li>方法論：<a href="/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">Migration Playbook Methodology</a>（Type C operational hybrid）</li>
<li>官方：<a href="https://planetscale.com/docs/imports">PlanetScale Migration Guide</a> / <a href="https://github.com/planetscale/vitess-operator">Vitess Operator</a></li>
</ul>
]]></content:encoded></item><item><title>Immuta</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/immuta/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/immuta/</guid><description>&lt;p>Immuta 是 &lt;em>Universal Data Access Platform&lt;/em>、定位是 &lt;em>跨多 data warehouse 統一的 query-time access control + masking 抽象層&lt;/em>。它解的問題是 &lt;em>同一份 policy 要同時在 Snowflake、Databricks、BigQuery、Redshift、Synapse 上生效&lt;/em>、不必到每個 warehouse 內逐表寫 native RLS / masking。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/google-dlp/" data-link-title="Google DLP" data-link-desc="GCP 原生 Sensitive Data Protection：infoType discovery &amp;#43; transformation (mask / FPE / tokenize / k-anonymity)、整合 BigQuery / GCS / Cloud SQL">Google DLP&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/cloud-data-policy/" data-link-title="Cloud-native Data Policy (BigQuery &amp;#43; S3)" data-link-desc="BigQuery column / row-level security &amp;#43; S3 bucket policy &amp;#43; Access Points &amp;#43; Macie、雲端原生資料層 access control、跟 DLP / Purview 互補">Cloud-native data policy&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/microsoft-purview/" data-link-title="Microsoft Purview" data-link-desc="Microsoft 跨 M365 / Azure / endpoint 的 data governance &amp;#43; information protection &amp;#43; DLP &amp;#43; insider risk 統合平台、label-driven">Microsoft Purview&lt;/a> 的差異在 &lt;em>policy abstraction layer + query-time enforcement + ABAC scale&lt;/em>、偵測或 classification 層面相近。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Immuta 核心定位是 &lt;em>data security platform&lt;/em>、以 &lt;em>Data Policy + Subject Policy&lt;/em> 為 first-class concept、走 &lt;em>Attribute-Based Access Control (ABAC)&lt;/em> 模型。底層機制是 &lt;em>Native Query Plan Rewriter&lt;/em> — analyst 寫 SQL 後 Immuta 攔截、解析 policy、把 row filter 跟 column mask &lt;em>translate 成各 warehouse native primitive&lt;/em>（Snowflake row access policy / dynamic masking、BigQuery RLS、Databricks Unity Catalog policy）後再交給 warehouse 執行。Performance 接近 native、不是 proxy 中轉。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/cloud-data-policy/" data-link-title="Cloud-native Data Policy (BigQuery &amp;#43; S3)" data-link-desc="BigQuery column / row-level security &amp;#43; S3 bucket policy &amp;#43; Access Points &amp;#43; Macie、雲端原生資料層 access control、跟 DLP / Purview 互補">Cloud-native data policy&lt;/a> 比、cloud-native（Snowflake Horizon / BigQuery column-level security / Redshift dynamic masking）限單一雲、政策語意散落在各 warehouse；Immuta 走 &lt;em>policy abstraction&lt;/em>、寫一次 policy 對多 warehouse 生效。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/microsoft-purview/" data-link-title="Microsoft Purview" data-link-desc="Microsoft 跨 M365 / Azure / endpoint 的 data governance &amp;#43; information protection &amp;#43; DLP &amp;#43; insider risk 統合平台、label-driven">Microsoft Purview&lt;/a> 比、Purview 強在 Office docs label + endpoint DLP、Immuta 強在 &lt;em>data warehouse query-time access control&lt;/em>、兩者場景不重疊。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/google-dlp/" data-link-title="Google DLP" data-link-desc="GCP 原生 Sensitive Data Protection：infoType discovery &amp;#43; transformation (mask / FPE / tokenize / k-anonymity)、整合 BigQuery / GCS / Cloud SQL">Google DLP&lt;/a> 比、DLP 是 &lt;em>classification / discovery / redaction service&lt;/em>、Immuta 是 &lt;em>access policy enforcement&lt;/em>、前者找敏感資料、後者管誰能看到。&lt;/p></description><content:encoded><![CDATA[<p>Immuta 是 <em>Universal Data Access Platform</em>、定位是 <em>跨多 data warehouse 統一的 query-time access control + masking 抽象層</em>。它解的問題是 <em>同一份 policy 要同時在 Snowflake、Databricks、BigQuery、Redshift、Synapse 上生效</em>、不必到每個 warehouse 內逐表寫 native RLS / masking。跟 <a href="/blog/backend/07-security-data-protection/vendors/google-dlp/" data-link-title="Google DLP" data-link-desc="GCP 原生 Sensitive Data Protection：infoType discovery &#43; transformation (mask / FPE / tokenize / k-anonymity)、整合 BigQuery / GCS / Cloud SQL">Google DLP</a> / <a href="/blog/backend/07-security-data-protection/vendors/cloud-data-policy/" data-link-title="Cloud-native Data Policy (BigQuery &#43; S3)" data-link-desc="BigQuery column / row-level security &#43; S3 bucket policy &#43; Access Points &#43; Macie、雲端原生資料層 access control、跟 DLP / Purview 互補">Cloud-native data policy</a> / <a href="/blog/backend/07-security-data-protection/vendors/microsoft-purview/" data-link-title="Microsoft Purview" data-link-desc="Microsoft 跨 M365 / Azure / endpoint 的 data governance &#43; information protection &#43; DLP &#43; insider risk 統合平台、label-driven">Microsoft Purview</a> 的差異在 <em>policy abstraction layer + query-time enforcement + ABAC scale</em>、偵測或 classification 層面相近。</p>
<h2 id="服務定位">服務定位</h2>
<p>Immuta 核心定位是 <em>data security platform</em>、以 <em>Data Policy + Subject Policy</em> 為 first-class concept、走 <em>Attribute-Based Access Control (ABAC)</em> 模型。底層機制是 <em>Native Query Plan Rewriter</em> — analyst 寫 SQL 後 Immuta 攔截、解析 policy、把 row filter 跟 column mask <em>translate 成各 warehouse native primitive</em>（Snowflake row access policy / dynamic masking、BigQuery RLS、Databricks Unity Catalog policy）後再交給 warehouse 執行。Performance 接近 native、不是 proxy 中轉。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/cloud-data-policy/" data-link-title="Cloud-native Data Policy (BigQuery &#43; S3)" data-link-desc="BigQuery column / row-level security &#43; S3 bucket policy &#43; Access Points &#43; Macie、雲端原生資料層 access control、跟 DLP / Purview 互補">Cloud-native data policy</a> 比、cloud-native（Snowflake Horizon / BigQuery column-level security / Redshift dynamic masking）限單一雲、政策語意散落在各 warehouse；Immuta 走 <em>policy abstraction</em>、寫一次 policy 對多 warehouse 生效。跟 <a href="/blog/backend/07-security-data-protection/vendors/microsoft-purview/" data-link-title="Microsoft Purview" data-link-desc="Microsoft 跨 M365 / Azure / endpoint 的 data governance &#43; information protection &#43; DLP &#43; insider risk 統合平台、label-driven">Microsoft Purview</a> 比、Purview 強在 Office docs label + endpoint DLP、Immuta 強在 <em>data warehouse query-time access control</em>、兩者場景不重疊。跟 <a href="/blog/backend/07-security-data-protection/vendors/google-dlp/" data-link-title="Google DLP" data-link-desc="GCP 原生 Sensitive Data Protection：infoType discovery &#43; transformation (mask / FPE / tokenize / k-anonymity)、整合 BigQuery / GCS / Cloud SQL">Google DLP</a> 比、DLP 是 <em>classification / discovery / redaction service</em>、Immuta 是 <em>access policy enforcement</em>、前者找敏感資料、後者管誰能看到。</p>
<p>關鍵張力：<em>多 warehouse 統一治理價值</em> ↔ <em>商業 SaaS 成本</em>。單一 warehouse（純 Snowflake）客戶 2024+ 用 Snowflake Horizon native 多半夠用、Immuta 進場理由是 <em>Snowflake + Databricks + BigQuery 並存</em>、且 analyst 數量大到 ABAC 比 RBAC 划算。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>Immuta 在 data platform 承擔哪一段（query-time access control / masking / ABAC）、跟 <a href="/blog/backend/07-security-data-protection/vendors/cloud-data-policy/" data-link-title="Cloud-native Data Policy (BigQuery &#43; S3)" data-link-desc="BigQuery column / row-level security &#43; S3 bucket policy &#43; Access Points &#43; Macie、雲端原生資料層 access control、跟 DLP / Purview 互補">Cloud-native data policy</a> 的取捨</li>
<li>Data Policy / Subject Policy / ABAC 的 ownership 設計（Data steward / Compliance / Data engineering 各管什麼）</li>
<li>Query Plan Rewriter 的工作模式跟 native warehouse policy 的 fallback 邊界</li>
<li>何時用 Immuta、何時走 cloud-native policy / Privacera / Snowflake Horizon 的取捨</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Immuta deployment 是否健康、最少看四件事：</p>
<ul>
<li><strong>Data Source registration coverage</strong>：哪些 warehouse / schema / table 已註冊到 Immuta、是否有 <em>uncovered shadow path</em>（analyst 還能繞過 Immuta 直連 warehouse 拿 raw data）— 沒覆蓋等於有 backdoor</li>
<li><strong>Subject Policy 跟 IdP attribute 對齊</strong>：user attribute（部門、地理、clearance）從哪個 IdP / HRIS pull、attribute 變更（離職 / 換部門）多快 propagate 到 Immuta、policy 是否真的用 attribute 而不是退化成「user A、user B」直接 grant</li>
<li><strong>Policy-as-code 跟 review flow</strong>：Data Policy 是 UI 改還是走 Git PR review、policy change 是否經 staging tenant 驗證、有沒有 <em>break-glass</em> 流程</li>
<li><strong>Audit log 串到 SIEM</strong>：Immuta query audit 是否進 <a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / <a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a>、query pattern 異常（同一 user 大量觸發 masking、跨 schema scan）有無 alert</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/07-security-data-protection/data-protection-and-masking-governance/" data-link-title="7.4 資料保護與遮罩治理" data-link-desc="以問題驅動方式整理資料分級、遮罩、匯出與備份治理">Data Protection by Design</a> 邊界的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>Data Source registration</strong>：把 warehouse 內的 schema / table 註冊成 Immuta <em>Data Source</em>、Immuta 透過 service account 連 warehouse、拉 metadata + 註冊到 policy plane。Snowflake / Databricks / BigQuery / Redshift / Synapse / Starburst 是 first-class、其他 warehouse 走 JDBC connector。註冊後 analyst 改透過 Immuta 取得的 <em>projected view</em> 查詢、不直連原始 table。</p>
<p><strong>Data Policy（row / column / masking）</strong>：policy 三類 — <em>Subscription Policy</em>（誰能訂閱 data source）、<em>Row-level Policy</em>（filter 哪些 row）、<em>Masking Policy</em>（column 值如何呈現：hash / null / regex redact / k-anonymity / differential privacy noise）。可走 UI 設定、也可走 Immuta CLI / API 寫成 YAML 進 Git PR review，後者是 mature deployment 的標配。</p>
<p><strong>Subject Policy + ABAC</strong>：policy 用 <em>user attribute</em> 寫（<code>department == 'finance' AND region == 'EU' AND clearance &gt;= 'restricted'</code>）、不是 user / role 直接 grant。Attribute 從 IdP（<a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a> / Azure AD）/ HRIS（Workday）pull、Immuta Identity Manager 同步。ABAC 的價值在 scaling — 5000 個 analyst 用 RBAC 要管 hundreds of role、用 ABAC 寫 20 條 policy 涵蓋全部組合。</p>
<p><strong>Query Plan Rewriter</strong>：核心機制。analyst 對 Immuta data source 寫 SQL → Immuta 解析 query plan + 套用 user 對應 policy → 翻譯成 warehouse native primitive（Snowflake row access policy + dynamic masking function、BigQuery RLS、Databricks Unity Catalog policy）→ 交給 warehouse 執行。Performance 接近 native、不是 query proxy。意義是 <em>policy 抽象在 Immuta、執行在 warehouse</em>、不引入額外資料路徑。</p>
<p><strong>Identity Manager 跟 IdP integration</strong>：Immuta 串 <a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a> / Azure AD / Keycloak、用 SCIM / SAML / OIDC sync user + attribute。注意 <em>attribute propagation lag</em> — 員工換部門、HRIS 更新後多久反映到 Immuta policy 決策、production deployment 常見 trap 是 propagation 不及時、離職員工 attribute 還在、Subject Policy 仍判通過。</p>
<p><strong>Audit log</strong>：每個 query 都產 audit event（user、attribute snapshot、data source、applied policy、masked column、row count）、串到 <a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / <a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-security-operations/" data-link-title="Google Security Operations" data-link-desc="Google 雲原生 SIEM &#43; SOAR &#43; Mandiant threat intel 三合一（前 Chronicle）、UDM &#43; YARA-L、fixed-price by data tier、PB-scale 友善">Google Security Operations</a> 做 detection。對應 <a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">Detection Coverage and Signal Governance</a> — query audit 是 <em>data warehouse layer 的 first-class signal</em>。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Immuta</th>
          <th>Privacera</th>
          <th>Cloud-native data policy</th>
          <th>Snowflake Horizon native</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>計費模型</td>
          <td>SaaS、按 data source / module / user</td>
          <td>SaaS、按 data source / user</td>
          <td>內含於 warehouse 計費</td>
          <td>內含於 Snowflake credit</td>
      </tr>
      <tr>
          <td>多 warehouse 統一</td>
          <td>強 — abstraction layer、policy 寫一次</td>
          <td>強 — 類似定位、Apache Ranger 血脈</td>
          <td>弱 — 各 warehouse 各寫各的</td>
          <td>無 — 限 Snowflake</td>
      </tr>
      <tr>
          <td>ABAC 成熟度</td>
          <td>強 — IdP / HRIS attribute 為一等公民</td>
          <td>強 — Ranger ABAC 模型</td>
          <td>中 — 各 warehouse 支援不一</td>
          <td>中 — Snowflake tag-based</td>
      </tr>
      <tr>
          <td>Query 執行模型</td>
          <td>Native Query Plan Rewrite（接近 native）</td>
          <td>類似 rewrite + proxy 混合</td>
          <td>Native（warehouse 內建）</td>
          <td>Native</td>
      </tr>
      <tr>
          <td>Differential privacy</td>
          <td>內建 aggregate noise / k-anonymity</td>
          <td>部分支援</td>
          <td>一般無</td>
          <td>一般無</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>多 warehouse + analyst 數量大 + 合規重</td>
          <td>多 warehouse + Hadoop 遺產 + Ranger 熟</td>
          <td>單一雲 / 預算敏感 / 中小規模</td>
          <td>純 Snowflake + 想避免額外 vendor</td>
      </tr>
      <tr>
          <td>退場成本</td>
          <td>高 — policy / data source 數量多</td>
          <td>高 — 類似</td>
          <td>低 — policy 已在 warehouse 內</td>
          <td>低 — 不換 vendor</td>
      </tr>
  </tbody>
</table>
<p>選 Immuta 的核心訴求：<em>多 warehouse 並存 + ABAC 規模化 + 合規（HIPAA / GDPR / FedRAMP）要求 query-time enforcement + audit</em>、且能承擔商業 SaaS license 跟 policy-as-code lifecycle 投入。單一 Snowflake / 預算敏感 / 中小 data team 直接走 Snowflake Horizon 更划算。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>ABAC scaling beyond RBAC</strong>：RBAC 在 hundreds-of-analyst 規模會退化成 role explosion（finance-eu-restricted-q1、finance-eu-restricted-q2…）。ABAC 把 role 拆成 attribute 組合、policy 寫一次 <code>department == 'finance' AND region == 'EU'</code>、新 analyst 加入只要 attribute 對、自動繼承。實作 trap 是 attribute 設計 — 不能用 free-form string、要有 controlled vocabulary + HRIS 為 SSoT。</p>
<p><strong>Differential privacy 跟 aggregate query noise</strong>：Immuta 支援對 aggregate query（COUNT / SUM / AVG）注入 <em>Laplace / Gaussian noise</em> 避免重識別（re-identification）攻擊。場景是醫療 / 政府統計、analyst 看 aggregate 不該能逆推個人記錄。要決定 <em>epsilon</em>（privacy budget）— epsilon 小 noise 大、analyst 抱怨數字不準；epsilon 大 noise 小、privacy 保障弱。</p>
<p><strong>跟 dbt / Airflow 整合</strong>：data pipeline 內的 transform 也該受 policy 控制 — dbt 模型生成的 derived table 註冊回 Immuta、policy 自動繼承。Airflow DAG 用 service account 走 Immuta 的 <em>system account exemption</em> 路徑、跟 analyst query 區分 audit 來源。實務上是 <em>pipeline-aware policy</em> — 知道哪個 job 是 trusted ETL、哪個是 ad-hoc query。</p>
<p><strong>Native integration 細節</strong>：Snowflake 走 row access policy + dynamic masking function；Databricks 走 Unity Catalog row filter + column mask；BigQuery 走 authorized view + RLS；Redshift 走 RLS + dynamic data masking。Immuta 寫的 policy 翻譯成各 warehouse native object、可在 warehouse console 看到 generated artifact。Native integration 失效時（warehouse API rate limit / schema drift）會 fallback 到 <em>deny-by-default</em>、不是 silent allow。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Analyst 直連 warehouse 繞過 Immuta</strong>：service account 沒收緊、analyst 用 warehouse native credential 直查 — 收 warehouse user direct access、改強制走 Immuta projected view、用 warehouse network policy 鎖 IP</li>
<li><strong>Attribute propagation lag 導致離職員工仍能查</strong>：HRIS → Immuta sync 週期太長 — 縮 sync 頻率、配合 <a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a> deprovisioning webhook 即時觸發 attribute revoke</li>
<li><strong>Policy 改完 production 出現 mass deny</strong>：UI 直改、沒走 staging tenant 驗證 — policy 進 Git、PR review、staging 跑代表性 query suite、roll-forward 監控 deny rate</li>
<li><strong>Query performance 退化</strong>：複雜 row filter + masking 翻譯後的 warehouse plan 沒命中 index — 用 Immuta query analyzer 看 generated SQL、調整 policy 寫法或加 warehouse-side optimization</li>
<li><strong>Audit log 沒進 SIEM</strong>：Immuta audit export 沒設、event sink 斷線 — 補 <a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> HEC / Elastic ingest pipeline、加 lag alert</li>
<li><strong>計費暴衝</strong>：data source 數量爆炸（每張 table 註冊一次）、user count 估錯 — 用 Immuta usage dashboard 看 module-by-module、合併小 table 到 schema-level policy</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>單一雲 / 預算敏感 / 中小 data team</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/cloud-data-policy/" data-link-title="Cloud-native Data Policy (BigQuery &#43; S3)" data-link-desc="BigQuery column / row-level security &#43; S3 bucket policy &#43; Access Points &#43; Macie、雲端原生資料層 access control、跟 DLP / Purview 互補">Cloud-native data policy</a></td>
      </tr>
      <tr>
          <td>純 Snowflake、不想引額外 vendor</td>
          <td>Snowflake Horizon native（內建 row access policy + dynamic masking）</td>
      </tr>
      <tr>
          <td>Hadoop / Ranger 遺產重</td>
          <td>Privacera（Apache Ranger 商業化、跟 Hadoop ecosystem 整合）</td>
      </tr>
      <tr>
          <td>敏感資料 discovery / classification</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/google-dlp/" data-link-title="Google DLP" data-link-desc="GCP 原生 Sensitive Data Protection：infoType discovery &#43; transformation (mask / FPE / tokenize / k-anonymity)、整合 BigQuery / GCS / Cloud SQL">Google DLP</a> / <a href="/blog/backend/07-security-data-protection/vendors/microsoft-purview/" data-link-title="Microsoft Purview" data-link-desc="Microsoft 跨 M365 / Azure / endpoint 的 data governance &#43; information protection &#43; DLP &#43; insider risk 統合平台、label-driven">Microsoft Purview</a></td>
      </tr>
      <tr>
          <td>Office docs / endpoint DLP</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/microsoft-purview/" data-link-title="Microsoft Purview" data-link-desc="Microsoft 跨 M365 / Azure / endpoint 的 data governance &#43; information protection &#43; DLP &#43; insider risk 統合平台、label-driven">Microsoft Purview</a></td>
      </tr>
      <tr>
          <td>Object storage / file-level policy</td>
          <td>Cloud-native IAM + bucket policy（Immuta 不管 raw S3 / GCS）</td>
      </tr>
      <tr>
          <td>Query audit 後的 detection</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-security-operations/" data-link-title="Google Security Operations" data-link-desc="Google 雲原生 SIEM &#43; SOAR &#43; Mandiant threat intel 三合一（前 Chronicle）、UDM &#43; YARA-L、fixed-price by data tier、PB-scale 友善">Google Security Operations</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Immuta CLI / API 完整語法 reference、policy YAML schema 細節</li>
<li>各 warehouse 的 native policy primitive 對應細節（Snowflake row access policy / Databricks Unity Catalog policy 語法）</li>
<li>Differential privacy 數學（epsilon / delta / Laplace mechanism 證明）</li>
<li>Hadoop ecosystem 整合（HDFS / Hive / Impala — 屬 Privacera 主場）</li>
<li>Object storage / file-level access control（屬 cloud IAM）</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>Immuta 在 07 案例庫沒有直接 vendor-level 事件、但所有 data warehouse credential / access 相關 case 都是 query-time enforcement 的對照：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 Immuta 的關係（對照啟示）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/data-exfiltration/snowflake-2024-credential-abuse/" data-link-title="7.R7.4.2 Snowflake 2024：憑證濫用與資料竊取" data-link-desc="外洩憑證與 MFA 缺口如何在資料平台形成高風險外送事件">Snowflake 2024 Credential Abuse</a></td>
          <td>Immuta query-time ABAC 在 credential 外洩後仍限制 attacker 看到的 row + masked column、減 blast radius；對照啟示是「multi-tenant data warehouse 必須有 query-time 層」、不能只靠 credential / network 層</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/data-exfiltration/mailchimp-2023-support-tool-abuse/" data-link-title="7.R7.4.4 Mailchimp 2023：支援工具路徑與客戶資料風險" data-link-desc="社交工程進入客服工具後，如何形成特定客戶資料存取風險">Mailchimp 2023 Support Tool Abuse</a></td>
          <td>Immuta 對 support tool 連到 backend warehouse 的 query 套 attribute-based filter、限 support user 只看授權 tenant、避免 internal tool 變 cross-tenant 提權路徑</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/data-exfiltration/lastpass-2022-backup-chain/" data-link-title="7.R7.4.1 LastPass 2022：備份路徑與鏈式入侵" data-link-desc="開發環境資訊外流如何沿著備份路徑擴大成資料風險">LastPass 2022 Backup Chain</a></td>
          <td>對照啟示：Immuta 主要在 query-time layer、backup / cold storage 場景仍需 storage-layer policy + IAM 隔離、不要把 Immuta 當 storage encryption 替代</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/data-protection-and-masking-governance/" data-link-title="7.4 資料保護與遮罩治理" data-link-desc="以問題驅動方式整理資料分級、遮罩、匯出與備份治理">7.4 資料保護設計</a>、<a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">7.13 偵測覆蓋率與訊號治理</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/cloud-data-policy/" data-link-title="Cloud-native Data Policy (BigQuery &#43; S3)" data-link-desc="BigQuery column / row-level security &#43; S3 bucket policy &#43; Access Points &#43; Macie、雲端原生資料層 access control、跟 DLP / Purview 互補">Cloud-native data policy</a>、<a href="/blog/backend/07-security-data-protection/vendors/microsoft-purview/" data-link-title="Microsoft Purview" data-link-desc="Microsoft 跨 M365 / Azure / endpoint 的 data governance &#43; information protection &#43; DLP &#43; insider risk 統合平台、label-driven">Microsoft Purview</a>、<a href="/blog/backend/07-security-data-protection/vendors/google-dlp/" data-link-title="Google DLP" data-link-desc="GCP 原生 Sensitive Data Protection：infoType discovery &#43; transformation (mask / FPE / tokenize / k-anonymity)、整合 BigQuery / GCS / Cloud SQL">Google DLP</a></li>
<li>下游：<a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / <a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-security-operations/" data-link-title="Google Security Operations" data-link-desc="Google 雲原生 SIEM &#43; SOAR &#43; Mandiant threat intel 三合一（前 Chronicle）、UDM &#43; YARA-L、fixed-price by data tier、PB-scale 友善">Google Security Operations</a>（query audit 進 SIEM）</li>
<li>跨類：<a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a>（IdP attribute 來源）、<a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a>（warehouse service credential 管理）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（query audit anomaly → IR routing）</li>
<li>官方：<a href="https://documentation.immuta.com/">Immuta Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>Privacera</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/privacera/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/privacera/</guid><description>&lt;p>Privacera 是 &lt;em>data security + AI governance&lt;/em> SaaS 平台、由 Apache Ranger 核心 contributor 在 2016 創立、產品是 Ranger 的 commercial extension。核心定位是把 Hadoop / Hive / Trino ecosystem 慣用的 &lt;em>centralized policy + tag-based access control&lt;/em> 模式擴張到現代 cloud warehouse（Snowflake / Databricks / BigQuery / Redshift），並在 2023+ 加上 PAIG（Privacera AI Governance）處理 LLM application 的 prompt / response 治理。它跟 Immuta 是同類的 &lt;em>cross-warehouse data security platform&lt;/em>、但譜系跟強項不同 — Immuta 走 query rewriter + ABAC 原生、Privacera 走 Ranger heritage + AI governance。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Privacera 的 first-class concept 是 &lt;em>Policy Repository&lt;/em>（中央 policy store、所有 data source 共用一份規則）、底下接 &lt;em>Data Source Connector&lt;/em>（Snowflake / Databricks / Hive / Trino / Spark / S3 / BigQuery / Redshift）、上層產品包含：&lt;em>Access Manager&lt;/em>（Ranger-based、row / column / tag policy）、&lt;em>Data Discovery &amp;amp; Classification&lt;/em>（auto-scan + tag）、&lt;em>Encryption Gateway&lt;/em>（FPE + tokenization、在 query path 或 application 層 inline）、&lt;em>PAIG&lt;/em>（LLM prompt scan + response redaction、AI governance 子產品）。&lt;/p>
&lt;p>跟 Immuta 比、Privacera 走 &lt;em>Ranger heritage + AI governance 雙主軸&lt;/em> — 對既有 Apache Ranger 部署是天然 upgrade 路徑（policy schema / role model 接近）、PAIG 是少數把 LLM I/O 治理跟 data security policy 放同一個 platform 的選項；Immuta 走 &lt;em>query rewriter + ABAC 原生、cloud warehouse first&lt;/em>、現代 cloud-only 架構 onboarding 較快、但 LLM governance 需要外接。跟 &lt;em>Apache Ranger OSS&lt;/em> 比、Privacera 是 Ranger 的 SaaS 商業版 + 多 warehouse 擴張、不想付費可直接用 Ranger 但只覆蓋 Hadoop ecosystem、不含現代 warehouse connector / Discovery / PAIG。跟 &lt;em>cloud-native policy&lt;/em>（Snowflake row access policy / Databricks Unity Catalog / BigQuery column-level security）比、cloud-native 在單一 warehouse 內最便宜、但跨 warehouse + 跨 lake + LLM I/O 的 &lt;em>統一 policy 視圖&lt;/em> 需要 platform 層補位。&lt;/p></description><content:encoded><![CDATA[<p>Privacera 是 <em>data security + AI governance</em> SaaS 平台、由 Apache Ranger 核心 contributor 在 2016 創立、產品是 Ranger 的 commercial extension。核心定位是把 Hadoop / Hive / Trino ecosystem 慣用的 <em>centralized policy + tag-based access control</em> 模式擴張到現代 cloud warehouse（Snowflake / Databricks / BigQuery / Redshift），並在 2023+ 加上 PAIG（Privacera AI Governance）處理 LLM application 的 prompt / response 治理。它跟 Immuta 是同類的 <em>cross-warehouse data security platform</em>、但譜系跟強項不同 — Immuta 走 query rewriter + ABAC 原生、Privacera 走 Ranger heritage + AI governance。</p>
<h2 id="服務定位">服務定位</h2>
<p>Privacera 的 first-class concept 是 <em>Policy Repository</em>（中央 policy store、所有 data source 共用一份規則）、底下接 <em>Data Source Connector</em>（Snowflake / Databricks / Hive / Trino / Spark / S3 / BigQuery / Redshift）、上層產品包含：<em>Access Manager</em>（Ranger-based、row / column / tag policy）、<em>Data Discovery &amp; Classification</em>（auto-scan + tag）、<em>Encryption Gateway</em>（FPE + tokenization、在 query path 或 application 層 inline）、<em>PAIG</em>（LLM prompt scan + response redaction、AI governance 子產品）。</p>
<p>跟 Immuta 比、Privacera 走 <em>Ranger heritage + AI governance 雙主軸</em> — 對既有 Apache Ranger 部署是天然 upgrade 路徑（policy schema / role model 接近）、PAIG 是少數把 LLM I/O 治理跟 data security policy 放同一個 platform 的選項；Immuta 走 <em>query rewriter + ABAC 原生、cloud warehouse first</em>、現代 cloud-only 架構 onboarding 較快、但 LLM governance 需要外接。跟 <em>Apache Ranger OSS</em> 比、Privacera 是 Ranger 的 SaaS 商業版 + 多 warehouse 擴張、不想付費可直接用 Ranger 但只覆蓋 Hadoop ecosystem、不含現代 warehouse connector / Discovery / PAIG。跟 <em>cloud-native policy</em>（Snowflake row access policy / Databricks Unity Catalog / BigQuery column-level security）比、cloud-native 在單一 warehouse 內最便宜、但跨 warehouse + 跨 lake + LLM I/O 的 <em>統一 policy 視圖</em> 需要 platform 層補位。</p>
<p>關鍵張力：<em>Ranger heritage 的廣度</em> ↔ <em>現代 cloud-only 的部署速度</em> 是 Privacera vs Immuta 最常見的取捨。Hadoop / Hive / Trino 還在 production 又要管 Snowflake / Databricks，Privacera 的 connector 譜系比較貼；如果已經沒有 Hadoop 包袱、純 cloud warehouse + 不需 LLM governance，Immuta 或 cloud-native 是更輕的選擇。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>Privacera 在 data security stack 中承擔哪一段（central policy / data source enforcement / discovery / LLM I/O governance）、跟 <a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">偵測覆蓋率與訊號治理</a> 的交界</li>
<li>Policy Repository / Data Source Connector / Encryption Gateway / PAIG 各自的 ownership 設計（誰寫 policy、誰 review、誰 own LLM prompt rule）</li>
<li>Apache Ranger OSS / Privacera SaaS / Immuta / cloud-native policy 的取捨</li>
<li>何時選 Privacera、何時走 Immuta / Ranger OSS / 純 cloud-native</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Privacera deployment 是否健康、最少看四件事：</p>
<ul>
<li><strong>Policy Repository ownership</strong>：policy 是否走版控（Git → Privacera Policy API import）、誰能改 production policy、tag-based vs resource-based policy 比例（tag-based 是 sustainable 模式、resource-based 不適合長期維護）</li>
<li><strong>Data Source Connector coverage</strong>：哪些 warehouse / lake 接上 Privacera（Snowflake / Databricks / Hive / Trino / S3 / BigQuery / Redshift）、是否有 source 還沒接、unmanaged source 跟 managed source 比例</li>
<li><strong>Discovery &amp; Classification 跑得到位</strong>：sensitive data tag（PII / PHI / PCI）是否 auto-scan 自動掛在 column / file 上、tag freshness（多久重 scan 一次）、人工 review 流程</li>
<li><strong>PAIG / Encryption Gateway 使用範圍</strong>：LLM application 是否走 PAIG（prompt scan / response redaction）、sensitive table 是否走 Encryption Gateway 的 FPE / tokenization、application 是否還在用明文路徑繞過 gateway</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/07-security-data-protection/data-protection-and-masking-governance/" data-link-title="7.4 資料保護與遮罩治理" data-link-desc="以問題驅動方式整理資料分級、遮罩、匯出與備份治理">7.4 資料保護與遮罩治理</a> 邊界的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>Policy Repository（central policy store）</strong>：所有 data source 共用一份 <em>policy + tag</em> 定義、policy 不綁特定 source 而是綁 tag（<code>PII.email</code> 在 Snowflake / Hive / S3 對 finance role 都 mask）。Repository 走 Git 同步是 production 標準作法、不能讓 SRE 在 console 直接改 production policy。policy change 經 PR review + staging tenant 跑 24-48hr 觀察 query failure rate 才 promote。</p>
<p><strong>Data Source Connector</strong>：每個 warehouse / lake 一個 connector、connector 把 Privacera policy 翻譯成 source 原生機制（Snowflake row access policy + masking policy、Databricks Unity Catalog grant、Hive Ranger plugin、Trino access control plugin、S3 bucket policy）。意義是 <em>user 直接連 source</em> — query path 不走 Privacera proxy、Privacera 只負責 policy 推送 + audit pull。比 query rewriter / proxy 架構（Immuta 部分模式）latency 影響低、但 connector breakage 時可能 fail-open，需要 connector health monitoring。</p>
<p><strong>Access Manager（Ranger-based）</strong>：UI 跟 Apache Ranger 接近 — <em>resource-based policy</em>（指定 database / table / column）跟 <em>tag-based policy</em>（指定 tag、跨 source 套用）兩種模式。生產建議走 tag-based 為主、resource-based 只用在臨時例外。Row filter / column mask / deny rule 是核心三類 policy、配對 IdP（Okta / Azure AD / SAML）拉 user attribute 做 ABAC 決策。</p>
<p><strong>Data Discovery &amp; Classification</strong>：scanner 跑遍 data source、auto-detect column 內容（regex / dictionary / ML-based classifier）、自動掛 tag（<code>PII.email</code> / <code>PHI.diagnosis</code> / <code>PCI.card_number</code>）。tag freshness 是工程議題 — schema 變動後多久重 scan、scan cost 怎麼控、false positive tag 如何 review。Discovery 結果應該是 <em>建議 tag、人工 confirm</em>、不該全自動套 policy。</p>
<p><strong>PAIG（Privacera AI Governance）</strong>：2023+ 推、針對 LLM application 的 <em>prompt scan + response redaction</em> 子產品。流程是 application 在送 prompt 到 LLM endpoint 前先過 PAIG（檢查 prompt 內 PII / 機敏內容、決定 redact / block / log）、LLM 回 response 後再過 PAIG（redact 不該外洩的 token、檢查 response 是否含 sensitive 內容）。跟 OpenAI / Anthropic / Azure OpenAI 等 endpoint 整合走 SDK wrapper 或 proxy 模式。對應 <a href="/blog/backend/07-security-data-protection/" data-link-title="模組七：資安與資料保護" data-link-desc="以問題驅動方式擴充資安知識網：先定義服務環節問題，再以案例作為觸發式參考">AI / LLM governance</a> 章節的 data-side policy。</p>
<p><strong>Encryption Gateway（FPE + tokenization）</strong>：可在 <em>query path</em>（warehouse 內 column 存 token、query 時 decrypt）或 <em>application 層</em>（application 取資料前先過 gateway 換 token）做 inline encrypt / decrypt。FPE 保留資料 format（信用卡號加密後還是 16 碼數字）、application 不需改 schema。使用要看 <em>誰持有 key</em>（Privacera 託管 vs 自帶 KMS）、failure mode（gateway 掛掉時 application 行為）跟 latency 預算。</p>
<p><strong>跟 IdP integration</strong>：user / role / attribute 從 <a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a> / Azure AD / SAML IdP 拉、ABAC 決策依賴 IdP attribute（department、clearance level、project tag）。IdP attribute 治理品質直接決定 Privacera policy 品質 — IdP 內 attribute 亂、Privacera policy 不可能準。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Privacera</th>
          <th>Immuta</th>
          <th>Apache Ranger OSS</th>
          <th>Cloud-native policy（Snowflake / Unity Catalog / BigQuery）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>譜系</td>
          <td>Ranger commercial fork</td>
          <td>Cloud warehouse-first、原生 ABAC</td>
          <td>Hadoop ecosystem OSS</td>
          <td>單一 warehouse 廠商原生</td>
      </tr>
      <tr>
          <td>Source 覆蓋</td>
          <td>廣 — Hadoop + 多 cloud warehouse + LLM</td>
          <td>廣 — cloud warehouse + lake</td>
          <td>Hadoop ecosystem only</td>
          <td>單一 warehouse 內</td>
      </tr>
      <tr>
          <td>Policy 模式</td>
          <td>Tag-based + resource-based（Ranger 風）</td>
          <td>Query rewriter + ABAC attribute</td>
          <td>Resource-based + tag-based（基本版）</td>
          <td>Warehouse 原生 row / column policy</td>
      </tr>
      <tr>
          <td>LLM governance</td>
          <td>PAIG（內建）</td>
          <td>無原生、需外接</td>
          <td>無</td>
          <td>無</td>
      </tr>
      <tr>
          <td>Encryption</td>
          <td>Encryption Gateway（FPE + tokenization）</td>
          <td>Masking + format-preserving 部分</td>
          <td>基本 masking</td>
          <td>Warehouse 原生 dynamic masking</td>
      </tr>
      <tr>
          <td>計費</td>
          <td>Enterprise SaaS（按 source / module）</td>
          <td>Enterprise SaaS（按 source / user）</td>
          <td>OSS（免費、自管成本高）</td>
          <td>通常含在 warehouse spend</td>
      </tr>
      <tr>
          <td>部署速度</td>
          <td>中 — Ranger 熟悉者快</td>
          <td>中 — cloud-only 快</td>
          <td>慢 — 自管 Ranger admin / KMS</td>
          <td>快 — 直接寫 warehouse SQL</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>Hadoop + 現代 warehouse 混合 + AI 導入</td>
          <td>純 cloud warehouse + ABAC 重</td>
          <td>純 Hadoop ecosystem + 預算敏感</td>
          <td>單一 warehouse 內 + 跨 warehouse 不密</td>
      </tr>
      <tr>
          <td>退場成本</td>
          <td>中高 — policy 量 + connector + PAIG rule</td>
          <td>中高 — policy + ABAC attribute</td>
          <td>低</td>
          <td>低（policy 已在 warehouse）</td>
      </tr>
  </tbody>
</table>
<p>選 Privacera 的核心訴求：<em>Apache Ranger 已部署想 upgrade 到管理 platform</em>、或 <em>Hadoop / Hive / Trino + 現代 cloud warehouse 混合架構需要單一 policy 視圖</em>、或 <em>AI / LLM application 開始導入且資料治理要跟 LLM I/O policy 同 plane</em>。純 cloud-only + 不碰 LLM 走 Immuta 或 cloud-native 更輕。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>PAIG 的 prompt / response governance</strong>：LLM application 的 data security 問題在 <em>prompt 內帶 PII 進 LLM context</em>（資料外洩到第三方）跟 <em>response 含 sensitive 內容流回 user</em>（policy bypass）。PAIG 在這兩個邊界做 redact / block / log、把資料治理規則套到 LLM I/O。實作關鍵是 <em>latency 預算</em>（每個 prompt 過一次 scan）、<em>false positive 容忍度</em>（redact 太多 LLM 回答品質掉）、<em>audit log retention</em>（哪些 prompt 該保留多久）。</p>
<p><strong>Encryption Gateway 的 key ownership</strong>：FPE / tokenization 的安全性核心是 <em>誰持有 key</em>。Privacera 託管 key 是最快上線方案、但 vendor compromise 等於資料明文外洩風險；自帶 KMS（AWS KMS / Azure Key Vault / GCP KMS）grant Privacera 使用權限是 production 推薦、key rotation / revoke 自己掌握。Gateway down 時 fail-open（直通明文）vs fail-closed（application 報錯）要明確定義。</p>
<p><strong>Apache Ranger OSS 遷移路徑</strong>：Ranger OSS deployment 升級到 Privacera 通常走 <em>policy export → Privacera import</em> + <em>connector 改接 Privacera plugin</em> 的階段性遷移、不是 big-bang。Privacera Ranger plugin 跟 OSS Ranger plugin 行為兼容、可以混用一段時間。遷移期間 <em>policy schema 差異</em>（Privacera 加的 tag / Discovery 欄位 Ranger OSS 沒有）需要處理。</p>
<p><strong>Compliance template</strong>：GDPR / HIPAA / CCPA / PCI-DSS 的 compliance pack 提供 <em>預定義 tag 集 + policy 範本</em>（自動 mask EU resident 的 PII、PHI 只給特定 clearance role）。template 是起點不是終點 — organization 的實際 compliance 需求通常更細、template 只覆蓋通用條款。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Query 大量 fail / user 抱怨拿不到資料</strong>：新 policy promote 沒經 staging 觀察、tag 自動套到太廣範圍 — rollback policy、staging tenant 跑 query replay 找 affected query、tune tag scope</li>
<li><strong>Connector breakage 後 fail-open</strong>：Privacera policy 沒推到 source、source 還是用舊 policy 或全開 — connector health monitoring + alert、定期 audit policy sync diff</li>
<li><strong>Discovery scan 找不到敏感 column</strong>：classifier rule 沒涵蓋 organization-specific 格式（內部員工編號 / 客戶 ID 自訂格式）— 加 custom regex / dictionary classifier、人工 review tag 補漏</li>
<li><strong>PAIG redact 太兇 / LLM 回答品質掉</strong>：prompt scan rule 寫太寬、把無關 token 也 redact — staging 環境 replay LLM session 觀察 redact 比例、tune classifier threshold、加 allow-list</li>
<li><strong>Encryption Gateway latency 變高</strong>：gateway pod 不夠 / inline 模式擋在 hot path — scale gateway、評估 <em>application 側 cache token mapping</em> 或 <em>batch decrypt</em>、不是所有 query 都過 gateway</li>
<li><strong>Policy 版控漂移</strong>：SRE 在 console hotfix 沒回寫 Git、Git policy 跟 production 不同步 — disable console edit for production policy、policy change 強制走 Git PR</li>
<li><strong>IdP attribute 亂 / ABAC 決策不準</strong>：user department / clearance 在 IdP 沒人維護、Privacera 拉的 attribute 跟實際角色不符 — 修 IdP 側 attribute lifecycle（onboarding / role change / offboarding）、不是 Privacera 加更多 policy 補</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>純 cloud warehouse + ABAC 重</td>
          <td>Immuta（同類 platform、cloud-first）</td>
      </tr>
      <tr>
          <td>純 Hadoop ecosystem + 預算敏感</td>
          <td>Apache Ranger OSS（自管）</td>
      </tr>
      <tr>
          <td>單一 warehouse 內 policy 夠用</td>
          <td>Snowflake row access policy / Databricks Unity Catalog / BigQuery column-level security</td>
      </tr>
      <tr>
          <td>DLP / sensitive data discovery only</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/google-dlp/" data-link-title="Google DLP" data-link-desc="GCP 原生 Sensitive Data Protection：infoType discovery &#43; transformation (mask / FPE / tokenize / k-anonymity)、整合 BigQuery / GCS / Cloud SQL">Google DLP</a> / <a href="/blog/backend/07-security-data-protection/vendors/microsoft-purview/" data-link-title="Microsoft Purview" data-link-desc="Microsoft 跨 M365 / Azure / endpoint 的 data governance &#43; information protection &#43; DLP &#43; insider risk 統合平台、label-driven">Microsoft Purview</a></td>
      </tr>
      <tr>
          <td>純 LLM I/O guardrail（不含 data security）</td>
          <td>LLM-specific guardrail（Lakera / Protect AI / cloud provider 原生 content safety）</td>
      </tr>
      <tr>
          <td>SIEM / detection</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / <a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-security-operations/" data-link-title="Google Security Operations" data-link-desc="Google 雲原生 SIEM &#43; SOAR &#43; Mandiant threat intel 三合一（前 Chronicle）、UDM &#43; YARA-L、fixed-price by data tier、PB-scale 友善">Google Security Operations</a></td>
      </tr>
      <tr>
          <td>IdP / SSO 治理</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Apache Ranger OSS 的 admin / plugin 自管細節（policy DB schema、ranger-admin tuning）</li>
<li>PAIG 的 LLM SDK wrapper / proxy 模式選擇（SDK 整合屬 application engineering）</li>
<li>Encryption Gateway 的 FPE 演算法選型（NIST FF1 / FF3-1 等 cryptographic primitive 細節）</li>
<li>Privacera vs Immuta 的逐 feature checklist（產品快速迭代、列了會很快過期）</li>
<li>Snowflake / Databricks / BigQuery 各自原生 policy 的完整 reference（屬 warehouse vendor 文件）</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>Privacera 在 07 案例庫沒有直接 vendor-level 事件、但跨 warehouse + 加密 / tokenization 相關 case 都是 platform-level data security 的對照：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 Privacera 的關係（對照啟示）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/data-exfiltration/snowflake-2024-credential-abuse/" data-link-title="7.R7.4.2 Snowflake 2024：憑證濫用與資料竊取" data-link-desc="外洩憑證與 MFA 缺口如何在資料平台形成高風險外送事件">Snowflake 2024 Credential Abuse</a></td>
          <td>credential 外洩後仍要靠 query-time access control + tag-based masking 限制 query 範圍、Privacera Access Manager 跟 Immuta 同類補位、不能只靠 IdP MFA</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/data-exfiltration/mailchimp-2023-support-tool-abuse/" data-link-title="7.R7.4.4 Mailchimp 2023：支援工具路徑與客戶資料風險" data-link-desc="社交工程進入客服工具後，如何形成特定客戶資料存取風險">Mailchimp 2023 Support Tool Abuse</a></td>
          <td>support / 內部工具連 warehouse 必須走 Privacera policy gate、support role 看到的欄位該預設 mask、不是相信 application 層的 UI 隱藏</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/data-exfiltration/lastpass-2022-backup-chain/" data-link-title="7.R7.4.1 LastPass 2022：備份路徑與鏈式入侵" data-link-desc="開發環境資訊外流如何沿著備份路徑擴大成資料風險">LastPass 2022 Backup Chain</a></td>
          <td>Privacera Encryption Gateway 對 backup data 做 FPE / tokenization、即使 backup 外洩攻擊者拿到的也是 token、key ownership 一定要自帶 KMS</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/data-protection-and-masking-governance/" data-link-title="7.4 資料保護與遮罩治理" data-link-desc="以問題驅動方式整理資料分級、遮罩、匯出與備份治理">7.4 資料保護與遮罩治理</a>（cross-warehouse mask / tokenization policy）、<a href="/blog/backend/07-security-data-protection/data-residency-deletion-and-evidence-chain/" data-link-title="7.11 資料駐留、刪除與證據鏈" data-link-desc="定義跨區資料駐留、刪除請求與可驗證證據鏈問題">7.11 資料駐留、刪除與證據鏈</a>（資料分類 + 證據鏈跟 Discovery tag 對接）</li>
<li>平行：Immuta（同類 cross-warehouse data security platform、cloud-first）、Apache Ranger OSS（Hadoop ecosystem 自管）</li>
<li>下游：<a href="/blog/backend/07-security-data-protection/vendors/google-dlp/" data-link-title="Google DLP" data-link-desc="GCP 原生 Sensitive Data Protection：infoType discovery &#43; transformation (mask / FPE / tokenize / k-anonymity)、整合 BigQuery / GCS / Cloud SQL">Google DLP</a> / <a href="/blog/backend/07-security-data-protection/vendors/microsoft-purview/" data-link-title="Microsoft Purview" data-link-desc="Microsoft 跨 M365 / Azure / endpoint 的 data governance &#43; information protection &#43; DLP &#43; insider risk 統合平台、label-driven">Microsoft Purview</a>（DLP 跟 Discovery 互補、tag 來源可共用）</li>
<li>跨類：<a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a>（IdP attribute 來源、ABAC policy 依賴）、<a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a>（Encryption Gateway 的 KMS / key broker 選項）</li>
<li>跨模組：<a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / <a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a>（Privacera audit log → SIEM correlation）</li>
<li>官方：<a href="https://docs.privacera.com/">Privacera Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>Datadog Continuous Profiler</title><link>https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/datadog-continuous-profiler/</link><pubDate>Fri, 15 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/datadog-continuous-profiler/</guid><description>&lt;p>Datadog Continuous Profiler 的核心責任是把 production profile 接到 SaaS APM、deployment marker、service tag 與 release regression workflow。它適合已經使用 Datadog APM / metrics / logs 的團隊，重點在讓 slow request、resource saturation、deploy version 與 profile diff 能在同一個操作介面中對齊。&lt;/p>
&lt;h2 id="定位">定位&lt;/h2>
&lt;p>Datadog Continuous Profiler 是 &lt;a href="https://tarrragon.github.io/blog/backend/04-observability/vendors/datadog/" data-link-title="Datadog" data-link-desc="All-in-one SaaS 觀測平台、APM / Logs / Metrics / RUM / Security">Datadog&lt;/a> APM 的 &lt;em>production profiling&lt;/em> add-on、跟 Datadog Logs / Metrics / Traces 同 plane、共用 service tag、env tag、version tag 與 query bar。它的核心責任是把 production profile 接到 SaaS APM、deployment marker、service tag 與 release regression workflow，讓 slow request、resource saturation、deploy version 與 profile diff 能在同一個操作介面中對齊。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/pyroscope/" data-link-title="Pyroscope" data-link-desc="用 Grafana 生態與開源 profiling backend 建立可自管 profile diff 與 flame graph 的工具">Pyroscope&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/parca/" data-link-title="Parca" data-link-desc="用 eBPF 與開源 continuous profiling 平台建立 infrastructure-wide profile evidence 的工具">Parca&lt;/a> 這類 OSS profiler 比、Datadog Continuous Profiler 走 &lt;em>ecosystem-bundled&lt;/em> 路線 — profiler 本身不獨立計費、跟 APM host 一起進 business unit 預算、profile data 直接跟 trace_id、deploy marker、log query 在同一介面 cross-link。OSS profiler 走 &lt;em>standalone deployment&lt;/em>、profile store 自管（ClickHouse / object storage）、跟 observability 其他 plane 要自己 wire（grafana correlation、自寫 trace_id mapping）。差異在 &lt;em>跨 signal 的 query continuity 跟組織計費歸屬&lt;/em>、flame graph 本身的視覺呈現相近。&lt;/p>
&lt;p>這個定位讓 Datadog Continuous Profiler 接到 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/improvement-loop/" data-link-title="9.9 Performance Improvement Loop" data-link-desc="壓測 → profile → fix → re-test → release gate 的閉環">9.9 Performance Improvement Loop&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/04-observability/continuous-profiling/" data-link-title="4.9 Continuous Profiling" data-link-desc="把 CPU / memory / lock profile 從一次性除錯升級為持續訊號">4.9 Continuous Profiling&lt;/a>。它的價值在於降低 profile diff 的交接成本；它的代價在於 SaaS 成本、agent 設定、資料保留與 vendor 約束。&lt;/p></description><content:encoded><![CDATA[<p>Datadog Continuous Profiler 的核心責任是把 production profile 接到 SaaS APM、deployment marker、service tag 與 release regression workflow。它適合已經使用 Datadog APM / metrics / logs 的團隊，重點在讓 slow request、resource saturation、deploy version 與 profile diff 能在同一個操作介面中對齊。</p>
<h2 id="定位">定位</h2>
<p>Datadog Continuous Profiler 是 <a href="/blog/backend/04-observability/vendors/datadog/" data-link-title="Datadog" data-link-desc="All-in-one SaaS 觀測平台、APM / Logs / Metrics / RUM / Security">Datadog</a> APM 的 <em>production profiling</em> add-on、跟 Datadog Logs / Metrics / Traces 同 plane、共用 service tag、env tag、version tag 與 query bar。它的核心責任是把 production profile 接到 SaaS APM、deployment marker、service tag 與 release regression workflow，讓 slow request、resource saturation、deploy version 與 profile diff 能在同一個操作介面中對齊。</p>
<p>跟 <a href="/blog/backend/09-performance-capacity/vendors/pyroscope/" data-link-title="Pyroscope" data-link-desc="用 Grafana 生態與開源 profiling backend 建立可自管 profile diff 與 flame graph 的工具">Pyroscope</a> / <a href="/blog/backend/09-performance-capacity/vendors/parca/" data-link-title="Parca" data-link-desc="用 eBPF 與開源 continuous profiling 平台建立 infrastructure-wide profile evidence 的工具">Parca</a> 這類 OSS profiler 比、Datadog Continuous Profiler 走 <em>ecosystem-bundled</em> 路線 — profiler 本身不獨立計費、跟 APM host 一起進 business unit 預算、profile data 直接跟 trace_id、deploy marker、log query 在同一介面 cross-link。OSS profiler 走 <em>standalone deployment</em>、profile store 自管（ClickHouse / object storage）、跟 observability 其他 plane 要自己 wire（grafana correlation、自寫 trace_id mapping）。差異在 <em>跨 signal 的 query continuity 跟組織計費歸屬</em>、flame graph 本身的視覺呈現相近。</p>
<p>這個定位讓 Datadog Continuous Profiler 接到 <a href="/blog/backend/09-performance-capacity/improvement-loop/" data-link-title="9.9 Performance Improvement Loop" data-link-desc="壓測 → profile → fix → re-test → release gate 的閉環">9.9 Performance Improvement Loop</a> 與 <a href="/blog/backend/04-observability/continuous-profiling/" data-link-title="4.9 Continuous Profiling" data-link-desc="把 CPU / memory / lock profile 從一次性除錯升級為持續訊號">4.9 Continuous Profiling</a>。它的價值在於降低 profile diff 的交接成本；它的代價在於 SaaS 成本、agent 設定、資料保留與 vendor 約束。</p>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Datadog Continuous Profiler deployment 是否健康、最少看四件事：</p>
<ul>
<li><strong>Agent / SDK profiling 是否真的 enabled</strong>：Datadog Agent 跑著不等於 profiler 開了 — 各語言要在 SDK init 加 <code>profiling_enabled=true</code> 或環境變數 <code>DD_PROFILING_ENABLED=true</code>、Go / Java / Python / Node / Ruby / .NET 的開啟方式跟覆蓋的 profile type（CPU / heap / goroutine / lock / wall time）各不同</li>
<li><strong>Service / version / env tag 紀律</strong>：profile 沒有 <code>service</code> + <code>env</code> + <code>version</code> tag 就無法 diff、release marker 也對不上 — CI 要把 git SHA 或 release tag 注入 <code>DD_VERSION</code>、deploy pipeline 要打 deployment marker API</li>
<li><strong>Sampling rate 跟 production coverage</strong>：profiler 預設 60s 採一次、低流量服務或 short-lived 任務可能 sample 不到 hot path — 對 ultra-low latency / burst workload 要評估 sampling 是否還抓得到 regression signal</li>
<li><strong>Profile ingestion cost / retention</strong>：profile 是按 APM host 計費、但 profile event 量隨 service 數量 + sampling rate 漲、retention 預設 7 天（custom retention 另計）— 大型 deployment 要做 service-level enable/disable governance</li>
</ul>
<h2 id="適用場景">適用場景</h2>
<p>Release regression 定位適合 Datadog Continuous Profiler。當 canary 或 release candidate 的 p99、CPU、memory 或 cost per request 退化，團隊可以用 deployment marker 對比 release 前後 profile，找出變寬的 call stack。</p>
<p>APM-to-profile drilldown 適合 Datadog Continuous Profiler。慢 request 可以從 service、endpoint、trace 或 span 往下切到 profile，讓工程師知道 latency 是 DB、network、runtime、serialization、lock 還是 CPU hot path。</p>
<p>多語言 SaaS 團隊適合 Datadog Continuous Profiler。團隊如果同時維護 Go、Java、Python、Ruby、Node.js 或 .NET 服務，SaaS profiler 可以用統一 tag、dashboard 與權限模型管理。</p>
<h2 id="選型判準">選型判準</h2>
<table>
  <thead>
      <tr>
          <th>判準</th>
          <th>Datadog 的價值</th>
          <th>需要補的能力</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>APM 整合</td>
          <td>trace、service、endpoint、profile 可串接</td>
          <td>service tag 與 deploy label 紀律</td>
      </tr>
      <tr>
          <td>Deployment marker</td>
          <td>release 前後 profile diff 容易建立</td>
          <td>release pipeline 與版本標記整合</td>
      </tr>
      <tr>
          <td>SaaS 操作</td>
          <td>低自管成本、跨團隊易查詢</td>
          <td>成本治理、資料保留與 vendor 約束</td>
      </tr>
      <tr>
          <td>多語言支援</td>
          <td>多 runtime 用同一套操作介面</td>
          <td>各語言 agent overhead 與覆蓋差異</td>
      </tr>
  </tbody>
</table>
<p>APM 整合價值來自上下文連續。Metrics 告訴你 CPU 上升，trace 告訴你 endpoint 變慢，profile 告訴你哪段 code path 變貴；Datadog 的優勢是把這些訊號放進同一個查詢與 dashboard 流程。</p>
<p>Deployment marker 價值來自 release gate。Profile diff 如果能對齊 commit、version、environment 與 canary cohort，就能成為 <a href="/blog/backend/06-reliability/performance-regression-gate/" data-link-title="6.13 Performance Regression Gate" data-link-desc="把效能 baseline 從一次性壓測變成持續對齊的 release gate，涵蓋 baseline 設定、判讀方法、variance 控制與退化定位">6.13 Performance Regression Gate</a> 的 evidence。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Datadog Continuous Profiler</th>
          <th>Pyroscope</th>
          <th>Parca</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>部署模型</td>
          <td>SaaS only、跟 Datadog Agent / APM 綁</td>
          <td>OSS self-host / Grafana Cloud SaaS</td>
          <td>OSS self-host（Polar Signals SaaS 選）</td>
      </tr>
      <tr>
          <td>計費模型</td>
          <td>跟 APM host 計費（profile 不獨立 metering）</td>
          <td>OSS 免費 / Grafana Cloud 按 ingestion</td>
          <td>OSS 免費 / SaaS 按 host</td>
      </tr>
      <tr>
          <td>Profile 採集方式</td>
          <td>Language SDK（pull 採樣）</td>
          <td>SDK + eBPF agent</td>
          <td>eBPF-first、language-agnostic</td>
      </tr>
      <tr>
          <td>Trace correlation</td>
          <td>強 — trace_id 自動 link 到 flame graph</td>
          <td>中 — 要自己 wire OTel trace_id</td>
          <td>弱 — 偏 eBPF profile、trace 整合較淺</td>
      </tr>
      <tr>
          <td>視覺 / Workflow</td>
          <td>APM service view + Profile diff + Code Hotspot in IDE</td>
          <td>Grafana flame graph + diff、跟 Loki / Tempo 同 UI</td>
          <td>Parca UI 簡潔、偏單純 profile 探索</td>
      </tr>
      <tr>
          <td>多語言支援</td>
          <td>Go / Java / Python / Node / Ruby / .NET / PHP 官方 SDK</td>
          <td>同 + 社群 SDK；eBPF 補 native binary</td>
          <td>eBPF-only、不挑語言但 symbol 解析較吃力</td>
      </tr>
      <tr>
          <td>Vendor lock-in</td>
          <td>高 — profile 跟 APM workflow 綁、退場要重建 dashboard</td>
          <td>低 — OSS、profile 格式相對開放</td>
          <td>低 — OSS、pprof 格式相容</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>Datadog-heavy org、APM / log / metric 已用</td>
          <td>Grafana stack 已用、要省 license</td>
          <td>eBPF-first、low-overhead always-on</td>
      </tr>
  </tbody>
</table>
<p>選 Datadog Continuous Profiler 的核心訴求：<em>Datadog 已是 observability backbone</em> + 要 <em>APM trace ↔ profile drilldown 是 first-class workflow</em> + 接受 SaaS 計費 + 接受 SDK overhead trade-off。如果 Datadog 不是既有平台、單純為了 profiling 引入 Datadog 通常成本不划算、改走 Pyroscope / Parca。</p>
<p>跟一次性 runtime profiler（<code>pprof</code>、<code>async-profiler</code> 手動跑）的差異是時間維度。一次性 profiler 適合本機或 incident 當下調查；continuous profiler 適合 baseline、release diff 與長期退化治理 — 兩者互補、不互斥。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>APM trace ↔ profile correlation</strong>：Datadog SDK 把 <code>trace_id</code> 注入 profile sample 的 label、APM trace view 上每個 span 可以直接點到「執行這段 span 時的 flame graph」。意義是 <em>p99 latency 異常 trace 不只看 span 等待時間、能直接看到該 span 期間 CPU / lock / allocation 真正花在哪段 code</em>。需要 SDK 版本支援 + trace context propagation 正確接上、舊版 SDK 或自寫 instrumentation 容易斷鏈。</p>
<p><strong>Endpoint profiling</strong>：profile 按 HTTP endpoint / RPC method 切片、不只看 service 整體 hot path。意義是 <em>新加的 endpoint 即便 traffic 小、也能單獨看它的 CPU / allocation cost</em>、不會被 service 主流量稀釋。對 multi-tenant API、A/B test endpoint、internal admin endpoint 的退化偵測特別有用。</p>
<p><strong>Code Hotspot in IDE</strong>：Datadog IDE plugin（IntelliJ / VS Code）把 production profile 的 hot line 直接 overlay 到 source code、工程師 review PR 時能看到「這個 function 在 production 佔 service CPU 12%」。降低 <em>看 flame graph → 找 source 對應行</em> 的 cognitive cost。對應 <a href="/blog/backend/09-performance-capacity/improvement-loop/" data-link-title="9.9 Performance Improvement Loop" data-link-desc="壓測 → profile → fix → re-test → release gate 的閉環">9.9 Performance Improvement Loop</a> 中「production signal → code change」的 feedback loop 縮短。</p>
<p><strong>Profile diff（baseline vs candidate）</strong>：Datadog 內建 diff view、選兩個 time window 或兩個 version tag、直接看 flame graph 哪些 frame 變寬 / 變窄。是 <a href="/blog/backend/06-reliability/performance-regression-gate/" data-link-title="6.13 Performance Regression Gate" data-link-desc="把效能 baseline 從一次性壓測變成持續對齊的 release gate，涵蓋 baseline 設定、判讀方法、variance 控制與退化定位">6.13 Performance Regression Gate</a> 的核心 evidence — canary 跑完 30min、自動拉 baseline vs candidate diff 報告、超過 threshold 阻擋 promote。</p>
<p><strong>Notebooks correlation</strong>：Datadog Notebooks 可以把 profile flame graph、APM trace、metric chart、log query 排在同一份文件。incident post-mortem 跟 release review 寫一份 notebook 比散落多個 dashboard tab 更可追溯、也接 <a href="/blog/backend/04-observability/observability-evidence-package/" data-link-title="4.20 Observability Evidence Package" data-link-desc="把 log、metric、trace、audit 與資料品質限制包成可交接證據">evidence package</a> 規範。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>SDK overhead 在 production 過高</strong>：profiler 預設 overhead &lt; 2% CPU、但 wall-time profiling / allocation profiling 全開可能到 5%+ — canary 一台量測、按 profile type 分別 enable、不要全部一次開</li>
<li><strong>Sampling rate 太低 / false negative</strong>：short-lived job（&lt; 60s）或 low-traffic service 可能整個生命週期沒被 sample 到、看不到 hot path — 改成事件觸發 profile（on-demand profiling API）或拉高該 service 的 sampling rate</li>
<li><strong>Profile 沒有 version tag / 無法 diff</strong>：deploy pipeline 沒注入 <code>DD_VERSION</code>、release marker 對不上 — 補 CI 環境變數、用 <code>dd-trace</code> SDK 自動讀 git commit SHA、跑 staging 驗證 diff view 能顯示 version</li>
<li><strong>Trace ↔ profile drilldown 斷鏈</strong>：SDK 版本太舊、或 trace context 在非同步 / queue handler 沒 propagate — 升 SDK + 補 trace context propagation、用一條已知慢 trace 驗證能不能跳到 flame graph</li>
<li><strong>Profiling cost spike</strong>：新 service 開啟 profiling、或某 service profile event 暴增（exception 路徑反覆採樣）— 看 Datadog usage dashboard 的 profile host hour、對嫌疑 service 暫關 profiling 觀察 cost 曲線、再 tune sampling rate</li>
<li><strong>Flame graph symbol 解析失敗 / 顯示 <code>?</code> frame</strong>：缺 debug symbol、stripped binary、或語言 runtime 版本不支援 — 補 build 時保留 symbol、確認 SDK 版本 vs runtime 版本對應表</li>
<li><strong>Lock profile 看不出 contention</strong>：某些語言（Go / Java）的 lock profiling 需要額外 flag（<code>DD_PROFILING_BLOCK_ENABLED</code> / <code>DD_PROFILING_LOCK_ENABLED</code>）— 預設沒開、要明確 enable 才看得到 lock contention flame graph</li>
</ul>
<h2 id="操作成本">操作成本</h2>
<p>Datadog Continuous Profiler 的主要成本是資料量與保留。Profile sample、tag cardinality、service 數量、environment 數量與 retention 都會影響費用與查詢體驗。</p>
<p>Agent 成本來自 runtime 差異。不同語言的 profiler 支援、overhead、可觀測維度與限制不同，導入時要用 canary service 量測 CPU、memory、latency 與 profile completeness。</p>
<p>Vendor 成本來自資料與 workflow 綁定。當 profile diff、release marker、APM drilldown 與 incident workflow 都在 Datadog 中，後續切換平台需要重新建立 tag schema、dashboard、retention 與 gate integration。</p>
<h2 id="evidence-package">Evidence Package</h2>
<p>Datadog Continuous Profiler 結果應回寫到 evidence package。最小欄位包括 service、version、environment、deploy marker、profile type、time range、comparison baseline、profile diff link、overhead estimate、known gap 與 owner。</p>
<table>
  <thead>
      <tr>
          <th>欄位</th>
          <th>Datadog 證據來源</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Source</td>
          <td>profiler view、profile diff、APM link</td>
      </tr>
      <tr>
          <td>Time range</td>
          <td>baseline / candidate profile window</td>
      </tr>
      <tr>
          <td>Query link</td>
          <td>Datadog profile、trace、dashboard link</td>
      </tr>
      <tr>
          <td>Data quality</td>
          <td>service tag、version tag、sampling status</td>
      </tr>
      <tr>
          <td>Confidence</td>
          <td>production coverage、agent overhead</td>
      </tr>
      <tr>
          <td>Known gap</td>
          <td>runtime coverage、tag drift、retention limit</td>
      </tr>
  </tbody>
</table>
<p>Evidence package 的核心用途是讓 release regression 可追溯。Reviewer 要能從 failed gate 直接打開 profile diff，看出哪個 service、version、endpoint 或 call stack 造成資源成本變化。</p>
<h2 id="案例回寫">案例回寫</h2>
<p>Datadog Continuous Profiler 適合回寫 release regression 與 APM 整合案例。它可接 <a href="/blog/backend/09-performance-capacity/cases/netflix-aurora-consolidation/" data-link-title="9.C23 Netflix：把關聯式 DB 統一到 Aurora、效能 &#43;75%、成本 -28%" data-link-desc="Netflix 把多套關聯式 DB 統一到 Aurora、效能提升 75%、成本下降 28%、串流數十億小時">9.C23 Netflix Aurora consolidation</a> 的 profile noise 降低、<a href="/blog/backend/09-performance-capacity/cases/tubi-elasticache-ml-feature-store/" data-link-title="9.C25 Tubi：從 ScyllaDB 遷到 ElastiCache、ML feature store 達 sub-10ms p99" data-link-desc="Tubi 把 ML 推薦的 feature store 從 ScyllaDB 遷到 ElastiCache for Redis、99 百分位延遲降到 10ms 以下">9.C25 Tubi feature store</a> 的 low-latency hot path 定位、<a href="/blog/backend/09-performance-capacity/cases/coinbase-ultra-low-latency-exchange-2023/" data-link-title="9.C3 Coinbase International Exchange：超低延遲交易的逆向容量設計" data-link-desc="為什麼 Coinbase 國際交易所選 Cluster Placement Group &#43; z1d 而不是自動擴容 — 延遲敏感型負載的容量取捨">9.C3 Coinbase ultra-low latency exchange</a> 的 z1d 單執行緒 hot path 分析、<a href="/blog/backend/09-performance-capacity/cases/lyft-microservice-eight-x-peak/" data-link-title="9.C7 Lyft：100&#43; 微服務在 8 倍峰值下的 Auto Scaling" data-link-desc="Lyft 用 AWS Auto Scaling 跨 100&#43; 個微服務承載 8 倍峰值流量、跨 200&#43; 城市">9.C7 Lyft 100+ 微服務</a> 的 per-service profile diff，以及 <a href="/blog/backend/04-observability/cases/datadog-otel-migration-practice/" data-link-title="4.C7 Datadog：OTel 相容遷移實務" data-link-desc="APM 採集從專有代理轉向 OTel 相容模式的治理案例。">Datadog OTel migration practice</a> 的 observability pipeline 整合。</p>
<p>這些案例的重點是上下文對齊。Datadog Profiler 頁引用案例時，要把 case 轉成 service tag、deploy marker、profile diff、trace drilldown 與 release gate evidence — 例如 Coinbase sub-ms 目標下、profile 必須對齊 RAFT consensus 跟 placement group 拓樸、才能解釋 hot path 為何在某些 epoch 才出現。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/09-performance-capacity/improvement-loop/" data-link-title="9.9 Performance Improvement Loop" data-link-desc="壓測 → profile → fix → re-test → release gate 的閉環">9.9 Performance Improvement Loop</a></li>
<li>上游：<a href="/blog/backend/09-performance-capacity/performance-observability/" data-link-title="9.8 效能可觀測性" data-link-desc="saturation metric、USE / RED method、cost dashboard">9.8 效能可觀測性</a></li>
<li>跨模組：<a href="/blog/backend/04-observability/continuous-profiling/" data-link-title="4.9 Continuous Profiling" data-link-desc="把 CPU / memory / lock profile 從一次性除錯升級為持續訊號">4.9 Continuous Profiling</a></li>
<li>平行：<a href="/blog/backend/09-performance-capacity/vendors/pyroscope/" data-link-title="Pyroscope" data-link-desc="用 Grafana 生態與開源 profiling backend 建立可自管 profile diff 與 flame graph 的工具">Pyroscope</a></li>
<li>平行：<a href="/blog/backend/09-performance-capacity/vendors/parca/" data-link-title="Parca" data-link-desc="用 eBPF 與開源 continuous profiling 平台建立 infrastructure-wide profile evidence 的工具">Parca</a></li>
<li>官方：<a href="https://docs.datadoghq.com/profiler/">Datadog Continuous Profiler documentation</a></li>
</ul>
]]></content:encoded></item><item><title>Pyroscope</title><link>https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/pyroscope/</link><pubDate>Fri, 15 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/pyroscope/</guid><description>&lt;p>Pyroscope 的核心責任是提供開源 continuous profiling backend，讓團隊用 Grafana 生態保存、查詢、比較與視覺化 production profile。它適合偏 OSS-first、已使用 Grafana / Prometheus / Tempo / Loki 的團隊，重點在把 CPU、memory、allocation 與 profile diff 放進可自管 observability stack。Pyroscope 原為獨立 OSS 專案、&lt;em>2023 年被 Grafana Labs 收購&lt;/em>、現分兩條產品線：&lt;em>Grafana Pyroscope&lt;/em>（OSS、Apache 2.0、self-host）與 &lt;em>Grafana Cloud Profiles&lt;/em>（商業 SaaS、走 Grafana Cloud 計費）。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Pyroscope 在 continuous profiling 賽道上的差異點是 &lt;em>Grafana Labs 整合 + 多語言 SDK 覆蓋&lt;/em>、而不是 profiling 演算法本身。跟 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/parca/" data-link-title="Parca" data-link-desc="用 eBPF 與開源 continuous profiling 平台建立 infrastructure-wide profile evidence 的工具">Parca&lt;/a> 比、Parca 走 &lt;em>pprof + Prometheus-style label&lt;/em> 的 CNCF / eBPF infrastructure profiling 路線、focus 在 system-wide 一次抓全機；Pyroscope 走 &lt;em>per-language SDK + Grafana stack 整合&lt;/em> 的 developer-facing 路線、focus 在 application-level flame graph 與 release diff。跟 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/datadog-continuous-profiler/" data-link-title="Datadog Continuous Profiler" data-link-desc="用 SaaS APM 整合、deployment marker 與 profile diff 支援 release regression 定位的 profiling 工具">Datadog Continuous Profiler&lt;/a> 比、Datadog 走 &lt;em>SaaS all-in-one + APM 同 trace context&lt;/em>、profiling 自動跟 trace span 關聯；Pyroscope 走 &lt;em>self-host 可選 + Grafana 跨 signal&lt;/em>、整合靠 Grafana dashboard 跟 explore link 而非 product-level deep linking。&lt;/p>
&lt;p>這個定位讓 Pyroscope 接到 &lt;a href="https://tarrragon.github.io/blog/backend/04-observability/continuous-profiling/" data-link-title="4.9 Continuous Profiling" data-link-desc="把 CPU / memory / lock profile 從一次性除錯升級為持續訊號">4.9 Continuous Profiling&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/improvement-loop/" data-link-title="9.9 Performance Improvement Loop" data-link-desc="壓測 → profile → fix → re-test → release gate 的閉環">9.9 Performance Improvement Loop&lt;/a>。它的價值在於 OSS / Grafana 整合與可自管；它的代價在於 storage、retention、agent rollout 與營運責任要由團隊承擔。&lt;/p>
&lt;h2 id="最短判讀路徑">最短判讀路徑&lt;/h2>
&lt;p>判斷 Pyroscope deployment 是否健康、最少看四件事：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Agent / SDK setup&lt;/strong>：是用 &lt;em>language SDK&lt;/em>（in-process profiler、跟 application code 一起部署）還是 &lt;em>Grafana Alloy / Pyroscope agent&lt;/em>（out-of-process、適合 binary-only 或無法改 code 的 workload）— 兩條路 overhead、覆蓋率、tag 注入方式都不同&lt;/li>
&lt;li>&lt;strong>Push or pull model&lt;/strong>：SDK 預設 &lt;em>push&lt;/em>（application 主動把 profile sample 推到 Pyroscope server）、Alloy / agent 可走 &lt;em>pull&lt;/em>（scrape pprof endpoint、跟 Prometheus 同模型）— push 適合 short-lived job / serverless、pull 適合 long-running service + Kubernetes service discovery&lt;/li>
&lt;li>&lt;strong>Grafana integration&lt;/strong>：是否在 Grafana datasource 設好 Pyroscope、explore 是否能跨 trace / log / profile 跳轉（Tempo trace → Pyroscope profile by service+span）、dashboard 是否內嵌 flame graph panel&lt;/li>
&lt;li>&lt;strong>Tag schema discipline&lt;/strong>：service / version / region / environment / pod 是否一致命名、deploy event 是否打 label 讓 baseline / candidate 比較可成立&lt;/li>
&lt;/ul>
&lt;p>四件事任一缺失、profile 就只是「能看 flame graph」而非「release gate evidence」、無法支撐 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/improvement-loop/" data-link-title="9.9 Performance Improvement Loop" data-link-desc="壓測 → profile → fix → re-test → release gate 的閉環">9.9 Performance Improvement Loop&lt;/a> 的 diff workflow。&lt;/p></description><content:encoded><![CDATA[<p>Pyroscope 的核心責任是提供開源 continuous profiling backend，讓團隊用 Grafana 生態保存、查詢、比較與視覺化 production profile。它適合偏 OSS-first、已使用 Grafana / Prometheus / Tempo / Loki 的團隊，重點在把 CPU、memory、allocation 與 profile diff 放進可自管 observability stack。Pyroscope 原為獨立 OSS 專案、<em>2023 年被 Grafana Labs 收購</em>、現分兩條產品線：<em>Grafana Pyroscope</em>（OSS、Apache 2.0、self-host）與 <em>Grafana Cloud Profiles</em>（商業 SaaS、走 Grafana Cloud 計費）。</p>
<h2 id="服務定位">服務定位</h2>
<p>Pyroscope 在 continuous profiling 賽道上的差異點是 <em>Grafana Labs 整合 + 多語言 SDK 覆蓋</em>、而不是 profiling 演算法本身。跟 <a href="/blog/backend/09-performance-capacity/vendors/parca/" data-link-title="Parca" data-link-desc="用 eBPF 與開源 continuous profiling 平台建立 infrastructure-wide profile evidence 的工具">Parca</a> 比、Parca 走 <em>pprof + Prometheus-style label</em> 的 CNCF / eBPF infrastructure profiling 路線、focus 在 system-wide 一次抓全機；Pyroscope 走 <em>per-language SDK + Grafana stack 整合</em> 的 developer-facing 路線、focus 在 application-level flame graph 與 release diff。跟 <a href="/blog/backend/09-performance-capacity/vendors/datadog-continuous-profiler/" data-link-title="Datadog Continuous Profiler" data-link-desc="用 SaaS APM 整合、deployment marker 與 profile diff 支援 release regression 定位的 profiling 工具">Datadog Continuous Profiler</a> 比、Datadog 走 <em>SaaS all-in-one + APM 同 trace context</em>、profiling 自動跟 trace span 關聯；Pyroscope 走 <em>self-host 可選 + Grafana 跨 signal</em>、整合靠 Grafana dashboard 跟 explore link 而非 product-level deep linking。</p>
<p>這個定位讓 Pyroscope 接到 <a href="/blog/backend/04-observability/continuous-profiling/" data-link-title="4.9 Continuous Profiling" data-link-desc="把 CPU / memory / lock profile 從一次性除錯升級為持續訊號">4.9 Continuous Profiling</a> 與 <a href="/blog/backend/09-performance-capacity/improvement-loop/" data-link-title="9.9 Performance Improvement Loop" data-link-desc="壓測 → profile → fix → re-test → release gate 的閉環">9.9 Performance Improvement Loop</a>。它的價值在於 OSS / Grafana 整合與可自管；它的代價在於 storage、retention、agent rollout 與營運責任要由團隊承擔。</p>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Pyroscope deployment 是否健康、最少看四件事：</p>
<ul>
<li><strong>Agent / SDK setup</strong>：是用 <em>language SDK</em>（in-process profiler、跟 application code 一起部署）還是 <em>Grafana Alloy / Pyroscope agent</em>（out-of-process、適合 binary-only 或無法改 code 的 workload）— 兩條路 overhead、覆蓋率、tag 注入方式都不同</li>
<li><strong>Push or pull model</strong>：SDK 預設 <em>push</em>（application 主動把 profile sample 推到 Pyroscope server）、Alloy / agent 可走 <em>pull</em>（scrape pprof endpoint、跟 Prometheus 同模型）— push 適合 short-lived job / serverless、pull 適合 long-running service + Kubernetes service discovery</li>
<li><strong>Grafana integration</strong>：是否在 Grafana datasource 設好 Pyroscope、explore 是否能跨 trace / log / profile 跳轉（Tempo trace → Pyroscope profile by service+span）、dashboard 是否內嵌 flame graph panel</li>
<li><strong>Tag schema discipline</strong>：service / version / region / environment / pod 是否一致命名、deploy event 是否打 label 讓 baseline / candidate 比較可成立</li>
</ul>
<p>四件事任一缺失、profile 就只是「能看 flame graph」而非「release gate evidence」、無法支撐 <a href="/blog/backend/09-performance-capacity/improvement-loop/" data-link-title="9.9 Performance Improvement Loop" data-link-desc="壓測 → profile → fix → re-test → release gate 的閉環">9.9 Performance Improvement Loop</a> 的 diff workflow。</p>
<h2 id="適用場景">適用場景</h2>
<p>自管 profiling backend 適合 Pyroscope。團隊若有資料主權、成本控制、內網部署或 OSS-first 要求，可以用 Pyroscope 保存 profile，降低 profile sample 外送帶來的治理成本。</p>
<p>Profile diff workflow 適合 Pyroscope。Release candidate、canary、baseline review 或 incident after-action 都可以用時間區間比較，找出 CPU、memory 或 allocation 的相對變化。</p>
<p>Grafana stack 整合適合 Pyroscope。若服務已經有 Grafana dashboard，profile link 可以放進 latency、CPU、memory、cost 或 release dashboard，讓 SRE 從聚合訊號跳到 callstack。</p>
<h2 id="選型判準">選型判準</h2>
<table>
  <thead>
      <tr>
          <th>判準</th>
          <th>Pyroscope 的價值</th>
          <th>需要補的能力</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>OSS / self-host</td>
          <td>profile 資料可自管</td>
          <td>backend storage、retention、upgrade</td>
      </tr>
      <tr>
          <td>Grafana 整合</td>
          <td>dashboard、explore、profile link 容易串接</td>
          <td>tag schema 與 dashboard discipline</td>
      </tr>
      <tr>
          <td>Profile diff</td>
          <td>時間區間與版本對比直觀</td>
          <td>deploy label 與 baseline 管理</td>
      </tr>
      <tr>
          <td>多語言 agent</td>
          <td>常見 runtime 可導入</td>
          <td>agent overhead 與覆蓋差異量測</td>
      </tr>
  </tbody>
</table>
<p>OSS / self-host 價值來自控制權。Profile 可能包含 function name、package path、tenant-specific code path 或敏感 business logic，自管能讓資料保存與存取控制更貼近內部規範。</p>
<p>Grafana 整合價值來自操作連續性。當 CPU dashboard、latency dashboard 與 deploy annotation 都在 Grafana 中，Pyroscope 能讓工程師從圖表直接切到 flame graph。</p>
<h2 id="跟其他工具的取捨">跟其他工具的取捨</h2>
<p>Pyroscope 和 Datadog Continuous Profiler 的主要差異是平台責任。Pyroscope 偏 OSS / self-host / Grafana stack；Datadog 偏 SaaS all-in-one 與 APM product workflow。</p>
<p>Pyroscope 和 Parca 的主要差異是生態定位。Pyroscope 偏 Grafana profiling backend 與 developer-facing flame graph；Parca 偏 eBPF / infrastructure-wide profiling 與 CNCF 生態。</p>
<p>Pyroscope 和一次性 profiler 的主要差異是可比較性。一次性 profiler 擅長局部調查；Pyroscope 擅長讓 profile 成為 release baseline 與 incident evidence。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Pyroscope（Grafana）</th>
          <th>Parca</th>
          <th>Datadog Continuous Profiler</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>部署模型</td>
          <td>OSS self-host / Grafana Cloud Profiles SaaS</td>
          <td>OSS self-host（CNCF Sandbox）</td>
          <td>SaaS only</td>
      </tr>
      <tr>
          <td>Profile 來源</td>
          <td>language SDK + Alloy / agent（push 為主）</td>
          <td>pprof scrape（pull）+ Parca Agent（eBPF）</td>
          <td>Datadog Agent + language tracer 整合</td>
      </tr>
      <tr>
          <td>語言覆蓋</td>
          <td>Go / Python / Java / Ruby / .NET / Rust / Node</td>
          <td>任何能輸出 pprof 的 runtime + eBPF system-wide</td>
          <td>Go / Python / Java / Ruby / .NET / Node</td>
      </tr>
      <tr>
          <td>Tag / label</td>
          <td>Prometheus-style label + 自訂 tag</td>
          <td>Prometheus-style label</td>
          <td>Datadog tag（跟 APM 共用）</td>
      </tr>
      <tr>
          <td>Diff workflow</td>
          <td>時間區間 + label 對比 + flame graph diff UI</td>
          <td>時間區間 + label 對比</td>
          <td>自動跟 deploy event + trace span 關聯</td>
      </tr>
      <tr>
          <td>整合方向</td>
          <td>Grafana（Tempo / Loki / Mimir 互跳）</td>
          <td>Prometheus / Grafana（弱整合）</td>
          <td>Datadog APM / Logs / Metrics 同 plane</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>Grafana-first、OSS-friendly、release diff 主流程</td>
          <td>infrastructure-wide eBPF profiling、CNCF 生態</td>
          <td>Datadog 已是主 observability、要 APM 連動</td>
      </tr>
  </tbody>
</table>
<p>選 Pyroscope 的核心訴求：<em>已用 Grafana stack + 多語言服務組合 + 要 OSS self-host 選項或預算敏感</em>、profile 主要用途是 release diff / incident hot-path 定位、不需要 APM-level 自動 trace 關聯。</p>
<h2 id="操作成本">操作成本</h2>
<p>Pyroscope 的主要成本是自管 backend。Profile ingest、storage、retention、compaction、backup、upgrade 與 dashboard ownership 都需要團隊負責。</p>
<p>Tag 成本來自查詢維度。service、version、region、environment、runtime、pod、tenant 這些 label 能提高定位能力，也會增加 cardinality、儲存與查詢成本。</p>
<p>Agent 成本來自 rollout 與 overhead。導入時要先選代表性服務，量測 profiler 對 CPU、memory、latency 的影響，再逐步擴大到 critical path。</p>
<h2 id="evidence-package">Evidence Package</h2>
<p>Pyroscope 結果應回寫到 evidence package。最小欄位包括 service、version、environment、profile type、baseline window、candidate window、profile diff link、tag set、retention policy、overhead estimate、known gap 與 owner。</p>
<table>
  <thead>
      <tr>
          <th>欄位</th>
          <th>Pyroscope 證據來源</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Source</td>
          <td>profile query、flame graph、diff link</td>
      </tr>
      <tr>
          <td>Time range</td>
          <td>baseline / candidate profile window</td>
      </tr>
      <tr>
          <td>Query link</td>
          <td>Grafana / Pyroscope explore link</td>
      </tr>
      <tr>
          <td>Data quality</td>
          <td>tag completeness、sampling status</td>
      </tr>
      <tr>
          <td>Confidence</td>
          <td>production coverage、agent overhead</td>
      </tr>
      <tr>
          <td>Known gap</td>
          <td>未覆蓋 runtime、tag drift、retention gap</td>
      </tr>
  </tbody>
</table>
<p>Evidence package 的核心用途是讓 profile diff 成為 release artifact。Reviewer 要能從 release gate 打開 Pyroscope diff，確認變化來自 code path、runtime 行為、負載變化或 baseline drift。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Grafana Cloud Profiles</strong>：商業 SaaS 版本、走 Grafana Cloud 計費（per-series 或 per-profile bytes）、適合不想自管 storage / retention / compaction 的團隊。跟 OSS Pyroscope 共用 SDK 跟 query API、可在 OSS 起步、規模到一定程度再遷移到 Cloud、避免廠商一開始就鎖死。</p>
<p><strong>Flame graph diff</strong>：Pyroscope 的核心 release workflow — 選 baseline window（release 前 24hr）跟 candidate window（release 後 24hr）、UI 把兩張 flame graph 差異標紅綠、可直接看到哪個 function 變慢 / 變快。判讀要點是 <em>baseline window 要排除部署當下的 warm-up / cache miss spike</em>、否則 diff 噪音蓋過真實 regression。</p>
<p><strong>多語言 SDK 覆蓋</strong>：Pyroscope 官方 SDK 覆蓋 Go / Python / Java / Ruby / .NET / Rust / Node.js — Go SDK 用 <code>runtime/pprof</code> 包裝、Java 走 async-profiler、Python 走 <code>py-spy</code> 風格 sampling profiler、Node.js 走 V8 sampling。各 SDK overhead 不一致（Java async-profiler ~1%、Python py-spy ~3-5%）、選型時要看代表性服務量測再 rollout、不能假設「都很低」。</p>
<p><strong>Adhoc profiling</strong>：當 production SDK 沒裝、或想對 batch job / CLI tool 做一次性 profile、可用 Pyroscope CLI 上傳 <em>standalone pprof file</em>（<code>pyroscope adhoc</code> 或 <code>profilecli</code>）— 補位「標準 pprof endpoint 不夠用、但又不想長期 instrument」的情境。對 ad-hoc incident investigation 跟 batch job postmortem 特別有用。</p>
<p><strong>Grafana Alloy 整合</strong>：Grafana Alloy（前 Grafana Agent）內建 Pyroscope receiver、可同時 scrape Prometheus metrics + tail Loki log + push Tempo trace + scrape Pyroscope profile、單一 agent 跨 four signal、降低 sidecar 數量跟維運成本。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>SDK overhead 過高 / latency p99 上升</strong>：profile sample rate 太高、或 Java async-profiler 在低 CPU host 競爭 schedule — 降 sample rate、staging 量測 CPU / latency delta 確認 &lt; 3% 再 promote</li>
<li><strong>Push agent 跟 pull agent 取捨錯</strong>：short-lived job 用 pull 結果還沒被 scrape 就 exit、long-running service 用 push 結果 Pyroscope server 過載 — short-lived / serverless 走 SDK push、long-running + Kubernetes service discovery 走 Alloy pull</li>
<li><strong>Label cardinality 爆 / storage 跟查詢都慢</strong>：tag 加了 pod name / request ID / user ID 等高 cardinality 維度 — 限制 tag 為 service / version / region / environment / cluster 等低 cardinality、高基數維度走 trace / log 別放 profile</li>
<li><strong>Baseline / candidate diff 全是噪音</strong>：baseline window 沒對齊流量模式（off-peak vs peak）、或 deploy label 沒打 — 要求 release pipeline 自動寫 <code>version</code> / <code>deploy_id</code> label、diff window 跨完整流量週期（24hr or 7day）</li>
<li><strong>Grafana datasource 連不到 / explore 跳轉失敗</strong>：datasource URL 設錯、或 service / span tag 不一致 — Tempo trace 用的 <code>service.name</code> 要跟 Pyroscope <code>service</code> label 對齊、否則 cross-signal 跳轉斷裂</li>
<li><strong>Storage / retention 失控</strong>：profile 保留太久、SmartStore-like 冷儲存沒設 — Pyroscope OSS 支援 object storage（S3 / GCS）backend、長 retention 必開、不然 PV 會爆</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>已用 Datadog APM、要 trace ↔ profile 自動關聯</td>
          <td><a href="/blog/backend/09-performance-capacity/vendors/datadog-continuous-profiler/" data-link-title="Datadog Continuous Profiler" data-link-desc="用 SaaS APM 整合、deployment marker 與 profile diff 支援 release regression 定位的 profiling 工具">Datadog Continuous Profiler</a></td>
      </tr>
      <tr>
          <td>要 eBPF system-wide / infrastructure profiling</td>
          <td><a href="/blog/backend/09-performance-capacity/vendors/parca/" data-link-title="Parca" data-link-desc="用 eBPF 與開源 continuous profiling 平台建立 infrastructure-wide profile evidence 的工具">Parca</a></td>
      </tr>
      <tr>
          <td>不想自管 backend、但要 Grafana stack</td>
          <td>Grafana Cloud Profiles（商業 SaaS、同 SDK）</td>
      </tr>
  </tbody>
</table>
<h2 id="案例回寫">案例回寫</h2>
<p>Pyroscope 適合回寫 OSS observability 與 release diff 案例。它可接 <a href="/blog/backend/09-performance-capacity/cases/netflix-aurora-consolidation/" data-link-title="9.C23 Netflix：把關聯式 DB 統一到 Aurora、效能 &#43;75%、成本 -28%" data-link-desc="Netflix 把多套關聯式 DB 統一到 Aurora、效能提升 75%、成本下降 28%、串流數十億小時">9.C23 Netflix Aurora consolidation</a> 的 profile noise 降低、<a href="/blog/backend/09-performance-capacity/cases/tubi-elasticache-ml-feature-store/" data-link-title="9.C25 Tubi：從 ScyllaDB 遷到 ElastiCache、ML feature store 達 sub-10ms p99" data-link-desc="Tubi 把 ML 推薦的 feature store 從 ScyllaDB 遷到 ElastiCache for Redis、99 百分位延遲降到 10ms 以下">9.C25 Tubi feature store</a> 的 hot path 定位、<a href="/blog/backend/09-performance-capacity/cases/riot-games-eks-multi-cluster/" data-link-title="9.C12 Riot Games：246 個 EKS cluster 的多遊戲多地區治理" data-link-desc="Riot Games 從 Mesos 遷移到 EKS、用 246 個 cluster 跨遊戲跨地區治理、年省 1000 萬美金">9.C12 Riot Games EKS multi-cluster</a> 的 single-tenant per game profile 隔離、<a href="/blog/backend/09-performance-capacity/cases/capcom-gaming-dynamodb-eks/" data-link-title="9.C19 Capcom：Resident Evil / Monster Hunter 在 DynamoDB &#43; EKS 上的遊戲後端" data-link-desc="Capcom 把 Resident Evil、Street Fighter、Monster Hunter 遊戲後端跑在 DynamoDB &#43; EKS、單一秒位數延遲、營運成本降 30%">9.C19 Capcom 遊戲後端</a> 的 30% 成本下降 hot path 分析，以及 <a href="/blog/backend/09-performance-capacity/improvement-loop/" data-link-title="9.9 Performance Improvement Loop" data-link-desc="壓測 → profile → fix → re-test → release gate 的閉環">9.9 Improvement Loop</a> 的 baseline / candidate profile diff。</p>
<p>這些案例的重點是可比較 profile。Pyroscope 頁引用案例時，要把 case 轉成 tag schema、baseline window、candidate window、flame graph diff 與 release gate evidence — 例如 Riot Games 246 cluster 的 tag schema 必須涵蓋 game / region / cluster 三維、才能避免「跨遊戲混合 profile」的歸因錯誤。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/09-performance-capacity/improvement-loop/" data-link-title="9.9 Performance Improvement Loop" data-link-desc="壓測 → profile → fix → re-test → release gate 的閉環">9.9 Performance Improvement Loop</a></li>
<li>上游：<a href="/blog/backend/09-performance-capacity/performance-observability/" data-link-title="9.8 效能可觀測性" data-link-desc="saturation metric、USE / RED method、cost dashboard">9.8 效能可觀測性</a></li>
<li>跨模組：<a href="/blog/backend/04-observability/continuous-profiling/" data-link-title="4.9 Continuous Profiling" data-link-desc="把 CPU / memory / lock profile 從一次性除錯升級為持續訊號">4.9 Continuous Profiling</a></li>
<li>平行：<a href="/blog/backend/09-performance-capacity/vendors/datadog-continuous-profiler/" data-link-title="Datadog Continuous Profiler" data-link-desc="用 SaaS APM 整合、deployment marker 與 profile diff 支援 release regression 定位的 profiling 工具">Datadog Continuous Profiler</a></li>
<li>平行：<a href="/blog/backend/09-performance-capacity/vendors/parca/" data-link-title="Parca" data-link-desc="用 eBPF 與開源 continuous profiling 平台建立 infrastructure-wide profile evidence 的工具">Parca</a></li>
<li>官方：<a href="https://grafana.com/docs/pyroscope/latest/">Grafana Pyroscope documentation</a></li>
</ul>
]]></content:encoded></item><item><title>Parca</title><link>https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/parca/</link><pubDate>Fri, 15 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/parca/</guid><description>&lt;p>Parca 的核心責任是用開源 continuous profiling 與 eBPF 路線建立 infrastructure-wide profile evidence。它適合需要低侵入、跨 process、跨 service、偏平台層的 profiling 團隊，重點在用 always-on profile 找出 CPU、memory、runtime 與 kernel / user space 的資源熱點。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Parca 是 Polar Signals 主導的 OSS continuous profiling、特色是 &lt;em>eBPF-based 採集 + pprof 標準格式 + Prometheus-style 拉取與 label 模型&lt;/em>。它跟 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/pyroscope/" data-link-title="Pyroscope" data-link-desc="用 Grafana 生態與開源 profiling backend 建立可自管 profile diff 與 flame graph 的工具">Pyroscope&lt;/a> 是 OSS 同類、跟 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/datadog-continuous-profiler/" data-link-title="Datadog Continuous Profiler" data-link-desc="用 SaaS APM 整合、deployment marker 與 profile diff 支援 release regression 定位的 profiling 工具">Datadog Continuous Profiler&lt;/a> 則是 OSS / 自管 vs SaaS / APM 整合的差異。eBPF agent 直接從 kernel 採 stack trace、不需要 application 改 code 或注入 runtime agent；pprof 格式讓既有 Go / Java / Python 工具鏈可以直接讀；Prometheus-style scrape 讓 Parca server 跟 metrics 用同一套 service discovery 與 label。&lt;/p>
&lt;h2 id="最短判讀路徑">最短判讀路徑&lt;/h2>
&lt;p>判斷 Parca 部署是否能撐起 platform-wide profiling、最少看四件事：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>eBPF agent deploy&lt;/strong>：Parca Agent 走 DaemonSet 跑在每個 node、需要 kernel ≥ 4.18（CO-RE / BTF）、&lt;code>SYS_ADMIN&lt;/code> 或 &lt;code>PERF_EVENT&lt;/code> capability、host PID namespace。受管 Kubernetes（GKE / EKS / AKS）的 worker node 是否允許這個權限是第一個判讀點&lt;/li>
&lt;li>&lt;strong>Parca server scrape&lt;/strong>：server 跟 agent 走 pull-based、Prometheus-style ServiceMonitor / scrape config、label 跟 metrics 同模型（namespace / pod / container / node）。scrape interval、retention、storage backend（FrostDB 內建 / object storage）要明確&lt;/li>
&lt;li>&lt;strong>pprof query&lt;/strong>：profile 以 pprof format 存、Parca UI 提供 flame graph 與 compare view、也可 export pprof file 給 &lt;code>go tool pprof&lt;/code> 或其他既有工具離線分析&lt;/li>
&lt;li>&lt;strong>Grafana integration&lt;/strong>：Parca 提供 datasource plugin、profile 可以跟 metrics / log / trace 在 Grafana 同一頁 correlate、配 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/pyroscope/" data-link-title="Pyroscope" data-link-desc="用 Grafana 生態與開源 profiling backend 建立可自管 profile diff 與 flame graph 的工具">Pyroscope&lt;/a> 或 Tempo 形成 observability 對齊&lt;/li>
&lt;/ul>
&lt;p>四件事任一缺失、就是 profiling control plane 還沒上線的待補項目。&lt;/p></description><content:encoded><![CDATA[<p>Parca 的核心責任是用開源 continuous profiling 與 eBPF 路線建立 infrastructure-wide profile evidence。它適合需要低侵入、跨 process、跨 service、偏平台層的 profiling 團隊，重點在用 always-on profile 找出 CPU、memory、runtime 與 kernel / user space 的資源熱點。</p>
<h2 id="服務定位">服務定位</h2>
<p>Parca 是 Polar Signals 主導的 OSS continuous profiling、特色是 <em>eBPF-based 採集 + pprof 標準格式 + Prometheus-style 拉取與 label 模型</em>。它跟 <a href="/blog/backend/09-performance-capacity/vendors/pyroscope/" data-link-title="Pyroscope" data-link-desc="用 Grafana 生態與開源 profiling backend 建立可自管 profile diff 與 flame graph 的工具">Pyroscope</a> 是 OSS 同類、跟 <a href="/blog/backend/09-performance-capacity/vendors/datadog-continuous-profiler/" data-link-title="Datadog Continuous Profiler" data-link-desc="用 SaaS APM 整合、deployment marker 與 profile diff 支援 release regression 定位的 profiling 工具">Datadog Continuous Profiler</a> 則是 OSS / 自管 vs SaaS / APM 整合的差異。eBPF agent 直接從 kernel 採 stack trace、不需要 application 改 code 或注入 runtime agent；pprof 格式讓既有 Go / Java / Python 工具鏈可以直接讀；Prometheus-style scrape 讓 Parca server 跟 metrics 用同一套 service discovery 與 label。</p>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Parca 部署是否能撐起 platform-wide profiling、最少看四件事：</p>
<ul>
<li><strong>eBPF agent deploy</strong>：Parca Agent 走 DaemonSet 跑在每個 node、需要 kernel ≥ 4.18（CO-RE / BTF）、<code>SYS_ADMIN</code> 或 <code>PERF_EVENT</code> capability、host PID namespace。受管 Kubernetes（GKE / EKS / AKS）的 worker node 是否允許這個權限是第一個判讀點</li>
<li><strong>Parca server scrape</strong>：server 跟 agent 走 pull-based、Prometheus-style ServiceMonitor / scrape config、label 跟 metrics 同模型（namespace / pod / container / node）。scrape interval、retention、storage backend（FrostDB 內建 / object storage）要明確</li>
<li><strong>pprof query</strong>：profile 以 pprof format 存、Parca UI 提供 flame graph 與 compare view、也可 export pprof file 給 <code>go tool pprof</code> 或其他既有工具離線分析</li>
<li><strong>Grafana integration</strong>：Parca 提供 datasource plugin、profile 可以跟 metrics / log / trace 在 Grafana 同一頁 correlate、配 <a href="/blog/backend/09-performance-capacity/vendors/pyroscope/" data-link-title="Pyroscope" data-link-desc="用 Grafana 生態與開源 profiling backend 建立可自管 profile diff 與 flame graph 的工具">Pyroscope</a> 或 Tempo 形成 observability 對齊</li>
</ul>
<p>四件事任一缺失、就是 profiling control plane 還沒上線的待補項目。</p>
<h2 id="定位">定位</h2>
<p>Parca 適合平台團隊建立 profiling control plane。當問題橫跨 Kubernetes cluster、node pool、multi-service path 或 shared runtime 成本，Parca 能從更接近 infrastructure 的角度收集 profile。</p>
<p>這個定位讓 Parca 接到 <a href="/blog/backend/09-performance-capacity/bottleneck-localization/" data-link-title="9.5 瓶頸定位流程" data-link-desc="從 app 到 DB / cache / broker / 第三方 quota 的逐層瓶頸定位">9.5 瓶頸定位流程</a> 與 <a href="/blog/backend/04-observability/continuous-profiling/" data-link-title="4.9 Continuous Profiling" data-link-desc="把 CPU / memory / lock profile 從一次性除錯升級為持續訊號">4.9 Continuous Profiling</a>。它的價值在於低侵入與平台廣度；它的代價在於 eBPF 支援、symbolization、storage、權限與平台維運責任。</p>
<h2 id="適用場景">適用場景</h2>
<p>Infrastructure-wide profiling 適合 Parca。平台團隊可以觀察 cluster、node、namespace、service 與 process 的 CPU 熱點，找出共同 library、runtime、sidecar、agent 或 kernel path 的成本。</p>
<p>Kubernetes 平台適合 Parca。當服務在多 namespace、多 workload、多 node pool 上運作，Parca 可以把 profile 維度接到 pod、container、node、namespace 與 label。</p>
<p>低侵入 profiling 適合 Parca。eBPF-based profiling 可以降低 application instrumentation 成本，讓團隊先取得廣域視角，再對特定服務加更細的 runtime profiler 或 APM 整合。</p>
<h2 id="選型判準">選型判準</h2>
<table>
  <thead>
      <tr>
          <th>判準</th>
          <th>Parca 的價值</th>
          <th>需要補的能力</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>eBPF / low overhead</td>
          <td>低侵入取得廣域 profile</td>
          <td>kernel / runtime 支援與權限治理</td>
      </tr>
      <tr>
          <td>Platform-wide</td>
          <td>node、namespace、service 維度可對照</td>
          <td>Kubernetes label 與 ownership discipline</td>
      </tr>
      <tr>
          <td>Open source</td>
          <td>profiling platform 可自管</td>
          <td>storage、retention、upgrade</td>
      </tr>
      <tr>
          <td>Compare / diff</td>
          <td>profile compare 支援退化定位</td>
          <td>deploy label、baseline 與 symbolization</td>
      </tr>
  </tbody>
</table>
<p>eBPF / low overhead 價值來自平台廣度。團隊可以先觀察整個基礎設施的 CPU 熱點，再決定哪些服務需要更深入的 application-level profiling。</p>
<p>Platform-wide 價值來自共同成本治理。Sidecar、agent、logging library、serialization library 或 runtime upgrade 的成本可能散在多個服務中，Parca 這類工具能把分散成本聚合回平台決策。</p>
<h2 id="跟其他工具的取捨">跟其他工具的取捨</h2>
<p>Parca 和 Datadog Continuous Profiler 的主要差異是平台模型。Parca 偏開源、自管、eBPF 與 infra-wide profiling；Datadog 偏 SaaS、APM drilldown、deployment marker 與產品化 workflow。</p>
<p>Parca 和 Pyroscope 的主要差異是視角。Pyroscope 偏 Grafana / application profiling backend；Parca 偏 eBPF、Kubernetes / infrastructure-level profiling 與平台團隊治理。</p>
<p>Parca 和 language runtime profiler 的主要差異是導入方式。Runtime profiler 能提供語言特定維度；Parca 能先提供低侵入廣域 profile，但 symbolization 與語言細節需要額外治理。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Parca</th>
          <th>Pyroscope</th>
          <th>Datadog Continuous Profiler</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>採集方式</td>
          <td>eBPF agent（kernel-level、unwound）</td>
          <td>eBPF + SDK 雙路、語言 SDK 較豐富</td>
          <td>APM agent 內建、語言 SDK 整合</td>
      </tr>
      <tr>
          <td>Profile format</td>
          <td>pprof（Google 標準）</td>
          <td>自家 + pprof export</td>
          <td>Datadog proprietary、可 export pprof</td>
      </tr>
      <tr>
          <td>採集模型</td>
          <td>Pull-based、Prometheus-style scrape</td>
          <td>Push or pull（Grafana Agent）</td>
          <td>Push to Datadog backend</td>
      </tr>
      <tr>
          <td>Label 模型</td>
          <td>Prometheus label（namespace / pod）</td>
          <td>Grafana label</td>
          <td>Datadog tag</td>
      </tr>
      <tr>
          <td>部署模型</td>
          <td>Self-hosted OSS + Polar Signals SaaS</td>
          <td>Self-hosted OSS + Grafana Cloud SaaS</td>
          <td>SaaS only</td>
      </tr>
      <tr>
          <td>Storage</td>
          <td>FrostDB 內建 / object storage</td>
          <td>自家 storage / Grafana backend</td>
          <td>Datadog managed</td>
      </tr>
      <tr>
          <td>APM 整合</td>
          <td>弱 — 走 Grafana correlation</td>
          <td>中 — Grafana stack 整合</td>
          <td>強 — trace ↔ profile drilldown 內建</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>Platform team 自管、Prometheus stack</td>
          <td>Grafana stack 已用、應用層 profiling</td>
          <td>已用 Datadog、APM-first、SaaS-only 可</td>
      </tr>
  </tbody>
</table>
<h2 id="進階主題">進階主題</h2>
<p><strong>Polar Signals Cloud</strong>：Parca 上游公司 Polar Signals 提供 managed SaaS — agent 一樣走 OSS、server / storage / UI 託管。適合不想養 Parca server 又要 OSS agent 路線的團隊。差異點是 ingestion cost 跟 retention 由 SaaS 計費、license / data residency 要看合約。</p>
<p><strong>Prometheus 同 label model</strong>：Parca 的 service discovery、scrape config 跟 label 跟 Prometheus 幾乎同形 — 既有 ServiceMonitor、relabel rule、Kubernetes SD 可以直接複用。意義是 profile 維度跟 metric 維度天然對齊、<code>namespace=foo, service=bar</code> 在兩邊都成立、cross-signal correlation 不需要再 mapping。</p>
<p><strong>Compare profiles（diff before/after deploy）</strong>：Parca UI 支援選 baseline window 跟 candidate window 做 flame graph diff、顏色標示哪個 stack frame 變胖變瘦。配 <a href="/blog/backend/09-performance-capacity/improvement-loop/" data-link-title="9.9 Performance Improvement Loop" data-link-desc="壓測 → profile → fix → re-test → release gate 的閉環">9.9 Performance Improvement Loop</a> 的 deploy marker、可以把「這次發版讓 CPU +15%」直接歸因到具體 frame。</p>
<p><strong>Continuous profiling vs sampling-only</strong>：傳統 profiler 是「出問題時手動跑 30 秒」、Parca 是「always-on、低頻率持續採」。差異是 <em>事後回溯能力</em> — incident 發生時直接拉時間區間的 profile、不用重現問題；sampling-only 工具在偶發 spike 時抓不到現場。代價是 storage 跟 agent overhead 要長期治理。</p>
<h2 id="操作成本">操作成本</h2>
<p>Parca 的主要成本是平台維運。Agent / scraper、server、storage、retention、symbolization、upgrade 與 Kubernetes 權限都需要平台團隊負責。</p>
<p>Symbolization 成本來自可讀性。Profile 如果缺 symbol、debug info、build ID 或 source mapping，flame graph 會變成難以行動的 address / binary offset，因此 build pipeline 要保留符號資訊策略。</p>
<p>權限成本來自 eBPF 與 node visibility。低層 profiling 需要足夠 host / kernel 權限，受管 Kubernetes、security policy、multi-tenant cluster 與 compliance 要先評估。</p>
<h2 id="evidence-package">Evidence Package</h2>
<p>Parca 結果應回寫到 evidence package。最小欄位包括 cluster、namespace、service、node pool、profile type、baseline window、candidate window、compare link、symbolization status、agent overhead、known gap 與 owner。</p>
<table>
  <thead>
      <tr>
          <th>欄位</th>
          <th>Parca 證據來源</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Source</td>
          <td>Parca query、compare view、flame graph</td>
      </tr>
      <tr>
          <td>Time range</td>
          <td>baseline / candidate profile window</td>
      </tr>
      <tr>
          <td>Query link</td>
          <td>Parca UI / dashboard / metrics link</td>
      </tr>
      <tr>
          <td>Data quality</td>
          <td>label completeness、symbolization status</td>
      </tr>
      <tr>
          <td>Confidence</td>
          <td>cluster coverage、agent overhead</td>
      </tr>
      <tr>
          <td>Known gap</td>
          <td>未覆蓋 node、symbol 缺失、kernel 限制</td>
      </tr>
  </tbody>
</table>
<p>Evidence package 的核心用途是把平台層 profile 變成容量決策。Reviewer 要能看到成本來自 application code、runtime、sidecar、kernel path 還是 shared library，並把結果回寫到 owner。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>eBPF agent 起不來 / kernel 不支援</strong>：舊 kernel（&lt; 4.18）或缺 BTF / CO-RE 支援、受管 Kubernetes 不開 <code>SYS_ADMIN</code> — 先確認 node OS image、必要時換 distribution 或升級 worker node pool</li>
<li><strong>Profile storage 暴增</strong>：scrape interval 太密 + retention 沒設 + label cardinality 爆炸（把 request-id 放進 label）— 降頻、限 retention window、把高 cardinality 維度移出 profile label</li>
<li><strong>Symbol resolution 失敗 / flame graph 全是 address</strong>：build pipeline 沒保留 debug info、stripped binary、容器 image 不含符號 — 在 build 階段保留 debug symbol、用 separate debuginfo 上傳 Parca debuginfod、或在 image 保留 unstripped binary</li>
<li><strong>JIT 語言（Java / Node.js）stack 不完整</strong>：eBPF 看到的是 native frame、JIT-compiled frame 需要額外 perf map / JVMTI agent — 補語言層 profiler 或開 JIT symbol dump</li>
<li><strong>Agent overhead 影響 production</strong>：sample rate 預設 19 Hz、特定 workload 可能仍敏感 — 在 noisy neighbor 敏感的 node pool 降頻或排除特定 namespace</li>
<li><strong>多 cluster scrape 中心化太重</strong>：單一 Parca server 拉 N 個 cluster 變瓶頸 — 改 federation 模型、每 cluster 一個 Parca server、上層做 query aggregation</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>Parca 適合回寫平台層與 multi-service 成本案例。它可接 <a href="/blog/backend/09-performance-capacity/cases/gcp-130k-node-gke-cluster/" data-link-title="9.C34 GCP：130,000-node GKE cluster 的工程極限" data-link-desc="Google 用單一 GKE control plane 跑 13 萬個 node、AI workload &#43; 1000 Pods/sec 創建吞吐">9.C34 GCP 130K node GKE cluster</a> 的 cluster-scale profiling 需求、<a href="/blog/backend/09-performance-capacity/cases/riot-games-eks-multi-cluster/" data-link-title="9.C12 Riot Games：246 個 EKS cluster 的多遊戲多地區治理" data-link-desc="Riot Games 從 Mesos 遷移到 EKS、用 246 個 cluster 跨遊戲跨地區治理、年省 1000 萬美金">9.C12 Riot Games EKS multi-cluster</a> 的 246 cluster 平台成本治理、<a href="/blog/backend/09-performance-capacity/cases/netflix-aurora-consolidation/" data-link-title="9.C23 Netflix：把關聯式 DB 統一到 Aurora、效能 &#43;75%、成本 -28%" data-link-desc="Netflix 把多套關聯式 DB 統一到 Aurora、效能提升 75%、成本下降 28%、串流數十億小時">9.C23 Netflix Aurora consolidation</a> 的 shared platform noise 降低、<a href="/blog/backend/09-performance-capacity/cases/maersk-bosch-azure-aks/" data-link-title="9.C33 Maersk &#43; Bosch：傳統產業在 Azure AKS 上的微服務治理" data-link-desc="全球海運 Maersk 跟 Bosch 智慧建築把 AKS 當微服務治理基礎、釋放工程資源做業務功能">9.C33 Maersk + Bosch Azure AKS</a> 的傳統產業多 BU 平台層歸因，以及 <a href="/blog/backend/09-performance-capacity/cases/capcom-gaming-dynamodb-eks/" data-link-title="9.C19 Capcom：Resident Evil / Monster Hunter 在 DynamoDB &#43; EKS 上的遊戲後端" data-link-desc="Capcom 把 Resident Evil、Street Fighter、Monster Hunter 遊戲後端跑在 DynamoDB &#43; EKS、單一秒位數延遲、營運成本降 30%">9.C19 Capcom DynamoDB + EKS</a> 跨遊戲共用後端的 profile 切分。</p>
<p>這些案例的重點是平台視角。Parca 頁引用案例時，要把 case 轉成 cluster / namespace / service label、compare window、symbolization、shared library cost 與 owner routing — 例如 GCP 130K-node 規模下，Parca 自身的 storage / scrape capacity 也成為 profile target、不只是觀測 application。</p>
<p>兩個典型用途值得單獨點名：</p>
<ul>
<li><strong>Performance regression detection</strong>：發版前後拉 compare profile、把「這次 release 讓 P99 CPU +18%」歸因到具體 stack frame。配 <a href="/blog/backend/09-performance-capacity/cases/riot-games-eks-multi-cluster/" data-link-title="9.C12 Riot Games：246 個 EKS cluster 的多遊戲多地區治理" data-link-desc="Riot Games 從 Mesos 遷移到 EKS、用 246 個 cluster 跨遊戲跨地區治理、年省 1000 萬美金">9.C12 Riot Games EKS multi-cluster</a> 的 246 cluster 規模、單一 service rollout 在 always-on profile 下可秒級看出 hot path 變化、不需要等 SRE 跑手動 pprof</li>
<li><strong>Cost engineering</strong>：把 CPU profile 折算成 node 成本、找出 shared library / runtime / sidecar 的 hidden cost。配 <a href="/blog/backend/09-performance-capacity/cases/netflix-aurora-consolidation/" data-link-title="9.C23 Netflix：把關聯式 DB 統一到 Aurora、效能 &#43;75%、成本 -28%" data-link-desc="Netflix 把多套關聯式 DB 統一到 Aurora、效能提升 75%、成本下降 28%、串流數十億小時">9.C23 Netflix Aurora consolidation</a> 的 platform consolidation 思路、profile 證據可以決定要不要重寫熱點、換 library、還是接受成本</li>
</ul>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/09-performance-capacity/bottleneck-localization/" data-link-title="9.5 瓶頸定位流程" data-link-desc="從 app 到 DB / cache / broker / 第三方 quota 的逐層瓶頸定位">9.5 瓶頸定位流程</a></li>
<li>上游：<a href="/blog/backend/09-performance-capacity/improvement-loop/" data-link-title="9.9 Performance Improvement Loop" data-link-desc="壓測 → profile → fix → re-test → release gate 的閉環">9.9 Performance Improvement Loop</a></li>
<li>跨模組：<a href="/blog/backend/04-observability/continuous-profiling/" data-link-title="4.9 Continuous Profiling" data-link-desc="把 CPU / memory / lock profile 從一次性除錯升級為持續訊號">4.9 Continuous Profiling</a></li>
<li>平行：<a href="/blog/backend/09-performance-capacity/vendors/datadog-continuous-profiler/" data-link-title="Datadog Continuous Profiler" data-link-desc="用 SaaS APM 整合、deployment marker 與 profile diff 支援 release regression 定位的 profiling 工具">Datadog Continuous Profiler</a></li>
<li>平行：<a href="/blog/backend/09-performance-capacity/vendors/pyroscope/" data-link-title="Pyroscope" data-link-desc="用 Grafana 生態與開源 profiling backend 建立可自管 profile diff 與 flame graph 的工具">Pyroscope</a></li>
<li>官方：<a href="https://www.parca.dev/docs/">Parca documentation</a></li>
</ul>
]]></content:encoded></item><item><title>效能與容量工具清單</title><link>https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/</link><pubDate>Fri, 15 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/</guid><description>&lt;p>效能與容量工具清單的核心責任是把工具名稱放回 workload model、saturation discovery、capacity planning 與 production validation 的服務責任。工具頁先回答它降低哪一種風險，再討論 scenario scripting、distributed load、結果保存、CI 整合、成本與案例回寫。&lt;/p>
&lt;h2 id="讀法">讀法&lt;/h2>
&lt;p>效能工具要從問題節點進入。團隊如果缺 workload model，先讀 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/workload-modeling/" data-link-title="9.2 Workload Modeling" data-link-desc="把 production traffic shape 翻成可重播的壓測模型">9.2 Workload Modeling&lt;/a>；如果缺 saturation 邊界，先讀 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/saturation-discovery/" data-link-title="9.4 Saturation Discovery" data-link-desc="找出 throughput plateau 與 latency knee 的方法">9.4 Saturation Discovery&lt;/a>；如果缺 production 驗證，先讀 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/production-validation/" data-link-title="9.10 Production-Side 驗證" data-link-desc="shadow traffic、dark launch、canary、production-like load test">9.10 Production-Side 驗證&lt;/a>。&lt;/p>
&lt;p>工具頁的任務是承接這些問題節點。k6、JMeter、Gatling、Locust 與 Vegeta 都能產生負載，但它們在腳本語言、protocol 覆蓋、分散式執行、CI integration、報表與團隊學習成本上不同；production replay、profiling 與 cost analysis 工具則承擔不同的證據責任。&lt;/p>
&lt;h2 id="教學順序同步">教學順序同步&lt;/h2>
&lt;p>效能與容量工具頁的教學順序是先建立 load test，再進入 replay / mirroring、profiling、optimization 與 FinOps。這個順序對齊 checkout E7：讀者先理解 workload model、saturation evidence 與 capacity gate，再比較 production traffic evidence、profile evidence、rightsizing 建議與成本 owner 如何形成改善閉環。&lt;/p>
&lt;h2 id="t1-工具頁">T1 工具頁&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>工具&lt;/th>
 &lt;th>類型&lt;/th>
 &lt;th>核心責任&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/k6/" data-link-title="k6" data-link-desc="用 scriptable scenario 建立 API、protocol 與 CI 友善壓測的效能工程工具">k6&lt;/a>&lt;/td>
 &lt;td>Load test&lt;/td>
 &lt;td>用 scriptable scenario 建立 API / protocol 負載&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/jmeter/" data-link-title="Apache JMeter" data-link-desc="用 GUI、plugin 與多 protocol sampler 承接企業壓測資產的效能工程工具">JMeter&lt;/a>&lt;/td>
 &lt;td>Load test&lt;/td>
 &lt;td>用 GUI、plugin 與多 protocol sampler 承接企業測試資產&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/gatling/" data-link-title="Gatling" data-link-desc="用 JVM DSL、simulation 與 injection profile 表達複雜 scenario 的效能工程工具">Gatling&lt;/a>&lt;/td>
 &lt;td>Load test&lt;/td>
 &lt;td>用 JVM DSL 與 injection profile 表達複雜 scenario&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/locust/" data-link-title="Locust" data-link-desc="用 Python user behavior 與 distributed worker 表達高自訂負載模型的效能工程工具">Locust&lt;/a>&lt;/td>
 &lt;td>Load test&lt;/td>
 &lt;td>用 Python user behavior 與 distributed worker 表達高自訂負載&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/vegeta/" data-link-title="Vegeta" data-link-desc="用簡潔 CLI 與固定 rate HTTP attack 快速探測 latency、throughput 與 saturation 的效能工程工具">Vegeta&lt;/a>&lt;/td>
 &lt;td>HTTP probe&lt;/td>
 &lt;td>用固定 rate HTTP attack 快速探測 endpoint saturation&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/goreplay/" data-link-title="GoReplay" data-link-desc="用 production HTTP traffic capture 與 replay 驗證真實請求形狀的效能工程工具">GoReplay&lt;/a>&lt;/td>
 &lt;td>Traffic replay&lt;/td>
 &lt;td>捕捉 production HTTP traffic 並重播到 shadow target&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/service-mesh-mirroring/" data-link-title="Service Mesh Mirroring" data-link-desc="用 sidecar / proxy 層 mirror production traffic 到新版本或 shadow service 的 production validation 方式">Service Mesh Mirroring&lt;/a>&lt;/td>
 &lt;td>Traffic mirror&lt;/td>
 &lt;td>用 proxy route policy mirror production traffic&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/aws-vpc-traffic-mirroring/" data-link-title="AWS VPC Traffic Mirroring" data-link-desc="用 VPC 網路層封包鏡像觀察 production traffic 的低侵入 production validation 方式">AWS VPC Traffic Mirroring&lt;/a>&lt;/td>
 &lt;td>Traffic mirror&lt;/td>
 &lt;td>用 VPC 網路層封包鏡像建立低侵入 production evidence&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/datadog-continuous-profiler/" data-link-title="Datadog Continuous Profiler" data-link-desc="用 SaaS APM 整合、deployment marker 與 profile diff 支援 release regression 定位的 profiling 工具">Datadog Continuous Profiler&lt;/a>&lt;/td>
 &lt;td>Profiling&lt;/td>
 &lt;td>用 SaaS APM 整合與 deploy marker 支援 profile diff&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/pyroscope/" data-link-title="Pyroscope" data-link-desc="用 Grafana 生態與開源 profiling backend 建立可自管 profile diff 與 flame graph 的工具">Pyroscope&lt;/a>&lt;/td>
 &lt;td>Profiling&lt;/td>
 &lt;td>用 Grafana / OSS profiling backend 建立可自管 profile diff&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/parca/" data-link-title="Parca" data-link-desc="用 eBPF 與開源 continuous profiling 平台建立 infrastructure-wide profile evidence 的工具">Parca&lt;/a>&lt;/td>
 &lt;td>Profiling&lt;/td>
 &lt;td>用 eBPF 與平台視角建立 infrastructure-wide profile evidence&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/akamas/" data-link-title="Akamas" data-link-desc="用 AI-driven optimization 把效能、可靠性與雲端成本放進同一個容量調校閉環">Akamas&lt;/a>&lt;/td>
 &lt;td>Optimization&lt;/td>
 &lt;td>用 SLO constraint 與配置實驗建立 capacity / cost 調校閉環&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/vantage/" data-link-title="Vantage" data-link-desc="用 cloud cost reports、Kubernetes cost allocation 與 forecast 建立工程可用的成本可見性">Vantage&lt;/a>&lt;/td>
 &lt;td>FinOps&lt;/td>
 &lt;td>用 cost reports、Kubernetes cost 與 forecast 建立成本可見性&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/cloudhealth/" data-link-title="CloudHealth" data-link-desc="用 enterprise FinOps governance、policy 與多雲成本管理支援大型組織的容量成本治理">CloudHealth&lt;/a>&lt;/td>
 &lt;td>FinOps&lt;/td>
 &lt;td>用 enterprise governance、policy 與 allocation 管理雲端成本&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/aws-cost-explorer/" data-link-title="AWS Cost Explorer" data-link-desc="用 AWS-native 成本與用量分析建立 account、service、tag 與 usage type 的成本判讀入口">AWS Cost Explorer&lt;/a>&lt;/td>
 &lt;td>AWS FinOps&lt;/td>
 &lt;td>用 AWS-native cost / usage report 建立成本分析 baseline&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>這批工具頁已完成 load test、production traffic replay、continuous profiling 與 capacity / cost analysis 的主要分流。k6 承接 scriptable scenario，JMeter 承接企業測試資產，Gatling 承接 JVM simulation，Locust 承接 Python custom behavior，Vegeta 承接快速 HTTP probe；GoReplay、Service Mesh Mirroring 與 AWS VPC Traffic Mirroring 承接不同層級的 production traffic evidence；Datadog Continuous Profiler、Pyroscope 與 Parca 承接不同操作模型的 profile evidence；Akamas、Vantage、CloudHealth 與 AWS Cost Explorer 承接 cost visibility、optimization 與 FinOps governance。&lt;/p></description><content:encoded><![CDATA[<p>效能與容量工具清單的核心責任是把工具名稱放回 workload model、saturation discovery、capacity planning 與 production validation 的服務責任。工具頁先回答它降低哪一種風險，再討論 scenario scripting、distributed load、結果保存、CI 整合、成本與案例回寫。</p>
<h2 id="讀法">讀法</h2>
<p>效能工具要從問題節點進入。團隊如果缺 workload model，先讀 <a href="/blog/backend/09-performance-capacity/workload-modeling/" data-link-title="9.2 Workload Modeling" data-link-desc="把 production traffic shape 翻成可重播的壓測模型">9.2 Workload Modeling</a>；如果缺 saturation 邊界，先讀 <a href="/blog/backend/09-performance-capacity/saturation-discovery/" data-link-title="9.4 Saturation Discovery" data-link-desc="找出 throughput plateau 與 latency knee 的方法">9.4 Saturation Discovery</a>；如果缺 production 驗證，先讀 <a href="/blog/backend/09-performance-capacity/production-validation/" data-link-title="9.10 Production-Side 驗證" data-link-desc="shadow traffic、dark launch、canary、production-like load test">9.10 Production-Side 驗證</a>。</p>
<p>工具頁的任務是承接這些問題節點。k6、JMeter、Gatling、Locust 與 Vegeta 都能產生負載，但它們在腳本語言、protocol 覆蓋、分散式執行、CI integration、報表與團隊學習成本上不同；production replay、profiling 與 cost analysis 工具則承擔不同的證據責任。</p>
<h2 id="教學順序同步">教學順序同步</h2>
<p>效能與容量工具頁的教學順序是先建立 load test，再進入 replay / mirroring、profiling、optimization 與 FinOps。這個順序對齊 checkout E7：讀者先理解 workload model、saturation evidence 與 capacity gate，再比較 production traffic evidence、profile evidence、rightsizing 建議與成本 owner 如何形成改善閉環。</p>
<h2 id="t1-工具頁">T1 工具頁</h2>
<table>
  <thead>
      <tr>
          <th>工具</th>
          <th>類型</th>
          <th>核心責任</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/vendors/k6/" data-link-title="k6" data-link-desc="用 scriptable scenario 建立 API、protocol 與 CI 友善壓測的效能工程工具">k6</a></td>
          <td>Load test</td>
          <td>用 scriptable scenario 建立 API / protocol 負載</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/vendors/jmeter/" data-link-title="Apache JMeter" data-link-desc="用 GUI、plugin 與多 protocol sampler 承接企業壓測資產的效能工程工具">JMeter</a></td>
          <td>Load test</td>
          <td>用 GUI、plugin 與多 protocol sampler 承接企業測試資產</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/vendors/gatling/" data-link-title="Gatling" data-link-desc="用 JVM DSL、simulation 與 injection profile 表達複雜 scenario 的效能工程工具">Gatling</a></td>
          <td>Load test</td>
          <td>用 JVM DSL 與 injection profile 表達複雜 scenario</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/vendors/locust/" data-link-title="Locust" data-link-desc="用 Python user behavior 與 distributed worker 表達高自訂負載模型的效能工程工具">Locust</a></td>
          <td>Load test</td>
          <td>用 Python user behavior 與 distributed worker 表達高自訂負載</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/vendors/vegeta/" data-link-title="Vegeta" data-link-desc="用簡潔 CLI 與固定 rate HTTP attack 快速探測 latency、throughput 與 saturation 的效能工程工具">Vegeta</a></td>
          <td>HTTP probe</td>
          <td>用固定 rate HTTP attack 快速探測 endpoint saturation</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/vendors/goreplay/" data-link-title="GoReplay" data-link-desc="用 production HTTP traffic capture 與 replay 驗證真實請求形狀的效能工程工具">GoReplay</a></td>
          <td>Traffic replay</td>
          <td>捕捉 production HTTP traffic 並重播到 shadow target</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/vendors/service-mesh-mirroring/" data-link-title="Service Mesh Mirroring" data-link-desc="用 sidecar / proxy 層 mirror production traffic 到新版本或 shadow service 的 production validation 方式">Service Mesh Mirroring</a></td>
          <td>Traffic mirror</td>
          <td>用 proxy route policy mirror production traffic</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/vendors/aws-vpc-traffic-mirroring/" data-link-title="AWS VPC Traffic Mirroring" data-link-desc="用 VPC 網路層封包鏡像觀察 production traffic 的低侵入 production validation 方式">AWS VPC Traffic Mirroring</a></td>
          <td>Traffic mirror</td>
          <td>用 VPC 網路層封包鏡像建立低侵入 production evidence</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/vendors/datadog-continuous-profiler/" data-link-title="Datadog Continuous Profiler" data-link-desc="用 SaaS APM 整合、deployment marker 與 profile diff 支援 release regression 定位的 profiling 工具">Datadog Continuous Profiler</a></td>
          <td>Profiling</td>
          <td>用 SaaS APM 整合與 deploy marker 支援 profile diff</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/vendors/pyroscope/" data-link-title="Pyroscope" data-link-desc="用 Grafana 生態與開源 profiling backend 建立可自管 profile diff 與 flame graph 的工具">Pyroscope</a></td>
          <td>Profiling</td>
          <td>用 Grafana / OSS profiling backend 建立可自管 profile diff</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/vendors/parca/" data-link-title="Parca" data-link-desc="用 eBPF 與開源 continuous profiling 平台建立 infrastructure-wide profile evidence 的工具">Parca</a></td>
          <td>Profiling</td>
          <td>用 eBPF 與平台視角建立 infrastructure-wide profile evidence</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/vendors/akamas/" data-link-title="Akamas" data-link-desc="用 AI-driven optimization 把效能、可靠性與雲端成本放進同一個容量調校閉環">Akamas</a></td>
          <td>Optimization</td>
          <td>用 SLO constraint 與配置實驗建立 capacity / cost 調校閉環</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/vendors/vantage/" data-link-title="Vantage" data-link-desc="用 cloud cost reports、Kubernetes cost allocation 與 forecast 建立工程可用的成本可見性">Vantage</a></td>
          <td>FinOps</td>
          <td>用 cost reports、Kubernetes cost 與 forecast 建立成本可見性</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/vendors/cloudhealth/" data-link-title="CloudHealth" data-link-desc="用 enterprise FinOps governance、policy 與多雲成本管理支援大型組織的容量成本治理">CloudHealth</a></td>
          <td>FinOps</td>
          <td>用 enterprise governance、policy 與 allocation 管理雲端成本</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/vendors/aws-cost-explorer/" data-link-title="AWS Cost Explorer" data-link-desc="用 AWS-native 成本與用量分析建立 account、service、tag 與 usage type 的成本判讀入口">AWS Cost Explorer</a></td>
          <td>AWS FinOps</td>
          <td>用 AWS-native cost / usage report 建立成本分析 baseline</td>
      </tr>
  </tbody>
</table>
<p>這批工具頁已完成 load test、production traffic replay、continuous profiling 與 capacity / cost analysis 的主要分流。k6 承接 scriptable scenario，JMeter 承接企業測試資產，Gatling 承接 JVM simulation，Locust 承接 Python custom behavior，Vegeta 承接快速 HTTP probe；GoReplay、Service Mesh Mirroring 與 AWS VPC Traffic Mirroring 承接不同層級的 production traffic evidence；Datadog Continuous Profiler、Pyroscope 與 Parca 承接不同操作模型的 profile evidence；Akamas、Vantage、CloudHealth 與 AWS Cost Explorer 承接 cost visibility、optimization 與 FinOps governance。</p>
<h2 id="內容覆蓋進度">內容覆蓋進度</h2>
<p>每個工具頁下會擴充兩類文章：deep article（工具自身的配置、故障、容量、走 <a href="/blog/posts/vendor-%E6%B7%B1%E5%BA%A6%E6%8A%80%E8%A1%93%E6%96%87%E7%AB%A0%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84%E5%90%8C-vendor-%E7%B3%BB%E5%88%97%E7%9A%84%E9%96%8B%E5%A0%B4%E8%BC%AA%E6%9B%BF%E9%A9%97%E8%AD%89/" data-link-title="Vendor 深度技術文章方法論的演化紀錄：同 vendor 系列的開場輪替驗證" data-link-desc="vendor overview 飽和後要寫單一功能深度文章、需要選題與結構依據時回來。這套方法論的驗證來源與 cadence variant 在高風險場景（同 vendor sub-tool 系列）的實證。">6-section 模板</a>）跟 migration playbook（跨工具遷移流程、走 <a href="/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">6-type 結構</a>）。「← X」代表從 X 遷入。</p>
<table>
  <thead>
      <tr>
          <th>Vendor</th>
          <th>Deep article</th>
          <th>Migration playbook</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="k6/">k6</a></td>
          <td>—</td>
          <td><a href="k6/migrate-from-jmeter/">← JMeter (Type E)</a></td>
      </tr>
      <tr>
          <td><a href="datadog-continuous-profiler/">Datadog Continuous Profiler</a></td>
          <td>—</td>
          <td><a href="datadog-continuous-profiler/migrate-from-pyroscope/">← Pyroscope (Type C)</a></td>
      </tr>
  </tbody>
</table>
<p>其他 T1 工具（JMeter / Gatling / Locust / Vegeta / GoReplay / Service Mesh Mirroring / AWS VPC Traffic Mirroring / Pyroscope / Parca / Akamas / Vantage / CloudHealth / AWS Cost Explorer）尚未開始。跟 <a href="/blog/backend/06-reliability/vendors/" data-link-title="可靠性 Vendor 清單" data-link-desc="規劃 CI、壓測、chaos engineering 與 SLO 工具的服務頁撰寫順序與判準">06 vendors</a> 共用部分工具（k6 / JMeter / Gatling / Locust），未來寫 deep article 時需明確區分「驗證流程的工具鏈」（06）跟「效能工程的工具鏈」（09）的角度。對應的 backlog 議題見上方「T1 工具頁」段每個工具頁要回答的核心責任、跟各工具 <code>_index.md</code> 的「預計實作話題」段。</p>
<h2 id="後續候選">後續候選</h2>
<table>
  <thead>
      <tr>
          <th>類型</th>
          <th>候選工具</th>
          <th>寫作重點</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Load test</td>
          <td>Artillery、wrk、hey、Grafana k6 Cloud、AWS Distributed Load Testing、BlazeMeter、LoadRunner</td>
          <td>managed runner、跨 region、報表與費用</td>
      </tr>
      <tr>
          <td>Production traffic replay</td>
          <td>shadow traffic pattern、Diffy 類 response diff、proxy mirror variants</td>
          <td>response diff、資料遮罩、side effect 邊界</td>
      </tr>
      <tr>
          <td>Profiling</td>
          <td>GCP Cloud Profiler、AWS CodeGuru Profiler、Azure Application Insights Profiler、New Relic Profiler、Dynatrace Profiling</td>
          <td>雲端整合、採樣成本、profile diff</td>
      </tr>
      <tr>
          <td>Capacity / cost analysis</td>
          <td>Kubecost / OpenCost、CloudZero、CAST AI、Infracost、Harness Cloud Cost Management</td>
          <td>workload-level 成本、rightsizing、IaC cost</td>
      </tr>
      <tr>
          <td>Benchmark / workload model</td>
          <td>YCSB、JMH、pgbench、sysbench</td>
          <td>component benchmark、DB workload、micro vs system boundary</td>
      </tr>
  </tbody>
</table>
<p>Load test 工具頁要保留 workload model 語言。JMeter 適合 protocol 覆蓋與 GUI 驅動團隊，Gatling 適合程式化 scenario 與 JVM 生態，Locust 適合 Python 團隊，Vegeta 適合簡單 HTTP 壓測與 CLI workflow。</p>
<p>Production replay 工具頁要保留安全與副作用邊界。Replay production traffic 會碰到 PII、credential、payment callback、idempotency 與下游配額，因此文章要先定義遮罩、隔離、rate limit 與 stop condition。</p>
<p>Profiling 工具頁要保留長期成本。Continuous profiling 能降低退化定位時間，但會增加採樣成本、儲存成本、敏感資訊治理、symbolization 與 baseline 維護責任。</p>
<p>Capacity / cost analysis 工具頁要保留 owner 與行動閉環。成本報表只有在 tag、label、cost center、service owner、release marker 與 action workflow 對齊後，才會變成容量規劃與成本改善的工程證據。</p>
<p>主流覆蓋檢查的重點是分開 scenario load、quick probe、managed runner、traffic replay、profiling、FinOps 與 component benchmark。k6 / Gatling / Locust 解 scenario；Vegeta / wrk / hey 解 quick HTTP probe；Grafana k6 Cloud / AWS Distributed Load Testing / BlazeMeter 解 managed runner；Pyroscope / Parca / Datadog / cloud profiler 解 profiling；Kubecost / CloudZero / CAST AI 解 workload cost。</p>
<h2 id="工具頁標準章節">工具頁標準章節</h2>
<table>
  <thead>
      <tr>
          <th>章節</th>
          <th>效能與容量工具頁要補的內容</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>工具定位</td>
          <td>它是 load test、replay、traffic mirror、profiler、optimizer 還是 FinOps 工具</td>
      </tr>
      <tr>
          <td>本章目標</td>
          <td>讀者能判斷它降低容量未知、production gap、瓶頸定位或成本歸因哪種風險</td>
      </tr>
      <tr>
          <td>最短判讀路徑</td>
          <td>用「缺 workload、缺 saturation、缺 production evidence、缺 cost owner」快速定位</td>
      </tr>
      <tr>
          <td>日常操作與決策形狀</td>
          <td>scenario、runner、threshold、sampling、dashboard、recommendation、owner</td>
      </tr>
      <tr>
          <td>核心取捨表</td>
          <td>同類工具與相鄰工具的機會成本，例如 k6 vs JMeter、Vantage vs Cost Explorer</td>
      </tr>
      <tr>
          <td>進階主題</td>
          <td>distributed runner、shadow traffic、continuous profiling、optimization guardrail</td>
      </tr>
      <tr>
          <td>排錯與失敗快速判讀</td>
          <td>runner bottleneck、side effect、sampling bias、tag gap、forecast drift</td>
      </tr>
      <tr>
          <td>何時改走其他服務</td>
          <td>驗證流程回 06、觀測資料回 04、部署控制回 05、事故處理回 08</td>
      </tr>
      <tr>
          <td>不在本頁內的主題</td>
          <td>完整工具 CLI 教學、供應商 pricing 細節、所有 dashboard 設定</td>
      </tr>
      <tr>
          <td>案例回寫與下一步路由</td>
          <td>回到 09 cases、6.13 regression gate、4.20 evidence package</td>
      </tr>
  </tbody>
</table>
<h2 id="跨-vendor-議題對照">跨 vendor 議題對照</h2>
<p>本模組 15 個 vendor 跨 5 個 sub-category（load test / production replay / continuous profiling / optimization / FinOps）、解不同效能與容量工程問題、不是同類選一。</p>
<table>
  <thead>
      <tr>
          <th>Sub-category</th>
          <th>典型 vendor</th>
          <th>輸出證據</th>
          <th>Production 風險</th>
          <th>操作成本</th>
          <th>Owner</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Load test</td>
          <td>k6 / JMeter / Gatling / Locust / Vegeta</td>
          <td>threshold pass/fail / p95 p99 / throughput</td>
          <td>低（測試環境）</td>
          <td>scenario 維護 / runner 規模 / 測試資料</td>
          <td>Engineering / QA</td>
      </tr>
      <tr>
          <td>Production replay</td>
          <td>GoReplay / Service Mesh Mirroring / AWS VPC</td>
          <td>response diff / shadow load</td>
          <td>高（PII / side effect / 配額）</td>
          <td>masking / isolation / rate limit</td>
          <td>SRE + Security</td>
      </tr>
      <tr>
          <td>Continuous profiling</td>
          <td>Datadog Profiler / Pyroscope / Parca</td>
          <td>flame graph diff / regression detection</td>
          <td>中（採樣 overhead）</td>
          <td>symbolization / storage / baseline 維護</td>
          <td>Engineering</td>
      </tr>
      <tr>
          <td>Optimization</td>
          <td>Akamas</td>
          <td>recommendation / SLO-constrained config</td>
          <td>中（autopilot rollout）</td>
          <td>objective model / approval workflow</td>
          <td>SRE + FinOps</td>
      </tr>
      <tr>
          <td>FinOps</td>
          <td>Vantage / CloudHealth / AWS Cost Explorer</td>
          <td>cost report / forecast / rightsizing</td>
          <td>無(reporting)</td>
          <td>tag governance / owner mapping / cadence</td>
          <td>FinOps + Eng lead</td>
      </tr>
  </tbody>
</table>
<p>對照表的用途有三：</p>
<ul>
<li>對齊 sub-category 跟問題節點：缺 saturation → load test；缺 production gap → replay；缺 瓶頸定位 → profiler；缺 capacity / cost 閉環 → optimizer + FinOps</li>
<li>評估 production 風險：load test 安全、replay / mirror 要明示 side effect 邊界、profiler 要看採樣 overhead、FinOps reporting 無風險</li>
<li>對齊 owner：load test 多 Engineering / QA、replay 多 SRE + Security、optimization + FinOps 跨團隊</li>
</ul>
<p>下面 5 段把對照表的 sub-category 展開、每段帶 vendor 選型判讀。</p>
<h3 id="load-testk6--jmeter--gatling--locust--vegeta">Load test（k6 / JMeter / Gatling / Locust / Vegeta）</h3>
<p>Load test 是 09 模組的主要 saturation 探測工具、跟 <a href="/blog/backend/06-reliability/vendors/" data-link-title="可靠性 Vendor 清單" data-link-desc="規劃 CI、壓測、chaos engineering 與 SLO 工具的服務頁撰寫順序與判準">06 reliability load test 章節</a> 同 vendor 但角度不同 — 06 看 CI gate / regression evidence、09 看 capacity planning / saturation discovery / peak event readiness。</p>
<p>選型判讀：CI-first JS → <a href="/blog/backend/09-performance-capacity/vendors/k6/" data-link-title="k6" data-link-desc="用 scriptable scenario 建立 API、protocol 與 CI 友善壓測的效能工程工具">k6</a>；JVM + 複雜 scenario → <a href="/blog/backend/09-performance-capacity/vendors/gatling/" data-link-title="Gatling" data-link-desc="用 JVM DSL、simulation 與 injection profile 表達複雜 scenario 的效能工程工具">Gatling</a>；既有 .jmx 資產 → <a href="/blog/backend/09-performance-capacity/vendors/jmeter/" data-link-title="Apache JMeter" data-link-desc="用 GUI、plugin 與多 protocol sampler 承接企業壓測資產的效能工程工具">JMeter</a>；Python custom behavior → <a href="/blog/backend/09-performance-capacity/vendors/locust/" data-link-title="Locust" data-link-desc="用 Python user behavior 與 distributed worker 表達高自訂負載模型的效能工程工具">Locust</a>；快速 HTTP probe / fixed rate → <a href="/blog/backend/09-performance-capacity/vendors/vegeta/" data-link-title="Vegeta" data-link-desc="用簡潔 CLI 與固定 rate HTTP attack 快速探測 latency、throughput 與 saturation 的效能工程工具">Vegeta</a>（單一 HTTP attack 模式、不適合多 step scenario）。</p>
<h3 id="production-replaygoreplay--service-mesh-mirroring--aws-vpc-traffic-mirroring">Production replay（GoReplay / Service Mesh Mirroring / AWS VPC Traffic Mirroring）</h3>
<p>Production replay 把實際流量重播到 shadow target、補 load test 的「人工 scenario 跟真實流量差距」缺口。<strong>GoReplay</strong> 應用層 HTTP traffic capture + replay；<strong>Service Mesh Mirroring</strong> 用 Envoy / Istio proxy mirror、適合 K8s 內部；<strong>AWS VPC Traffic Mirroring</strong> L4 封包鏡像、適合非 HTTP / 低侵入。</p>
<p>選型判讀：HTTP application 層 → GoReplay；K8s 內 service mesh → Service Mesh Mirroring；非 HTTP / 跨 VPC / 低侵入 → AWS VPC。共同議題：PII 遮罩、idempotency boundary、downstream 配額 — 不可省。</p>
<h3 id="continuous-profilingdatadog-continuous-profiler--pyroscope--parca">Continuous profiling（Datadog Continuous Profiler / Pyroscope / Parca）</h3>
<p>Continuous profiling 在 production 持續採樣、退化時可 profile diff 找瓶頸。<strong>Datadog Continuous Profiler</strong> SaaS APM 整合、deploy marker 自動關聯；<strong>Pyroscope</strong> OSS / Grafana 生態、可自管或 Grafana Cloud；<strong>Parca</strong> eBPF-based、infrastructure-wide profile（不需 application instrumentation）。</p>
<p>選型判讀：已用 Datadog APM → Datadog Profiler；Grafana 生態 / OSS → Pyroscope；不想 instrument application + eBPF 友善 → Parca。共同議題：採樣 overhead（CPU / memory）、symbolization、storage cost、敏感資訊。</p>
<h3 id="optimizationakamas">Optimization（Akamas）</h3>
<p>Optimization 把 workload + SLO + cost 放進同一閉環、產出 configuration recommendation。<strong>Akamas</strong> 是 09 模組唯一 optimizer vendor、適合已有可量測 workload 跟成本壓力的服務。</p>
<p>選型判讀：Kubernetes rightsizing + runtime tuning + cost target → Akamas；純 FinOps reporting 不夠（要主動建議）→ Akamas。Akamas 不替代 FinOps tool — Vantage / CloudHealth 看歷史成本、Akamas 提產出未來 recommendation。</p>
<h3 id="finopsvantage--cloudhealth--aws-cost-explorer">FinOps（Vantage / CloudHealth / AWS Cost Explorer）</h3>
<p>FinOps 提供 cost visibility + forecast + allocation。<strong>Vantage</strong> Kubernetes cost + forecast 友善的 startup-friendly 平台；<strong>CloudHealth</strong> enterprise FinOps governance + policy + chargeback；<strong>AWS Cost Explorer</strong> AWS-native cost analysis baseline（免費、限 AWS）。</p>
<p>選型判讀：純 AWS 啟動 → Cost Explorer；多雲 + startup / mid-size → Vantage；enterprise + 多 BU chargeback → CloudHealth；K8s workload cost → Kubecost / OpenCost（不在本表、後續候選）。共同議題：tag governance、cost center mapping、cadence。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/09-performance-capacity/load-test-tooling/" data-link-title="9.3 壓測工具選型" data-link-desc="k6 / JMeter / Gatling / Locust / Vegeta / Production Replay 的工程選型">9.3 壓測工具選型</a></li>
<li>上游：<a href="/blog/backend/09-performance-capacity/production-validation/" data-link-title="9.10 Production-Side 驗證" data-link-desc="shadow traffic、dark launch、canary、production-like load test">9.10 Production-Side 驗證</a></li>
<li>服務路徑：<a href="/blog/backend/#%e8%b2%ab%e7%a9%bf%e5%bc%8f%e6%a1%88%e4%be%8bcheckout-%e6%9c%8d%e5%8b%99%e6%bc%94%e9%80%b2" data-link-title="Backend 服務實務指南" data-link-desc="用跨語言教學路線整理資料庫、快取、訊息佇列、觀測、部署、可靠性、資安、事故與容量等後端服務能力">Checkout 服務演進</a></li>
<li>平行：<a href="/blog/backend/06-reliability/vendors/" data-link-title="可靠性 Vendor 清單" data-link-desc="規劃 CI、壓測、chaos engineering 與 SLO 工具的服務頁撰寫順序與判準">06 Reliability vendors</a> — 06 從驗證流程看工具，09 從容量量化與效能工程看工具</li>
</ul>
]]></content:encoded></item><item><title>資安與資料保護 Vendor 清單</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/</link><pubDate>Fri, 15 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/</guid><description>&lt;p>資安與資料保護 Vendor 清單的核心責任是把安全服務名稱放回控制面、信任邊界、證據鏈與交接路由的判斷。每個服務頁先回答它承擔身份、秘密、傳輸、入口、資料保護、供應鏈或偵測哪一段控制責任，再討論導入條件、操作成本、例外治理與事故回寫。多數控制面都有「自建 vs 買託管」的選擇：自建認證 vs Auth0 / Okta / Cognito、自管 secret store vs managed KMS / Vault、自架 WAF vs 雲端 WAF — 把整塊控制責任外包給專做合規的 vendor 是常見且合理的起點，逐控制面的買 vs 建判讀見 &lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/capability-buy-vs-build/" data-link-title="0.22 能力級買 vs 建：feature-as-a-service 與 BaaS bundle 選型" data-link-desc="在交付形態決定整個系統要不要自建之後、逐能力判斷該外包還是自建：辨識 managed 基礎設施、feature SaaS 與 BaaS bundle 三種外包深度、no-code 到 dev-tool 的服務光譜、買 vs 建判準與權重浮動、整合接縫與遷出代價">0.22 能力級買 vs 建&lt;/a>。&lt;/p>
&lt;h2 id="讀法">讀法&lt;/h2>
&lt;p>資安服務要從控制問題進入。讀者如果要處理身份與授權，先回到 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/identity-access-boundary/" data-link-title="7.2 身分與授權邊界" data-link-desc="以問題驅動方式整理身分、授權、會話與供應商身分鏈">7.2 身分與授權邊界&lt;/a>；如果要處理秘密與機器憑證，先回到 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/secrets-and-machine-credential-governance/" data-link-title="7.6 秘密管理與機器憑證治理" data-link-desc="以問題驅動方式整理 secret、token、key 與機器身份治理">7.6 秘密管理與機器憑證治理&lt;/a>；如果要處理入口與伺服器暴露，先回到 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/entrypoint-and-server-protection/" data-link-title="7.3 入口治理與伺服器防護" data-link-desc="以問題驅動方式整理對外入口、管理平面與伺服器邊界">7.3 入口治理與伺服器防護&lt;/a>。&lt;/p>
&lt;h2 id="教學順序同步">教學順序同步&lt;/h2>
&lt;p>資安服務頁的教學順序是先建立 identity / IAM，再進入 secrets / KMS / PKI、edge、supply chain、detection / DLP。這個順序對齊 checkout E6：讀者先理解誰能做什麼、秘密與金鑰如何生命週期化，再比較入口防護、artifact trust、偵測訊號與資料控制如何接到 release gate、evidence package 與 incident handoff。&lt;/p>
&lt;h2 id="t1-服務頁大綱">T1 服務頁大綱&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>服務群&lt;/th>
 &lt;th>候選服務&lt;/th>
 &lt;th>頁面要回答的核心問題&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Identity / IdP&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/auth0/" data-link-title="Auth0" data-link-desc="B2C / B2B Customer Identity Provider、Universal Login、Action / Rule hook、屬 Okta 旗下 Customer Identity Cloud">Auth0&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/keycloak/" data-link-title="Keycloak" data-link-desc="Open source self-hosted Identity Provider、Red Hat 主導、Realm-based multi-tenancy、適合資料主權與自訂 flow 需求">Keycloak&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-iam-identity-center/" data-link-title="AWS IAM Identity Center" data-link-desc="AWS 原生 workforce SSO、前 AWS SSO、Permission Set 跨帳號 access、可串外部 IdP federation">AWS IAM Identity Center&lt;/a>&lt;/td>
 &lt;td>人類身份、SSO、MFA、group、role 與 session 邊界如何治理&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Cloud IAM&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google Cloud IAM&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/azure-rbac/" data-link-title="Azure RBAC &amp;#43; Entra ID" data-link-desc="Azure 雙層身份/權限體系、Entra ID（IdP）&amp;#43; Azure RBAC（resource permission）、Conditional Access、PIM、Managed Identity">Azure RBAC&lt;/a>&lt;/td>
 &lt;td>cloud resource 權限、policy、role assumption 與 least privilege 如何落地&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Secrets / Vault&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-secrets-manager/" data-link-title="AWS Secrets Manager" data-link-desc="AWS 原生 secret store &amp;#43; 內建 RDS / Redshift rotation Lambda、Resource Policy 跨帳號共享、KMS 加密">AWS Secrets Manager&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/google-secret-manager/" data-link-title="Google Secret Manager" data-link-desc="GCP 原生 secret store、CMEK &amp;#43; Workload Identity Federation 整合、rotation 走自寫 Cloud Function 而非 built-in Lambda">Google Secret Manager&lt;/a>&lt;/td>
 &lt;td>secret storage、rotation、lease、audit 與 application delivery 如何治理&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>KMS / HSM&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-kms/" data-link-title="AWS KMS" data-link-desc="AWS 原生 key management service、envelope encryption / digital signing / Multi-Region Key、Key Policy &amp;#43; Grant 雙軌授權">AWS KMS&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/google-cloud-kms/" data-link-title="Google Cloud KMS" data-link-desc="GCP 原生 key management service、KeyRing / CryptoKey Version 設計、CMEK 整合 &amp;#43; Cloud HSM &amp;#43; External Key Manager">Google Cloud KMS&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/azure-key-vault/" data-link-title="Azure Key Vault" data-link-desc="Azure 三合一 service（Secret &amp;#43; Key &amp;#43; Certificate）、整合 Managed Identity &amp;#43; Entra ID RBAC、Premium tier 走 HSM">Azure Key Vault&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/cloudhsm/" data-link-title="AWS CloudHSM" data-link-desc="Single-tenant dedicated HSM（FIPS 140-2 Level 3）、AWS 不持 Crypto User credential、合規 &amp;#43; 資料主權場景的 key custody">CloudHSM&lt;/a>&lt;/td>
 &lt;td>key lifecycle、envelope encryption、rotation 與權限分離如何成立&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Edge / WAF&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &amp;#43; DDoS &amp;#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-waf/" data-link-title="AWS WAF" data-link-desc="AWS-internal WAF、跟 ALB / CloudFront / API Gateway 直接整合、Web ACL &amp;#43; Managed Rule Group &amp;#43; Rate-based Rule、Shield Standard 內含">AWS WAF&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/fastly-ngwaf/" data-link-title="Fastly Next-Gen WAF" data-link-desc="Behavioral / 語意分析 WAF（前 Signal Sciences）、低 false positive、Edge / Agent / Cloud 三種部署模型、API &amp;#43; ATO &amp;#43; Bot 一體">Fastly Next-Gen WAF&lt;/a>&lt;/td>
 &lt;td>入口防護、bot、rate limit、managed rule 與 false positive 如何取捨&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Certificate / PKI&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/cert-manager/" data-link-title="cert-manager" data-link-desc="K8s 原生 certificate lifecycle automation、支援 Let&amp;#39;s Encrypt / Vault PKI / Venafi 等多 issuer、auto-renewal &amp;#43; Challenge solver">cert-manager&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-acm/" data-link-title="AWS ACM" data-link-desc="AWS-managed certificate provisioning、DNS validation &amp;#43; auto-renewal、整合 ELB / CloudFront / API Gateway、Private CA 後端">AWS ACM&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/letsencrypt/" data-link-title="Let&amp;#39;s Encrypt" data-link-desc="免費 &amp;#43; 自動化的公共 ACME CA、90 天 TTL 強制自動化、跨雲跨平台 public TLS cert 的事實基礎">Let&amp;rsquo;s Encrypt&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/spire/" data-link-title="SPIRE" data-link-desc="SPIFFE Runtime Environment、attested workload identity、short-lived SVID &amp;#43; Trust Bundle、跨組織 federation">SPIRE&lt;/a>&lt;/td>
 &lt;td>TLS、mTLS、workload identity 與憑證生命週期如何自動化&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Supply chain&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &amp;#43; Secret Scanning &amp;#43; Dependency Review &amp;#43; Dependabot、跟 PR / Security tab 深度整合">GitHub Advanced Security&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &amp;#43; Code (SAST) &amp;#43; Container &amp;#43; IaC &amp;#43; Cloud (CSPM)、Reachability analysis">Snyk&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/dependabot/" data-link-title="Dependabot" data-link-desc="GitHub 原生依賴更新自動化、Version Update &amp;#43; Security Update &amp;#43; Alerts、Grouped Updates 減 PR noise、Auto-merge 配 branch protection">Dependabot&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &amp;#43; Secret &amp;#43; License &amp;#43; SBOM、Apache 2.0、CI 友善">Trivy&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/syft-grype/" data-link-title="Syft &amp;#43; Grype" data-link-desc="Anchore 開源姐妹工具：Syft 產 SBOM (CycloneDX / SPDX) &amp;#43; Grype scan 漏洞、Unix philosophy、cosign attestation 整合">Syft / Grype&lt;/a>&lt;/td>
 &lt;td>SCA、container scan、SBOM、artifact trust 與 release gate 如何接軌&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>SIEM / Detection&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &amp;#43; indexer &amp;#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &amp;#43; EDR &amp;#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &amp;#43; CSPM &amp;#43; CWS &amp;#43; AAP &amp;#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Security&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/google-security-operations/" data-link-title="Google Security Operations" data-link-desc="Google 雲原生 SIEM &amp;#43; SOAR &amp;#43; Mandiant threat intel 三合一（前 Chronicle）、UDM &amp;#43; YARA-L、fixed-price by data tier、PB-scale 友善">Google Security Operations&lt;/a>&lt;/td>
 &lt;td>偵測訊號、log pipeline、alert quality 與 incident handoff 如何治理&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>DLP / Data control&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/google-dlp/" data-link-title="Google DLP" data-link-desc="GCP 原生 Sensitive Data Protection：infoType discovery &amp;#43; transformation (mask / FPE / tokenize / k-anonymity)、整合 BigQuery / GCS / Cloud SQL">Google DLP&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/microsoft-purview/" data-link-title="Microsoft Purview" data-link-desc="Microsoft 跨 M365 / Azure / endpoint 的 data governance &amp;#43; information protection &amp;#43; DLP &amp;#43; insider risk 統合平台、label-driven">Microsoft Purview&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/cloud-data-policy/" data-link-title="Cloud-native Data Policy (BigQuery &amp;#43; S3)" data-link-desc="BigQuery column / row-level security &amp;#43; S3 bucket policy &amp;#43; Access Points &amp;#43; Macie、雲端原生資料層 access control、跟 DLP / Purview 互補">Cloud-native Data Policy (BigQuery + S3)&lt;/a>&lt;/td>
 &lt;td>資料分類、遮罩、匯出、資料駐留與證據鏈如何落地&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="內容覆蓋進度">內容覆蓋進度&lt;/h2>
&lt;p>每個 vendor 服務頁下會擴充兩類文章：deep article（vendor 自身的配置、故障、容量、走 &lt;a href="https://tarrragon.github.io/blog/posts/vendor-%E6%B7%B1%E5%BA%A6%E6%8A%80%E8%A1%93%E6%96%87%E7%AB%A0%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84%E5%90%8C-vendor-%E7%B3%BB%E5%88%97%E7%9A%84%E9%96%8B%E5%A0%B4%E8%BC%AA%E6%9B%BF%E9%A9%97%E8%AD%89/" data-link-title="Vendor 深度技術文章方法論的演化紀錄：同 vendor 系列的開場輪替驗證" data-link-desc="vendor overview 飽和後要寫單一功能深度文章、需要選題與結構依據時回來。這套方法論的驗證來源與 cadence variant 在高風險場景（同 vendor sub-tool 系列）的實證。">6-section 模板&lt;/a>）跟 migration playbook（跨 vendor 遷移流程、走 &lt;a href="https://tarrragon.github.io/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">6-type 結構&lt;/a>）。「→ X」代表遷移到 X 的 playbook。&lt;/p></description><content:encoded><![CDATA[<p>資安與資料保護 Vendor 清單的核心責任是把安全服務名稱放回控制面、信任邊界、證據鏈與交接路由的判斷。每個服務頁先回答它承擔身份、秘密、傳輸、入口、資料保護、供應鏈或偵測哪一段控制責任，再討論導入條件、操作成本、例外治理與事故回寫。多數控制面都有「自建 vs 買託管」的選擇：自建認證 vs Auth0 / Okta / Cognito、自管 secret store vs managed KMS / Vault、自架 WAF vs 雲端 WAF — 把整塊控制責任外包給專做合規的 vendor 是常見且合理的起點，逐控制面的買 vs 建判讀見 <a href="/blog/backend/00-service-selection/capability-buy-vs-build/" data-link-title="0.22 能力級買 vs 建：feature-as-a-service 與 BaaS bundle 選型" data-link-desc="在交付形態決定整個系統要不要自建之後、逐能力判斷該外包還是自建：辨識 managed 基礎設施、feature SaaS 與 BaaS bundle 三種外包深度、no-code 到 dev-tool 的服務光譜、買 vs 建判準與權重浮動、整合接縫與遷出代價">0.22 能力級買 vs 建</a>。</p>
<h2 id="讀法">讀法</h2>
<p>資安服務要從控制問題進入。讀者如果要處理身份與授權，先回到 <a href="/blog/backend/07-security-data-protection/identity-access-boundary/" data-link-title="7.2 身分與授權邊界" data-link-desc="以問題驅動方式整理身分、授權、會話與供應商身分鏈">7.2 身分與授權邊界</a>；如果要處理秘密與機器憑證，先回到 <a href="/blog/backend/07-security-data-protection/secrets-and-machine-credential-governance/" data-link-title="7.6 秘密管理與機器憑證治理" data-link-desc="以問題驅動方式整理 secret、token、key 與機器身份治理">7.6 秘密管理與機器憑證治理</a>；如果要處理入口與伺服器暴露，先回到 <a href="/blog/backend/07-security-data-protection/entrypoint-and-server-protection/" data-link-title="7.3 入口治理與伺服器防護" data-link-desc="以問題驅動方式整理對外入口、管理平面與伺服器邊界">7.3 入口治理與伺服器防護</a>。</p>
<h2 id="教學順序同步">教學順序同步</h2>
<p>資安服務頁的教學順序是先建立 identity / IAM，再進入 secrets / KMS / PKI、edge、supply chain、detection / DLP。這個順序對齊 checkout E6：讀者先理解誰能做什麼、秘密與金鑰如何生命週期化，再比較入口防護、artifact trust、偵測訊號與資料控制如何接到 release gate、evidence package 與 incident handoff。</p>
<h2 id="t1-服務頁大綱">T1 服務頁大綱</h2>
<table>
  <thead>
      <tr>
          <th>服務群</th>
          <th>候選服務</th>
          <th>頁面要回答的核心問題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Identity / IdP</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a>、<a href="/blog/backend/07-security-data-protection/vendors/auth0/" data-link-title="Auth0" data-link-desc="B2C / B2B Customer Identity Provider、Universal Login、Action / Rule hook、屬 Okta 旗下 Customer Identity Cloud">Auth0</a>、<a href="/blog/backend/07-security-data-protection/vendors/keycloak/" data-link-title="Keycloak" data-link-desc="Open source self-hosted Identity Provider、Red Hat 主導、Realm-based multi-tenancy、適合資料主權與自訂 flow 需求">Keycloak</a>、<a href="/blog/backend/07-security-data-protection/vendors/aws-iam-identity-center/" data-link-title="AWS IAM Identity Center" data-link-desc="AWS 原生 workforce SSO、前 AWS SSO、Permission Set 跨帳號 access、可串外部 IdP federation">AWS IAM Identity Center</a></td>
          <td>人類身份、SSO、MFA、group、role 與 session 邊界如何治理</td>
      </tr>
      <tr>
          <td>Cloud IAM</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM</a>、<a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google Cloud IAM</a>、<a href="/blog/backend/07-security-data-protection/vendors/azure-rbac/" data-link-title="Azure RBAC &#43; Entra ID" data-link-desc="Azure 雙層身份/權限體系、Entra ID（IdP）&#43; Azure RBAC（resource permission）、Conditional Access、PIM、Managed Identity">Azure RBAC</a></td>
          <td>cloud resource 權限、policy、role assumption 與 least privilege 如何落地</td>
      </tr>
      <tr>
          <td>Secrets / Vault</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a>、<a href="/blog/backend/07-security-data-protection/vendors/aws-secrets-manager/" data-link-title="AWS Secrets Manager" data-link-desc="AWS 原生 secret store &#43; 內建 RDS / Redshift rotation Lambda、Resource Policy 跨帳號共享、KMS 加密">AWS Secrets Manager</a>、<a href="/blog/backend/07-security-data-protection/vendors/google-secret-manager/" data-link-title="Google Secret Manager" data-link-desc="GCP 原生 secret store、CMEK &#43; Workload Identity Federation 整合、rotation 走自寫 Cloud Function 而非 built-in Lambda">Google Secret Manager</a></td>
          <td>secret storage、rotation、lease、audit 與 application delivery 如何治理</td>
      </tr>
      <tr>
          <td>KMS / HSM</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/aws-kms/" data-link-title="AWS KMS" data-link-desc="AWS 原生 key management service、envelope encryption / digital signing / Multi-Region Key、Key Policy &#43; Grant 雙軌授權">AWS KMS</a>、<a href="/blog/backend/07-security-data-protection/vendors/google-cloud-kms/" data-link-title="Google Cloud KMS" data-link-desc="GCP 原生 key management service、KeyRing / CryptoKey Version 設計、CMEK 整合 &#43; Cloud HSM &#43; External Key Manager">Google Cloud KMS</a>、<a href="/blog/backend/07-security-data-protection/vendors/azure-key-vault/" data-link-title="Azure Key Vault" data-link-desc="Azure 三合一 service（Secret &#43; Key &#43; Certificate）、整合 Managed Identity &#43; Entra ID RBAC、Premium tier 走 HSM">Azure Key Vault</a>、<a href="/blog/backend/07-security-data-protection/vendors/cloudhsm/" data-link-title="AWS CloudHSM" data-link-desc="Single-tenant dedicated HSM（FIPS 140-2 Level 3）、AWS 不持 Crypto User credential、合規 &#43; 資料主權場景的 key custody">CloudHSM</a></td>
          <td>key lifecycle、envelope encryption、rotation 與權限分離如何成立</td>
      </tr>
      <tr>
          <td>Edge / WAF</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &#43; DDoS &#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF</a>、<a href="/blog/backend/07-security-data-protection/vendors/aws-waf/" data-link-title="AWS WAF" data-link-desc="AWS-internal WAF、跟 ALB / CloudFront / API Gateway 直接整合、Web ACL &#43; Managed Rule Group &#43; Rate-based Rule、Shield Standard 內含">AWS WAF</a>、<a href="/blog/backend/07-security-data-protection/vendors/fastly-ngwaf/" data-link-title="Fastly Next-Gen WAF" data-link-desc="Behavioral / 語意分析 WAF（前 Signal Sciences）、低 false positive、Edge / Agent / Cloud 三種部署模型、API &#43; ATO &#43; Bot 一體">Fastly Next-Gen WAF</a></td>
          <td>入口防護、bot、rate limit、managed rule 與 false positive 如何取捨</td>
      </tr>
      <tr>
          <td>Certificate / PKI</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/cert-manager/" data-link-title="cert-manager" data-link-desc="K8s 原生 certificate lifecycle automation、支援 Let&#39;s Encrypt / Vault PKI / Venafi 等多 issuer、auto-renewal &#43; Challenge solver">cert-manager</a>、<a href="/blog/backend/07-security-data-protection/vendors/aws-acm/" data-link-title="AWS ACM" data-link-desc="AWS-managed certificate provisioning、DNS validation &#43; auto-renewal、整合 ELB / CloudFront / API Gateway、Private CA 後端">AWS ACM</a>、<a href="/blog/backend/07-security-data-protection/vendors/letsencrypt/" data-link-title="Let&#39;s Encrypt" data-link-desc="免費 &#43; 自動化的公共 ACME CA、90 天 TTL 強制自動化、跨雲跨平台 public TLS cert 的事實基礎">Let&rsquo;s Encrypt</a>、<a href="/blog/backend/07-security-data-protection/vendors/spire/" data-link-title="SPIRE" data-link-desc="SPIFFE Runtime Environment、attested workload identity、short-lived SVID &#43; Trust Bundle、跨組織 federation">SPIRE</a></td>
          <td>TLS、mTLS、workload identity 與憑證生命週期如何自動化</td>
      </tr>
      <tr>
          <td>Supply chain</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GitHub Advanced Security</a>、<a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk</a>、<a href="/blog/backend/07-security-data-protection/vendors/dependabot/" data-link-title="Dependabot" data-link-desc="GitHub 原生依賴更新自動化、Version Update &#43; Security Update &#43; Alerts、Grouped Updates 減 PR noise、Auto-merge 配 branch protection">Dependabot</a>、<a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a>、<a href="/blog/backend/07-security-data-protection/vendors/syft-grype/" data-link-title="Syft &#43; Grype" data-link-desc="Anchore 開源姐妹工具：Syft 產 SBOM (CycloneDX / SPDX) &#43; Grype scan 漏洞、Unix philosophy、cosign attestation 整合">Syft / Grype</a></td>
          <td>SCA、container scan、SBOM、artifact trust 與 release gate 如何接軌</td>
      </tr>
      <tr>
          <td>SIEM / Detection</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a>、<a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a>、<a href="/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &#43; CSPM &#43; CWS &#43; AAP &#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Security</a>、<a href="/blog/backend/07-security-data-protection/vendors/google-security-operations/" data-link-title="Google Security Operations" data-link-desc="Google 雲原生 SIEM &#43; SOAR &#43; Mandiant threat intel 三合一（前 Chronicle）、UDM &#43; YARA-L、fixed-price by data tier、PB-scale 友善">Google Security Operations</a></td>
          <td>偵測訊號、log pipeline、alert quality 與 incident handoff 如何治理</td>
      </tr>
      <tr>
          <td>DLP / Data control</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/google-dlp/" data-link-title="Google DLP" data-link-desc="GCP 原生 Sensitive Data Protection：infoType discovery &#43; transformation (mask / FPE / tokenize / k-anonymity)、整合 BigQuery / GCS / Cloud SQL">Google DLP</a>、<a href="/blog/backend/07-security-data-protection/vendors/microsoft-purview/" data-link-title="Microsoft Purview" data-link-desc="Microsoft 跨 M365 / Azure / endpoint 的 data governance &#43; information protection &#43; DLP &#43; insider risk 統合平台、label-driven">Microsoft Purview</a>、<a href="/blog/backend/07-security-data-protection/vendors/cloud-data-policy/" data-link-title="Cloud-native Data Policy (BigQuery &#43; S3)" data-link-desc="BigQuery column / row-level security &#43; S3 bucket policy &#43; Access Points &#43; Macie、雲端原生資料層 access control、跟 DLP / Purview 互補">Cloud-native Data Policy (BigQuery + S3)</a></td>
          <td>資料分類、遮罩、匯出、資料駐留與證據鏈如何落地</td>
      </tr>
  </tbody>
</table>
<h2 id="內容覆蓋進度">內容覆蓋進度</h2>
<p>每個 vendor 服務頁下會擴充兩類文章：deep article（vendor 自身的配置、故障、容量、走 <a href="/blog/posts/vendor-%E6%B7%B1%E5%BA%A6%E6%8A%80%E8%A1%93%E6%96%87%E7%AB%A0%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84%E5%90%8C-vendor-%E7%B3%BB%E5%88%97%E7%9A%84%E9%96%8B%E5%A0%B4%E8%BC%AA%E6%9B%BF%E9%A9%97%E8%AD%89/" data-link-title="Vendor 深度技術文章方法論的演化紀錄：同 vendor 系列的開場輪替驗證" data-link-desc="vendor overview 飽和後要寫單一功能深度文章、需要選題與結構依據時回來。這套方法論的驗證來源與 cadence variant 在高風險場景（同 vendor sub-tool 系列）的實證。">6-section 模板</a>）跟 migration playbook（跨 vendor 遷移流程、走 <a href="/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">6-type 結構</a>）。「→ X」代表遷移到 X 的 playbook。</p>
<table>
  <thead>
      <tr>
          <th>Vendor</th>
          <th>Deep article</th>
          <th>Migration playbook</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="cloudflare-waf/">Cloudflare WAF</a></td>
          <td><a href="cloudflare-waf/page-shield-csp-sri/">page-shield-csp-sri</a></td>
          <td>—</td>
      </tr>
      <tr>
          <td><a href="hashicorp-vault/">HashiCorp Vault</a></td>
          <td><a href="hashicorp-vault/dynamic-credential/">dynamic-credential</a></td>
          <td><a href="hashicorp-vault/migrate-to-aws-secrets-manager/">→ AWS Secrets Manager</a></td>
      </tr>
      <tr>
          <td><a href="splunk/">Splunk</a></td>
          <td><a href="splunk/risk-based-alerting/">risk-based-alerting</a></td>
          <td><a href="splunk/migrate-to-elastic-security/">→ Elastic Security</a></td>
      </tr>
  </tbody>
</table>
<p>本章節 vendor 服務頁覆蓋率高（51 個 vendor 服務頁、上方「T1 服務頁大綱」跟「後續候選」段已全部建立），但 deep article / migration playbook 還在早期階段。對應的 backlog 議題見上方「T1 服務頁大綱」段每個服務群要回答的核心問題、跟各 vendor <code>_index.md</code> 的「預計實作話題」段。</p>
<h2 id="服務頁標準章節">服務頁標準章節</h2>
<table>
  <thead>
      <tr>
          <th>章節</th>
          <th>資安服務頁要補的內容</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>服務定位</td>
          <td>它是 identity、IAM、secret、KMS、WAF、PKI、supply chain、SIEM 還是 DLP</td>
      </tr>
      <tr>
          <td>本章目標</td>
          <td>讀者能判斷控制面責任、信任邊界、證據需求、例外與事故交接</td>
      </tr>
      <tr>
          <td>最短判讀路徑</td>
          <td>用「誰能做什麼、憑證在哪裡、入口如何暴露、證據是否可回查」快速定位</td>
      </tr>
      <tr>
          <td>日常操作與決策形狀</td>
          <td>onboarding、policy、rotation、rule update、exception、audit、handoff</td>
      </tr>
      <tr>
          <td>核心取捨表</td>
          <td>managed service、self-hosted control、cloud-native、SaaS security tool 的機會成本</td>
      </tr>
      <tr>
          <td>進階主題</td>
          <td>federation、workload identity、mTLS、SBOM、DLP、multi-cloud policy</td>
      </tr>
      <tr>
          <td>排錯與失敗快速判讀</td>
          <td>over-permission、stale secret、broken rotation、WAF false positive、missing audit trail</td>
      </tr>
      <tr>
          <td>何時改走其他服務</td>
          <td>觀測訊號回 04、release gate 回 06、入口部署回 05、事故處理回 08</td>
      </tr>
      <tr>
          <td>不在本頁內的主題</td>
          <td>合規逐條法規解讀、完整 SOC 2 / HIPAA 流程、所有攻擊技術細節</td>
      </tr>
      <tr>
          <td>案例回寫</td>
          <td>回到 7.C cases、7.B blue-team materials、8 incident write-back 連到對應 vendor 事件</td>
      </tr>
      <tr>
          <td>下一步路由</td>
          <td>上游 chapter（7.X）、平行 vendor、下游模組（04 / 05 / 06 / 08）的交接</td>
      </tr>
  </tbody>
</table>
<h2 id="撰寫批次">撰寫批次</h2>
<table>
  <thead>
      <tr>
          <th>批次</th>
          <th>服務群</th>
          <th>撰寫目的</th>
          <th>狀態</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>S1</td>
          <td>Identity / Cloud IAM</td>
          <td>建立人類身份、機器身份、role / policy baseline</td>
          <td><strong>完成（2026-05-18、7 個 vendor）</strong></td>
      </tr>
      <tr>
          <td>S2</td>
          <td>Secrets / KMS / PKI</td>
          <td>建立 secret、key、certificate lifecycle 與 rotation 判準</td>
          <td><strong>完成（2026-05-18、11 個 vendor）</strong></td>
      </tr>
      <tr>
          <td>S3</td>
          <td>Edge / WAF / Supply chain</td>
          <td>建立入口防護、artifact trust 與 release gate 對照</td>
          <td><strong>完成（2026-05-18、8 個 vendor）</strong></td>
      </tr>
      <tr>
          <td>S4</td>
          <td>SIEM / Detection / DLP</td>
          <td>建立偵測覆蓋、資料保護、證據鏈與事故 handoff</td>
          <td><strong>完成（2026-05-18、7 個 vendor）</strong></td>
      </tr>
  </tbody>
</table>
<h2 id="後續候選c-批次完成">後續候選（C 批次完成）</h2>
<table>
  <thead>
      <tr>
          <th>類型</th>
          <th>候選服務</th>
          <th>寫作重點 / 狀態</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>PAM / access</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/teleport/" data-link-title="Teleport" data-link-desc="Identity-Aware Proxy &#43; PAM、SSH / DB / K8s / Desktop session 統一 short-lived cert &#43; session recording &#43; JIT、跟 Okta / Vault 互補">Teleport</a>、<a href="/blog/backend/07-security-data-protection/vendors/boundary/" data-link-title="HashiCorp Boundary" data-link-desc="Identity-based access broker、跟 Vault 同生態組合（Boundary 控連線 / Vault 給 credential）、Multi-hop Worker 跨網路分段">Boundary</a>、<a href="/blog/backend/07-security-data-protection/vendors/tailscale-ssh/" data-link-title="Tailscale SSH" data-link-desc="WireGuard-based zero-trust mesh &#43; identity-bound SSH、ACL JSON policy、developer-friendly、跟 IdP integration 取代 SSH key">Tailscale SSH</a>、<a href="/blog/backend/07-security-data-protection/vendors/cloudflare-access/" data-link-title="Cloudflare Access" data-link-desc="Zero Trust Network Access (ZTNA)、取代 VPN 的 application-layer access、Argo Tunnel &#43; Device Posture &#43; IdP integration">Cloudflare Access</a></td>
          <td>完成（C1、4 vendor）— 管理面 access、session audit、JIT</td>
      </tr>
      <tr>
          <td>CSPM / CNAPP</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/wiz/" data-link-title="Wiz" data-link-desc="Agentless CNAPP、Security Graph &#43; Toxic Combination 風險優先級、API-only scan 不需 workload agent">Wiz</a>、<a href="/blog/backend/07-security-data-protection/vendors/prisma-cloud/" data-link-title="Prisma Cloud" data-link-desc="Palo Alto CNAPP、agent (Defender) &#43; agentless 雙軌、五模組（Compute / CSPM / Code / Data / CIEM）、Compliance template 強">Prisma Cloud</a>、<a href="/blog/backend/07-security-data-protection/vendors/lacework/" data-link-title="Lacework" data-link-desc="CNAPP 走 Polygraph ML behavioral baseline 路線、2024 跟 Fortinet 合併成 FortiCNAPP、自動學 normal、anomaly 自動 alert">Lacework</a>、<a href="/blog/backend/07-security-data-protection/vendors/crowdstrike-falcon-cs/" data-link-title="CrowdStrike Falcon Cloud Security" data-link-desc="CrowdStrike 在 Falcon endpoint EDR 之上的 CNAPP、agent 統一跨 endpoint &#43; workload &#43; container、CrowdStrike Intelligence 內建">CrowdStrike Falcon CS</a></td>
          <td>完成（C2、4 vendor）— cloud posture、asset inventory、risk prioritization</td>
      </tr>
      <tr>
          <td>Policy as code</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/opa/" data-link-title="Open Policy Agent (OPA)" data-link-desc="CNCF general-purpose policy engine、Rego Datalog-like 語言、decoupled decision &#43; enforcement、跨 K8s / API / Terraform / SQL 統一 policy">OPA</a>、<a href="/blog/backend/07-security-data-protection/vendors/conftest/" data-link-title="Conftest" data-link-desc="OPA CLI wrapper for static config policy check、Rego policy &#43; 多 parser（Terraform / K8s / Dockerfile / JSON）、CI-time gate">Conftest</a>、<a href="/blog/backend/07-security-data-protection/vendors/kyverno/" data-link-title="Kyverno" data-link-desc="K8s-native policy engine、YAML policy（非 Rego）、五類 rule（Validate / Mutate / Generate / Verify Images / Cleanup）、CNCF Incubating">Kyverno</a>、<a href="/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &#43; Constraint 兩層、Rego policy &#43; Audit &#43; Mutation">Gatekeeper</a></td>
          <td>完成（C3、4 vendor）— admission control、policy review、exception workflow</td>
      </tr>
      <tr>
          <td>Runtime detection</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/falco/" data-link-title="Falco" data-link-desc="CNCF Graduated runtime cloud-native threat detection、eBPF / kmod driver、Rule YAML &#43; Falcosidekick &#43; Talon、K8s container runtime 偵測為主">Falco</a>、<a href="/blog/backend/07-security-data-protection/vendors/cilium-tetragon/" data-link-title="Cilium Tetragon" data-link-desc="eBPF-based runtime security &#43; inline enforcement、跟 Cilium CNI 同生態、TracingPolicy CRD、process credentials tracking &#43; KillerAction">Cilium Tetragon</a></td>
          <td>完成（C4、2 vendor）— syscall / runtime signal、container threat detection</td>
      </tr>
      <tr>
          <td>Secret scanning</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/gitguardian/" data-link-title="GitGuardian" data-link-desc="Secret scanning &#43; remediation SaaS、350&#43; Detector &#43; Validation endpoint、跨 SCM &#43; SaaS（Slack / Notion）、Honeytokens decoy">GitGuardian</a>、<a href="/blog/backend/07-security-data-protection/vendors/gitleaks/" data-link-title="Gitleaks" data-link-desc="OSS CLI secret scanner、Go 寫、Rule TOML &#43; regex &#43; entropy、SARIF output、跨 SCM、pre-commit &#43; CI 友善">Gitleaks</a></td>
          <td>完成（C4、2 vendor）— leaked secret detection、developer workflow、rotation trigger</td>
      </tr>
      <tr>
          <td>Data security</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/immuta/" data-link-title="Immuta" data-link-desc="Data security platform、跨 Snowflake / Databricks / BigQuery / Redshift 統一 ABAC &#43; masking、Query Plan Rewriter、native execution">Immuta</a>、<a href="/blog/backend/07-security-data-protection/vendors/privacera/" data-link-title="Privacera" data-link-desc="Data security &#43; AI governance platform、Apache Ranger commercial fork、多 warehouse access control &#43; LLM I/O 治理（PAIG）">Privacera</a>、<a href="/blog/backend/07-security-data-protection/vendors/microsoft-purview/" data-link-title="Microsoft Purview" data-link-desc="Microsoft 跨 M365 / Azure / endpoint 的 data governance &#43; information protection &#43; DLP &#43; insider risk 統合平台、label-driven">Microsoft Purview</a></td>
          <td>完成（C5 + S4、3 vendor）— data access policy、masking、lineage、governance</td>
      </tr>
  </tbody>
</table>
<p>主流覆蓋檢查的重點是分開 preventive control、detective control 與 response handoff。IAM / KMS / WAF / policy-as-code 是 preventive control；SIEM / runtime detection / secret scanning 是 detective control；PAM、incident channel 與 evidence write-back 連到 08 的 response handoff。</p>
<h2 id="reading-paths51-個-vendor-的進入順序建議">Reading paths（51 個 vendor 的進入順序建議）</h2>
<p>讀完 51 個 vendor 不是線性目的、是 <em>依組織當前的安全成熟度跳讀</em>。以下是四條常見路徑：</p>
<p><strong>Path A — Startup baseline（&lt; 50 人、cloud-native）</strong>：
<a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a> → <a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google Cloud IAM</a> → <a href="/blog/backend/07-security-data-protection/vendors/aws-secrets-manager/" data-link-title="AWS Secrets Manager" data-link-desc="AWS 原生 secret store &#43; 內建 RDS / Redshift rotation Lambda、Resource Policy 跨帳號共享、KMS 加密">AWS Secrets Manager</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-secret-manager/" data-link-title="Google Secret Manager" data-link-desc="GCP 原生 secret store、CMEK &#43; Workload Identity Federation 整合、rotation 走自寫 Cloud Function 而非 built-in Lambda">Google Secret Manager</a> → <a href="/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &#43; DDoS &#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF</a> → <a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GitHub Advanced Security</a> → <a href="/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &#43; CSPM &#43; CWS &#43; AAP &#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Security</a>。共 7-8 個 vendor、預算敏感、cloud-native、SaaS 優先。</p>
<p><strong>Path B — Enterprise multi-cloud（500+ 人、跨雲）</strong>：
<a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a> + <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a> → 各雲 IAM（<a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">GCP</a> / <a href="/blog/backend/07-security-data-protection/vendors/azure-rbac/" data-link-title="Azure RBAC &#43; Entra ID" data-link-desc="Azure 雙層身份/權限體系、Entra ID（IdP）&#43; Azure RBAC（resource permission）、Conditional Access、PIM、Managed Identity">Azure</a>）→ <a href="/blog/backend/07-security-data-protection/vendors/aws-kms/" data-link-title="AWS KMS" data-link-desc="AWS 原生 key management service、envelope encryption / digital signing / Multi-Region Key、Key Policy &#43; Grant 雙軌授權">AWS KMS</a> + <a href="/blog/backend/07-security-data-protection/vendors/cloudhsm/" data-link-title="AWS CloudHSM" data-link-desc="Single-tenant dedicated HSM（FIPS 140-2 Level 3）、AWS 不持 Crypto User credential、合規 &#43; 資料主權場景的 key custody">CloudHSM</a> → <a href="/blog/backend/07-security-data-protection/vendors/spire/" data-link-title="SPIRE" data-link-desc="SPIFFE Runtime Environment、attested workload identity、short-lived SVID &#43; Trust Bundle、跨組織 federation">SPIRE</a> + <a href="/blog/backend/07-security-data-protection/vendors/cert-manager/" data-link-title="cert-manager" data-link-desc="K8s 原生 certificate lifecycle automation、支援 Let&#39;s Encrypt / Vault PKI / Venafi 等多 issuer、auto-renewal &#43; Challenge solver">cert-manager</a> → <a href="/blog/backend/07-security-data-protection/vendors/fastly-ngwaf/" data-link-title="Fastly Next-Gen WAF" data-link-desc="Behavioral / 語意分析 WAF（前 Signal Sciences）、低 false positive、Edge / Agent / Cloud 三種部署模型、API &#43; ATO &#43; Bot 一體">Fastly NG-WAF</a> → <a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk</a> + <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> → <a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> → <a href="/blog/backend/07-security-data-protection/vendors/google-dlp/" data-link-title="Google DLP" data-link-desc="GCP 原生 Sensitive Data Protection：infoType discovery &#43; transformation (mask / FPE / tokenize / k-anonymity)、整合 BigQuery / GCS / Cloud SQL">Google DLP</a> + <a href="/blog/backend/07-security-data-protection/vendors/microsoft-purview/" data-link-title="Microsoft Purview" data-link-desc="Microsoft 跨 M365 / Azure / endpoint 的 data governance &#43; information protection &#43; DLP &#43; insider risk 統合平台、label-driven">Microsoft Purview</a>。</p>
<p><strong>Path C — Compliance-heavy（金融 / 醫療 / 政府）</strong>：
<a href="/blog/backend/07-security-data-protection/vendors/keycloak/" data-link-title="Keycloak" data-link-desc="Open source self-hosted Identity Provider、Red Hat 主導、Realm-based multi-tenancy、適合資料主權與自訂 flow 需求">Keycloak</a>（資料主權）→ <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a> + <a href="/blog/backend/07-security-data-protection/vendors/cloudhsm/" data-link-title="AWS CloudHSM" data-link-desc="Single-tenant dedicated HSM（FIPS 140-2 Level 3）、AWS 不持 Crypto User credential、合規 &#43; 資料主權場景的 key custody">CloudHSM</a>（FIPS 140-2 L3）→ <a href="/blog/backend/07-security-data-protection/vendors/cert-manager/" data-link-title="cert-manager" data-link-desc="K8s 原生 certificate lifecycle automation、支援 Let&#39;s Encrypt / Vault PKI / Venafi 等多 issuer、auto-renewal &#43; Challenge solver">cert-manager</a> + <a href="/blog/backend/07-security-data-protection/vendors/letsencrypt/" data-link-title="Let&#39;s Encrypt" data-link-desc="免費 &#43; 自動化的公共 ACME CA、90 天 TTL 強制自動化、跨雲跨平台 public TLS cert 的事實基礎">Let&rsquo;s Encrypt</a> → <a href="/blog/backend/07-security-data-protection/vendors/google-dlp/" data-link-title="Google DLP" data-link-desc="GCP 原生 Sensitive Data Protection：infoType discovery &#43; transformation (mask / FPE / tokenize / k-anonymity)、整合 BigQuery / GCS / Cloud SQL">Google DLP</a> + <a href="/blog/backend/07-security-data-protection/vendors/microsoft-purview/" data-link-title="Microsoft Purview" data-link-desc="Microsoft 跨 M365 / Azure / endpoint 的 data governance &#43; information protection &#43; DLP &#43; insider risk 統合平台、label-driven">Microsoft Purview</a> → <a href="/blog/backend/07-security-data-protection/vendors/cloud-data-policy/" data-link-title="Cloud-native Data Policy (BigQuery &#43; S3)" data-link-desc="BigQuery column / row-level security &#43; S3 bucket policy &#43; Access Points &#43; Macie、雲端原生資料層 access control、跟 DLP / Purview 互補">Cloud-native data policy</a> → <a href="/blog/backend/07-security-data-protection/vendors/google-security-operations/" data-link-title="Google Security Operations" data-link-desc="Google 雲原生 SIEM &#43; SOAR &#43; Mandiant threat intel 三合一（前 Chronicle）、UDM &#43; YARA-L、fixed-price by data tier、PB-scale 友善">Google Security Operations</a>（Mandiant + 大規模）。</p>
<p><strong>Path D — 事故驅動補洞</strong>：先讀 <a href="/blog/backend/07-security-data-protection/cases/" data-link-title="模組七案例正文" data-link-desc="資安控制面與控制平面轉換案例入口。">7.C 案例</a> + <a href="/blog/backend/07-security-data-protection/red-team/cases/" data-link-title="7.R7 事故案例庫（可引用）" data-link-desc="把公開事故整理成可引用案例體系，讓服務章節與 incident workflow 可雙向回寫">紅隊案例</a> 對應自家事故、再回 vendor 頁找控制面缺口。例如 helpdesk social engineering 失效 → <a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a> callback workflow + <a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> anomaly detection；signing key 失控 → <a href="/blog/backend/07-security-data-protection/vendors/aws-kms/" data-link-title="AWS KMS" data-link-desc="AWS 原生 key management service、envelope encryption / digital signing / Multi-Region Key、Key Policy &#43; Grant 雙軌授權">AWS KMS</a> / <a href="/blog/backend/07-security-data-protection/vendors/azure-key-vault/" data-link-title="Azure Key Vault" data-link-desc="Azure 三合一 service（Secret &#43; Key &#43; Certificate）、整合 Managed Identity &#43; Entra ID RBAC、Premium tier 走 HSM">Azure Key Vault</a> HSM-bound key + <a href="/blog/backend/07-security-data-protection/vendors/google-security-operations/" data-link-title="Google Security Operations" data-link-desc="Google 雲原生 SIEM &#43; SOAR &#43; Mandiant threat intel 三合一（前 Chronicle）、UDM &#43; YARA-L、fixed-price by data tier、PB-scale 友善">Google Security Operations</a> cross-tenant token forging detection。</p>
<h2 id="cross-category-整合-stack">Cross-category 整合 stack</h2>
<p>實務 stack 通常跨多個類別組合、不是單一 vendor。下表列三個典型 stack：</p>
<table>
  <thead>
      <tr>
          <th>Stack 場景</th>
          <th>Identity</th>
          <th>Cloud IAM</th>
          <th>Secrets / KMS</th>
          <th>WAF + Supply chain</th>
          <th>SIEM + DLP</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>AWS-only SaaS</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/aws-iam-identity-center/" data-link-title="AWS IAM Identity Center" data-link-desc="AWS 原生 workforce SSO、前 AWS SSO、Permission Set 跨帳號 access、可串外部 IdP federation">AWS IAM Identity Center</a> → <a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM</a></td>
          <td>AWS IAM</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/aws-secrets-manager/" data-link-title="AWS Secrets Manager" data-link-desc="AWS 原生 secret store &#43; 內建 RDS / Redshift rotation Lambda、Resource Policy 跨帳號共享、KMS 加密">AWS Secrets Manager</a> + <a href="/blog/backend/07-security-data-protection/vendors/aws-kms/" data-link-title="AWS KMS" data-link-desc="AWS 原生 key management service、envelope encryption / digital signing / Multi-Region Key、Key Policy &#43; Grant 雙軌授權">AWS KMS</a></td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/aws-waf/" data-link-title="AWS WAF" data-link-desc="AWS-internal WAF、跟 ALB / CloudFront / API Gateway 直接整合、Web ACL &#43; Managed Rule Group &#43; Rate-based Rule、Shield Standard 內含">AWS WAF</a> + <a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GHAS</a></td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / <a href="/blog/backend/07-security-data-protection/vendors/datadog-security/" data-link-title="Datadog Security" data-link-desc="Datadog observability platform 上的 security suite：Cloud SIEM &#43; CSPM &#43; CWS &#43; AAP &#43; Sensitive Data Scanner、跟 observability 同 plane">Datadog Security</a></td>
      </tr>
      <tr>
          <td>Multi-cloud + on-prem</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a>（人類）+ <a href="/blog/backend/07-security-data-protection/vendors/spire/" data-link-title="SPIRE" data-link-desc="SPIFFE Runtime Environment、attested workload identity、short-lived SVID &#43; Trust Bundle、跨組織 federation">SPIRE</a>（workload）</td>
          <td>三家 cloud IAM</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a>（跨雲統一）</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &#43; DDoS &#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF</a> + <a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk</a></td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a>（OSS-friendly）</td>
      </tr>
      <tr>
          <td>Microsoft 365 + Azure heavy</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/azure-rbac/" data-link-title="Azure RBAC &#43; Entra ID" data-link-desc="Azure 雙層身份/權限體系、Entra ID（IdP）&#43; Azure RBAC（resource permission）、Conditional Access、PIM、Managed Identity">Entra ID</a></td>
          <td>Azure RBAC</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/azure-key-vault/" data-link-title="Azure Key Vault" data-link-desc="Azure 三合一 service（Secret &#43; Key &#43; Certificate）、整合 Managed Identity &#43; Entra ID RBAC、Premium tier 走 HSM">Azure Key Vault</a></td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/fastly-ngwaf/" data-link-title="Fastly Next-Gen WAF" data-link-desc="Behavioral / 語意分析 WAF（前 Signal Sciences）、低 false positive、Edge / Agent / Cloud 三種部署模型、API &#43; ATO &#43; Bot 一體">Fastly NG-WAF</a> + <a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GHAS</a></td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/microsoft-purview/" data-link-title="Microsoft Purview" data-link-desc="Microsoft 跨 M365 / Azure / endpoint 的 data governance &#43; information protection &#43; DLP &#43; insider risk 統合平台、label-driven">Microsoft Purview</a> + Sentinel</td>
      </tr>
  </tbody>
</table>
<p>Stack 不是一次到位、按 <a href="#reading-paths33-%e5%80%8b-vendor-%e7%9a%84%e9%80%b2%e5%85%a5%e9%a0%86%e5%ba%8f%e5%bb%ba%e8%ad%b0">Path A → B → C</a> 的成熟度演進加 vendor。每加一個 vendor 都要對應一個 <em>已被 case 庫驗證</em> 的失效模式 — 不是「業界都用」就上。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/identity-access-boundary/" data-link-title="7.2 身分與授權邊界" data-link-desc="以問題驅動方式整理身分、授權、會話與供應商身分鏈">7.2 身分與授權邊界</a></li>
<li>上游：<a href="/blog/backend/07-security-data-protection/secrets-and-machine-credential-governance/" data-link-title="7.6 秘密管理與機器憑證治理" data-link-desc="以問題驅動方式整理 secret、token、key 與機器身份治理">7.6 秘密管理與機器憑證治理</a></li>
<li>上游：<a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">7.12 供應鏈完整性與 Artifact 信任</a></li>
<li>案例：<a href="/blog/backend/07-security-data-protection/cases/" data-link-title="模組七案例正文" data-link-desc="資安控制面與控制平面轉換案例入口。">7.C 資安案例正文</a></li>
<li>服務路徑：<a href="/blog/backend/07-security-data-protection/credential-rotation-scoped-evidence/" data-link-title="7.27 Credential Rotation with Scoped Evidence 實作示範" data-link-desc="以 webhook/API credential 輪替示範 scope map、證據欄位與回退窗口如何一起設計。">7.27 Credential Rotation with Scoped Evidence 實作示範</a></li>
</ul>
]]></content:encoded></item><item><title>可觀測性 Vendor 清單</title><link>https://tarrragon.github.io/blog/backend/04-observability/vendors/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/04-observability/vendors/</guid><description>&lt;p>可觀測性 Vendor 清單的核心責任是把工具名稱放回 telemetry contract、signal ownership、data quality、cardinality 與成本治理的判斷。每個服務頁先回答它承擔 metrics、logs、traces、errors、APM 或平台原生觀測的哪一段，再討論資料模型、查詢能力、成本與案例回寫。觀測這塊能力的買 vs 建特別現實：自建 telemetry stack（Prometheus、Grafana、Loki）、買 observability SaaS（Datadog、New Relic、Grafana Cloud），還是用雲端原生（CloudWatch、Cloud Monitoring）— 取捨與遷出代價見 &lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/capability-buy-vs-build/" data-link-title="0.22 能力級買 vs 建：feature-as-a-service 與 BaaS bundle 選型" data-link-desc="在交付形態決定整個系統要不要自建之後、逐能力判斷該外包還是自建：辨識 managed 基礎設施、feature SaaS 與 BaaS bundle 三種外包深度、no-code 到 dev-tool 的服務光譜、買 vs 建判準與權重浮動、整合接縫與遷出代價">0.22 能力級買 vs 建&lt;/a>。&lt;/p>
&lt;h2 id="讀法">讀法&lt;/h2>
&lt;p>可觀測性服務要從訊號責任進入。讀者如果要建立 metrics baseline，先回到 &lt;a href="https://tarrragon.github.io/blog/backend/04-observability/metrics-basics/" data-link-title="4.2 metrics 與 SLI/SLO" data-link-desc="整理 counter、gauge、histogram 與服務健康指標">Metrics Basics&lt;/a>；如果要處理資料品質，先回到 &lt;a href="https://tarrragon.github.io/blog/backend/04-observability/telemetry-data-quality/" data-link-title="4.17 Telemetry Data Quality" data-link-desc="把 missing signal、schema drift、sampling bias 與 timestamp skew 變成資料品質問題">4.17 Telemetry Data Quality&lt;/a>；如果要交付 evidence，先回到 &lt;a href="https://tarrragon.github.io/blog/backend/04-observability/observability-evidence-package/" data-link-title="4.20 Observability Evidence Package" data-link-desc="把 log、metric、trace、audit 與資料品質限制包成可交接證據">4.20 Observability Evidence Package&lt;/a>。&lt;/p>
&lt;h2 id="教學順序同步">教學順序同步&lt;/h2>
&lt;p>可觀測性服務頁的教學順序是先建立 OpenTelemetry 標準入口，再比較 metrics / logs / traces backend、SaaS observability 與 cloud-native 工具。這個順序服務 E1-E7 所有 checkout episode：每個服務變更都要把訊號整理成 evidence package，讀者要先理解 signal quality，再進入 vendor 能力與成本模型。&lt;/p>
&lt;h2 id="t1-服務頁大綱">T1 服務頁大綱&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>服務&lt;/th>
 &lt;th>類型&lt;/th>
 &lt;th>頁面要回答的核心問題&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/04-observability/vendors/opentelemetry/" data-link-title="OpenTelemetry" data-link-desc="可觀測性開放標準、SDK 與 Collector">OpenTelemetry&lt;/a>&lt;/td>
 &lt;td>Standard / SDK&lt;/td>
 &lt;td>instrumentation、collector、semantic convention 如何降低 vendor lock-in&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/04-observability/vendors/prometheus/" data-link-title="Prometheus" data-link-desc="Pull-based metrics 主流 OSS、PromQL 與 alerting">Prometheus&lt;/a>&lt;/td>
 &lt;td>Metrics&lt;/td>
 &lt;td>pull model、PromQL、cardinality 與 retention 如何取捨&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/04-observability/vendors/grafana-stack/" data-link-title="Grafana Stack" data-link-desc="Grafana / Loki / Tempo / Mimir / Pyroscope 全棧">Grafana Stack&lt;/a>&lt;/td>
 &lt;td>OSS / Cloud stack&lt;/td>
 &lt;td>Grafana、Loki、Tempo、Mimir 如何組成可觀測性平台&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/04-observability/vendors/datadog/" data-link-title="Datadog" data-link-desc="All-in-one SaaS 觀測平台、APM / Logs / Metrics / RUM / Security">Datadog&lt;/a>&lt;/td>
 &lt;td>SaaS APM&lt;/td>
 &lt;td>all-in-one APM、logs、traces、profiling 與成本治理如何取捨&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/04-observability/vendors/elastic-stack/" data-link-title="Elastic Stack" data-link-desc="ELK：Elasticsearch / Logstash / Kibana &amp;#43; Beats / APM">Elastic Stack&lt;/a>&lt;/td>
 &lt;td>Search / logs&lt;/td>
 &lt;td>log search、index lifecycle、APM 與資料量成本如何治理&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/04-observability/vendors/honeycomb/" data-link-title="Honeycomb" data-link-desc="High-cardinality observability 平台、events-based 模型">Honeycomb&lt;/a>&lt;/td>
 &lt;td>High-cardinality&lt;/td>
 &lt;td>event-based observability 與 high-cardinality 查詢如何支援除錯&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/04-observability/vendors/aws-cloudwatch/" data-link-title="AWS CloudWatch" data-link-desc="AWS 原生觀測性服務、Logs / Metrics / Traces (X-Ray)">AWS CloudWatch&lt;/a>&lt;/td>
 &lt;td>AWS-native&lt;/td>
 &lt;td>AWS metrics、logs、alarms 與 account / region 邊界如何管理&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/04-observability/vendors/gcp-cloud-operations/" data-link-title="GCP Cloud Operations" data-link-desc="GCP 原生觀測性套件（前 Stackdriver）：Logging / Monitoring / Trace / Profiler">GCP Cloud Operations&lt;/a>&lt;/td>
 &lt;td>GCP-native&lt;/td>
 &lt;td>Cloud Monitoring、Logging、Trace 與 GCP resource model 如何整合&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/04-observability/vendors/sentry/" data-link-title="Sentry" data-link-desc="Error tracking 主流、APM / Profiling / Session Replay 擴展">Sentry&lt;/a>&lt;/td>
 &lt;td>Error tracking&lt;/td>
 &lt;td>error event、release、trace、session replay 如何連到 owner action&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="內容覆蓋進度">內容覆蓋進度&lt;/h2>
&lt;p>每個 vendor 服務頁下會擴充兩類文章：deep article（vendor 自身的配置、故障、容量、走 &lt;a href="https://tarrragon.github.io/blog/posts/vendor-%E6%B7%B1%E5%BA%A6%E6%8A%80%E8%A1%93%E6%96%87%E7%AB%A0%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84%E5%90%8C-vendor-%E7%B3%BB%E5%88%97%E7%9A%84%E9%96%8B%E5%A0%B4%E8%BC%AA%E6%9B%BF%E9%A9%97%E8%AD%89/" data-link-title="Vendor 深度技術文章方法論的演化紀錄：同 vendor 系列的開場輪替驗證" data-link-desc="vendor overview 飽和後要寫單一功能深度文章、需要選題與結構依據時回來。這套方法論的驗證來源與 cadence variant 在高風險場景（同 vendor sub-tool 系列）的實證。">6-section 模板&lt;/a>）跟 migration playbook（跨 vendor 遷移流程、走 &lt;a href="https://tarrragon.github.io/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">6-type 結構&lt;/a>）。「→ X」代表遷移到 X 的 playbook、「← X」代表從 X 遷入、其他形式代表 same-vendor 的 topology / version / config 變動。&lt;/p></description><content:encoded><![CDATA[<p>可觀測性 Vendor 清單的核心責任是把工具名稱放回 telemetry contract、signal ownership、data quality、cardinality 與成本治理的判斷。每個服務頁先回答它承擔 metrics、logs、traces、errors、APM 或平台原生觀測的哪一段，再討論資料模型、查詢能力、成本與案例回寫。觀測這塊能力的買 vs 建特別現實：自建 telemetry stack（Prometheus、Grafana、Loki）、買 observability SaaS（Datadog、New Relic、Grafana Cloud），還是用雲端原生（CloudWatch、Cloud Monitoring）— 取捨與遷出代價見 <a href="/blog/backend/00-service-selection/capability-buy-vs-build/" data-link-title="0.22 能力級買 vs 建：feature-as-a-service 與 BaaS bundle 選型" data-link-desc="在交付形態決定整個系統要不要自建之後、逐能力判斷該外包還是自建：辨識 managed 基礎設施、feature SaaS 與 BaaS bundle 三種外包深度、no-code 到 dev-tool 的服務光譜、買 vs 建判準與權重浮動、整合接縫與遷出代價">0.22 能力級買 vs 建</a>。</p>
<h2 id="讀法">讀法</h2>
<p>可觀測性服務要從訊號責任進入。讀者如果要建立 metrics baseline，先回到 <a href="/blog/backend/04-observability/metrics-basics/" data-link-title="4.2 metrics 與 SLI/SLO" data-link-desc="整理 counter、gauge、histogram 與服務健康指標">Metrics Basics</a>；如果要處理資料品質，先回到 <a href="/blog/backend/04-observability/telemetry-data-quality/" data-link-title="4.17 Telemetry Data Quality" data-link-desc="把 missing signal、schema drift、sampling bias 與 timestamp skew 變成資料品質問題">4.17 Telemetry Data Quality</a>；如果要交付 evidence，先回到 <a href="/blog/backend/04-observability/observability-evidence-package/" data-link-title="4.20 Observability Evidence Package" data-link-desc="把 log、metric、trace、audit 與資料品質限制包成可交接證據">4.20 Observability Evidence Package</a>。</p>
<h2 id="教學順序同步">教學順序同步</h2>
<p>可觀測性服務頁的教學順序是先建立 OpenTelemetry 標準入口，再比較 metrics / logs / traces backend、SaaS observability 與 cloud-native 工具。這個順序服務 E1-E7 所有 checkout episode：每個服務變更都要把訊號整理成 evidence package，讀者要先理解 signal quality，再進入 vendor 能力與成本模型。</p>
<h2 id="t1-服務頁大綱">T1 服務頁大綱</h2>
<table>
  <thead>
      <tr>
          <th>服務</th>
          <th>類型</th>
          <th>頁面要回答的核心問題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/04-observability/vendors/opentelemetry/" data-link-title="OpenTelemetry" data-link-desc="可觀測性開放標準、SDK 與 Collector">OpenTelemetry</a></td>
          <td>Standard / SDK</td>
          <td>instrumentation、collector、semantic convention 如何降低 vendor lock-in</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/04-observability/vendors/prometheus/" data-link-title="Prometheus" data-link-desc="Pull-based metrics 主流 OSS、PromQL 與 alerting">Prometheus</a></td>
          <td>Metrics</td>
          <td>pull model、PromQL、cardinality 與 retention 如何取捨</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/04-observability/vendors/grafana-stack/" data-link-title="Grafana Stack" data-link-desc="Grafana / Loki / Tempo / Mimir / Pyroscope 全棧">Grafana Stack</a></td>
          <td>OSS / Cloud stack</td>
          <td>Grafana、Loki、Tempo、Mimir 如何組成可觀測性平台</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/04-observability/vendors/datadog/" data-link-title="Datadog" data-link-desc="All-in-one SaaS 觀測平台、APM / Logs / Metrics / RUM / Security">Datadog</a></td>
          <td>SaaS APM</td>
          <td>all-in-one APM、logs、traces、profiling 與成本治理如何取捨</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/04-observability/vendors/elastic-stack/" data-link-title="Elastic Stack" data-link-desc="ELK：Elasticsearch / Logstash / Kibana &#43; Beats / APM">Elastic Stack</a></td>
          <td>Search / logs</td>
          <td>log search、index lifecycle、APM 與資料量成本如何治理</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/04-observability/vendors/honeycomb/" data-link-title="Honeycomb" data-link-desc="High-cardinality observability 平台、events-based 模型">Honeycomb</a></td>
          <td>High-cardinality</td>
          <td>event-based observability 與 high-cardinality 查詢如何支援除錯</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/04-observability/vendors/aws-cloudwatch/" data-link-title="AWS CloudWatch" data-link-desc="AWS 原生觀測性服務、Logs / Metrics / Traces (X-Ray)">AWS CloudWatch</a></td>
          <td>AWS-native</td>
          <td>AWS metrics、logs、alarms 與 account / region 邊界如何管理</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/04-observability/vendors/gcp-cloud-operations/" data-link-title="GCP Cloud Operations" data-link-desc="GCP 原生觀測性套件（前 Stackdriver）：Logging / Monitoring / Trace / Profiler">GCP Cloud Operations</a></td>
          <td>GCP-native</td>
          <td>Cloud Monitoring、Logging、Trace 與 GCP resource model 如何整合</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/04-observability/vendors/sentry/" data-link-title="Sentry" data-link-desc="Error tracking 主流、APM / Profiling / Session Replay 擴展">Sentry</a></td>
          <td>Error tracking</td>
          <td>error event、release、trace、session replay 如何連到 owner action</td>
      </tr>
  </tbody>
</table>
<h2 id="內容覆蓋進度">內容覆蓋進度</h2>
<p>每個 vendor 服務頁下會擴充兩類文章：deep article（vendor 自身的配置、故障、容量、走 <a href="/blog/posts/vendor-%E6%B7%B1%E5%BA%A6%E6%8A%80%E8%A1%93%E6%96%87%E7%AB%A0%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84%E5%90%8C-vendor-%E7%B3%BB%E5%88%97%E7%9A%84%E9%96%8B%E5%A0%B4%E8%BC%AA%E6%9B%BF%E9%A9%97%E8%AD%89/" data-link-title="Vendor 深度技術文章方法論的演化紀錄：同 vendor 系列的開場輪替驗證" data-link-desc="vendor overview 飽和後要寫單一功能深度文章、需要選題與結構依據時回來。這套方法論的驗證來源與 cadence variant 在高風險場景（同 vendor sub-tool 系列）的實證。">6-section 模板</a>）跟 migration playbook（跨 vendor 遷移流程、走 <a href="/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">6-type 結構</a>）。「→ X」代表遷移到 X 的 playbook、「← X」代表從 X 遷入、其他形式代表 same-vendor 的 topology / version / config 變動。</p>
<table>
  <thead>
      <tr>
          <th>Vendor</th>
          <th>Deep article</th>
          <th>Migration playbook</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="aws-cloudwatch/">AWS CloudWatch</a></td>
          <td><a href="aws-cloudwatch/logs-insights-governance/">Logs Insights 治理</a> / <a href="aws-cloudwatch/alarms-composite-operations/">Alarms 與 Composite</a></td>
          <td>—</td>
      </tr>
      <tr>
          <td><a href="datadog/">Datadog</a></td>
          <td><a href="datadog/cost-governance-agent-config/">成本治理與 Agent 配置</a> / <a href="datadog/otlp-ingestion-otel-integration/">OTLP Ingestion 與 OTel 整合</a></td>
          <td><a href="datadog/migrate-from-new-relic/">← New Relic</a> / <a href="datadog/migrate-to-grafana-stack/">→ Grafana Stack</a></td>
      </tr>
      <tr>
          <td><a href="elastic-stack/">Elastic Stack</a></td>
          <td><a href="elastic-stack/ilm-log-pipeline/">ILM 與 Log Pipeline</a></td>
          <td><a href="elastic-stack/migrate-to-elastic-cloud/">→ Elastic Cloud</a></td>
      </tr>
      <tr>
          <td><a href="gcp-cloud-operations/">GCP Cloud Ops</a></td>
          <td><a href="gcp-cloud-operations/cloud-monitoring-mql/">Monitoring MQL</a> / <a href="gcp-cloud-operations/cloud-logging-export-compliance/">Logging 匯出合規</a></td>
          <td>—</td>
      </tr>
      <tr>
          <td><a href="grafana-stack/">Grafana Stack</a></td>
          <td><a href="grafana-stack/lgtm-stack-operations/">LGTM Stack Operations</a> / <a href="grafana-stack/loki-design-operational-limits/">Loki 設計與操作限制</a></td>
          <td><a href="grafana-stack/migrate-prometheus-to-cloud-metrics/">Prometheus → Cloud Metrics</a></td>
      </tr>
      <tr>
          <td><a href="honeycomb/">Honeycomb</a></td>
          <td><a href="honeycomb/high-cardinality-query-bubbleup/">High-Cardinality BubbleUp</a></td>
          <td><a href="honeycomb/migrate-from-sentry/">← Sentry</a></td>
      </tr>
      <tr>
          <td><a href="opentelemetry/">OpenTelemetry</a></td>
          <td><a href="opentelemetry/collector-deployment-patterns/">Collector 部署模式</a></td>
          <td>—</td>
      </tr>
      <tr>
          <td><a href="prometheus/">Prometheus</a></td>
          <td><a href="prometheus/capacity-failure-modes/">容量規劃與故障模式</a> / <a href="prometheus/promql-recording-rules/">PromQL 與 Recording Rules</a> / <a href="prometheus/remote-write-long-term-storage/">Remote Write 與長期儲存</a></td>
          <td>—</td>
      </tr>
      <tr>
          <td><a href="sentry/">Sentry</a></td>
          <td><a href="sentry/error-grouping-fingerprinting/">Error Grouping Fingerprinting</a> / <a href="sentry/release-tracking-session-replay/">Release Tracking Session Replay</a></td>
          <td>—</td>
      </tr>
  </tbody>
</table>
<p>進度（2026-06-23）：9 個 T1 vendor 全部有 deep article（共 21 篇）。OpenTelemetry 後續候選：Sampling 策略 / Auto-instrumentation。各 vendor 進階主題的更多 deep article 見各自 <code>_index.md</code> 的「預計實作話題」段。</p>
<h2 id="服務頁撰寫欄位">服務頁撰寫欄位</h2>
<table>
  <thead>
      <tr>
          <th>欄位</th>
          <th>可觀測性服務頁要保留的問題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>服務責任</td>
          <td>它承擔 signal standard、metrics、logs、traces、error tracking 還是 APM platform</td>
      </tr>
      <tr>
          <td>適用壓力</td>
          <td>cardinality、retention、debug speed、multi-cloud、compliance、成本哪個壓力最明顯</td>
      </tr>
      <tr>
          <td>替代邊界</td>
          <td>OSS stack、cloud-native、SaaS APM、specialized error tracking 的機會成本</td>
      </tr>
      <tr>
          <td>操作成本</td>
          <td>instrumentation、agent、collector、index、retention、query cost、PII governance</td>
      </tr>
      <tr>
          <td>Evidence</td>
          <td>dashboard、query link、trace sample、log sample、alert rule、data quality note</td>
      </tr>
      <tr>
          <td>案例回寫</td>
          <td>事故、capacity、release gate 與 cost attribution 如何回寫成 evidence package</td>
      </tr>
  </tbody>
</table>
<h2 id="服務頁標準章節">服務頁標準章節</h2>
<table>
  <thead>
      <tr>
          <th>章節</th>
          <th>可觀測性服務頁要補的內容</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>服務定位</td>
          <td>它是 standard、metrics backend、log search、trace backend、APM 還是 error tracking</td>
      </tr>
      <tr>
          <td>本章目標</td>
          <td>讀者能判斷 signal ownership、data quality、cardinality、retention 與 cost</td>
      </tr>
      <tr>
          <td>最短判讀路徑</td>
          <td>用「現在缺哪個訊號會阻止決策」快速判斷該看 metrics、logs、traces 或 errors</td>
      </tr>
      <tr>
          <td>日常操作與決策形狀</td>
          <td>instrumentation、collector、agent、dashboard、alert、retention</td>
      </tr>
      <tr>
          <td>核心取捨表</td>
          <td>OSS stack、SaaS APM、cloud-native、specialized tool 的機會成本</td>
      </tr>
      <tr>
          <td>進階主題</td>
          <td>high-cardinality、sampling、multi-cloud、PII redaction、cost attribution</td>
      </tr>
      <tr>
          <td>排錯與失敗快速判讀</td>
          <td>missing signal、label explosion、trace gap、log index cost、alert noise</td>
      </tr>
      <tr>
          <td>何時改走其他服務</td>
          <td>標準化先用 OpenTelemetry、規模化 metrics 轉 managed backend、事故協作轉 08</td>
      </tr>
      <tr>
          <td>不在本頁內的主題</td>
          <td>每種語言 SDK 完整教學、dashboard 美術、所有 query cookbook</td>
      </tr>
      <tr>
          <td>案例回寫與下一步路由</td>
          <td>回到 4.20 evidence package、9.8 performance observability、8 incident cases</td>
      </tr>
  </tbody>
</table>
<h2 id="跨-vendor-議題對照">跨 vendor 議題對照</h2>
<p>橫向議題在不同 vendor 用不同 mechanism 達成。本表列同一議題在 9 個 vendor 的對應位置、確保大綱不缺漏、讀者跨 vendor 查找時有索引。</p>
<table>
  <thead>
      <tr>
          <th>議題</th>
          <th>OTel</th>
          <th>Prometheus</th>
          <th>Grafana Stack</th>
          <th>Datadog</th>
          <th>Elastic Stack</th>
          <th>Honeycomb</th>
          <th>CloudWatch</th>
          <th>Cloud Ops</th>
          <th>Sentry</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>訊號類型</td>
          <td>全（標準）</td>
          <td>metrics</td>
          <td>全 stack</td>
          <td>全 + Security</td>
          <td>logs + APM</td>
          <td>events / traces</td>
          <td>全 AWS-native</td>
          <td>全 GCP-native</td>
          <td>errors + APM</td>
      </tr>
      <tr>
          <td>採集模式</td>
          <td>SDK + Collector</td>
          <td>Pull scrape</td>
          <td>mixed</td>
          <td>Agent push</td>
          <td>Beats / Agent</td>
          <td>SDK / OTLP</td>
          <td>Agent / native</td>
          <td>Agent / native</td>
          <td>SDK push</td>
      </tr>
      <tr>
          <td>查詢語言</td>
          <td>N/A</td>
          <td>PromQL</td>
          <td>PromQL/LogQL/TraceQL</td>
          <td>Datadog query</td>
          <td>KQL / ES DSL</td>
          <td>Honeycomb query</td>
          <td>Logs Insights</td>
          <td>Logs query</td>
          <td>Issue filter</td>
      </tr>
      <tr>
          <td>Cardinality</td>
          <td>由 backend 決定</td>
          <td>受限（series）</td>
          <td>Mimir / Loki 各自</td>
          <td>計費 per dim</td>
          <td>Mapping limit</td>
          <td>設計目標 (high)</td>
          <td>計費 per metric</td>
          <td>計費 per metric</td>
          <td>issue grouping</td>
      </tr>
      <tr>
          <td>部署模式</td>
          <td>OSS standard</td>
          <td>OSS self-host</td>
          <td>OSS / Cloud</td>
          <td>SaaS only</td>
          <td>OSS / Cloud</td>
          <td>SaaS only</td>
          <td>AWS managed</td>
          <td>GCP managed</td>
          <td>OSS / SaaS</td>
      </tr>
      <tr>
          <td>成本模型</td>
          <td>取決 backend</td>
          <td>self-host CapEx</td>
          <td>self-host / Cloud</td>
          <td>hosts + signals</td>
          <td>self-host</td>
          <td>events volume</td>
          <td>ingestion + API</td>
          <td>ingestion + API</td>
          <td>events volume</td>
      </tr>
      <tr>
          <td>多雲 / 跨平台</td>
          <td>是（標準）</td>
          <td>是 (OSS)</td>
          <td>是</td>
          <td>是</td>
          <td>是</td>
          <td>是</td>
          <td>AWS-only</td>
          <td>GCP-only</td>
          <td>是</td>
      </tr>
      <tr>
          <td>OTel 相容度</td>
          <td>原生</td>
          <td>exporter</td>
          <td>OTLP receiver</td>
          <td>OTLP ingestion</td>
          <td>OTLP ES 7.16+</td>
          <td>OTLP 原生</td>
          <td>ADOT</td>
          <td>OTLP Trace 2.0+</td>
          <td>OTel context</td>
      </tr>
      <tr>
          <td>主討論案例</td>
          <td>C2/C3/C4/C5/C8</td>
          <td>C1/C6/C7</td>
          <td>C6/C11</td>
          <td>C5</td>
          <td>C5/C6</td>
          <td>C7</td>
          <td>C1/C8</td>
          <td>C3</td>
          <td>待補</td>
      </tr>
  </tbody>
</table>
<p>對照表的用途有三：</p>
<ul>
<li>寫某 vendor 頁時、檢查橫向議題是否有對應的進階主題子段</li>
<li>讀者選型時、知道對應 mechanism 在不同 vendor 的形態</li>
<li>評估遷移風險：訊號類型 + 部署模式 + OTel 相容度三維度合併判讀</li>
</ul>
<p>下面 8 段把對照表的每行展開、避免裸表格成為終點。</p>
<h3 id="訊號類型">訊號類型</h3>
<p>訊號類型決定 vendor 解決哪一段觀測問題。<strong>OpenTelemetry</strong> 是 standard、覆蓋 traces / metrics / logs；<strong>Prometheus</strong> 純 metrics；<strong>Grafana Stack</strong> 全 stack（各 backend 各司其職、Loki + Tempo + Mimir + Pyroscope）；<strong>Datadog</strong> 全 + Security + RUM + CI；<strong>Elastic Stack</strong> logs 為主 + APM；<strong>Honeycomb</strong> events-based（不是 metrics aggregation）；<strong>CloudWatch / Cloud Operations</strong> 雲原生全 stack（含 traces / profiler）；<strong>Sentry</strong> 專精 error tracking + 簡易 APM。</p>
<p>選型判讀：缺哪個訊號 → 補對應 vendor；想 turnkey 全棧 → Datadog / cloud-native；想 OSS 全棧 → Grafana Stack；error tracking 已有 → Sentry / Bugsnag 補強。</p>
<h3 id="採集模式">採集模式</h3>
<p>採集模式影響部署複雜度跟 instrumentation 工作量。<strong>OTel</strong> 是 SDK + Collector 兩層；<strong>Prometheus</strong> 是 pull scrape（service discovery）；<strong>Grafana Stack</strong> 各 backend 模式不同（Loki push / Tempo OTLP / Mimir remote write）；<strong>Datadog</strong> Agent push；<strong>Elastic</strong> Beats / Logstash / Agent；<strong>Honeycomb</strong> SDK push 或 OTLP；<strong>CloudWatch / Cloud Ops</strong> 雲服務內建 + Agent；<strong>Sentry</strong> SDK push。</p>
<p>選型判讀：服務在 K8s + 想自管 → Prometheus pull + Operator；應用層 push → OTel SDK + Collector；不想配 instrumentation → Datadog / cloud-native 自動。</p>
<h3 id="查詢語言">查詢語言</h3>
<p>查詢語言差異影響 dashboard / alert 設計成本。<strong>Prometheus PromQL</strong>（業界 metrics query 標準）；<strong>Grafana</strong> 支援 PromQL（Mimir）/ LogQL（Loki）/ TraceQL（Tempo）；<strong>Datadog</strong> 自家 query syntax；<strong>Elastic</strong> KQL / Lucene / ES DSL / ES|QL；<strong>Honeycomb</strong> point-and-click + 簡單 query；<strong>CloudWatch</strong> Logs Insights syntax；<strong>Cloud Ops</strong> 類似但 GCP-specific；<strong>Sentry</strong> 是 issue filter、不算 query language。</p>
<p>選型判讀：跨 vendor 統一 → 學 PromQL + LogQL（Grafana 通用）；vendor-specific → 依該 vendor 學；OTel 不解決 query 問題（純 instrumentation 標準）。</p>
<h3 id="cardinality-處理">Cardinality 處理</h3>
<p>Cardinality 是 observability 成本跟可用性的關鍵。<strong>Prometheus</strong> 受限（series 爆炸會 OOM）；<strong>Datadog</strong> custom metrics 計費 per dimension；<strong>CloudWatch / Cloud Ops</strong> metrics 計費 per metric；<strong>Elastic</strong> mapping field limit；<strong>Honeycomb</strong> 設計目標就是 high-cardinality（events-based）；<strong>Grafana Stack</strong> Mimir 多 tenant 各自 cardinality budget；<strong>Sentry</strong> 用 issue grouping 替代 cardinality 概念。</p>
<p>選型判讀：high-cardinality 是核心需求（per-user / per-request debug）→ Honeycomb；中等 cardinality + 成本敏感 → Prometheus + 設計謹慎；任意 cardinality + 計費承擔 → Datadog。</p>
<h3 id="部署模式">部署模式</h3>
<p>部署模式決定運維責任歸屬。<strong>OTel</strong> 是 standard、各 backend 各自部署；<strong>Prometheus</strong> OSS self-host；<strong>Grafana Stack</strong> OSS self-host / Grafana Cloud；<strong>Datadog / Honeycomb / Sentry</strong> SaaS（Sentry 有 self-host OSS）；<strong>Elastic</strong> OSS / Elastic Cloud / OpenSearch fork；<strong>CloudWatch / Cloud Ops</strong> 雲原生 managed。</p>
<p>選型判讀：要極致控制 → self-host OSS；不想運維 → SaaS（Datadog / Honeycomb / Sentry）；已在 AWS / GCP → 雲原生 + 補強；混合模式 → OTel 抽象層 + 多 backend。</p>
<h3 id="成本模型">成本模型</h3>
<p>成本模型差異大、容易誤判。<strong>OTel</strong> 本身無成本、取決下游 backend；<strong>Prometheus</strong> self-host CapEx（compute + storage）；<strong>Grafana Stack</strong> self-host CapEx 或 Grafana Cloud OpEx；<strong>Datadog</strong> hosts + signal 各自計費（容易堆疊）；<strong>Elastic</strong> self-host CapEx 或 Elastic Cloud；<strong>Honeycomb</strong> events volume；<strong>CloudWatch / Cloud Ops</strong> ingestion + API call；<strong>Sentry</strong> events / users / replays 計費。</p>
<p>選型判讀：可預期固定成本 → self-host（CapEx）；流量不穩 → SaaS（OpEx + 預警）；多訊號類型 → Datadog 容易爆、Honeycomb 計費單純；AWS / GCP-only 場景 → 雲原生通常 cheaper than 第三方 SaaS。</p>
<h3 id="多雲--跨平台">多雲 / 跨平台</h3>
<p>多雲決定 vendor 鎖定風險。<strong>OTel</strong> 是抽象層、最不 lock-in；<strong>Prometheus / Grafana Stack / Elastic / Datadog / Honeycomb / Sentry</strong> 都支援多雲；<strong>CloudWatch</strong> AWS-only；<strong>Cloud Ops</strong> GCP-only；<strong>Azure Monitor</strong> Azure-only（T2 候選）。</p>
<p>選型判讀：多雲 → 避免 AWS / GCP-only vendor、用 Datadog / Grafana Stack / OTel + multi-backend；單一雲 → 雲原生通常成本最低；既有混合 → OTel 標準化 + 漸進遷移。</p>
<h3 id="otel-相容度">OTel 相容度</h3>
<p>OTel 相容度影響 vendor 切換成本。各 vendor 接受程度：</p>
<ul>
<li>完全相容（drop-in）：Honeycomb / Grafana Tempo / Cloud Trace（2.0+）</li>
<li>接受但 feature 落後 vendor SDK：Datadog / CloudWatch（X-Ray 整合）/ Elastic APM</li>
<li>跟 OTel 互補但設計不同：Prometheus（exporter pattern）/ Sentry（OTel context）</li>
</ul>
<p>選型判讀：未來想換 vendor → 從 day 1 用 OTel SDK；不換 vendor → vendor SDK 較深；多 backend dual ship → OTel 幾乎是唯一可行路徑。</p>
<h2 id="撰寫批次">撰寫批次</h2>
<table>
  <thead>
      <tr>
          <th>批次</th>
          <th>服務頁</th>
          <th>撰寫目的</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>O1</td>
          <td>OpenTelemetry</td>
          <td>建立 instrumentation standard、collector 與 vendor portability</td>
      </tr>
      <tr>
          <td>O2</td>
          <td>Prometheus / Grafana Stack</td>
          <td>建立 metrics baseline、cardinality 與 OSS platform 判準</td>
      </tr>
      <tr>
          <td>O3</td>
          <td>Elastic Stack / Datadog / Honeycomb / Sentry</td>
          <td>建立 logs / APM / high-cardinality / error tracking 對照</td>
      </tr>
      <tr>
          <td>O4</td>
          <td>AWS CloudWatch / GCP Cloud Operations</td>
          <td>建立 cloud-native observability 與 account / project 邊界</td>
      </tr>
  </tbody>
</table>
<h2 id="後續候選">後續候選</h2>
<table>
  <thead>
      <tr>
          <th>類型</th>
          <th>候選服務</th>
          <th>寫作重點</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Enterprise APM</td>
          <td>New Relic、Dynatrace、Splunk Observability</td>
          <td>SaaS APM、enterprise workflow、成本治理</td>
      </tr>
      <tr>
          <td>OSS / Hybrid</td>
          <td>SigNoz、Chronosphere、VictoriaMetrics、Thanos、Cortex</td>
          <td>Prometheus scale、managed metrics、OpenTelemetry ingestion</td>
      </tr>
      <tr>
          <td>Tracing</td>
          <td>Jaeger、OpenSearch Observability</td>
          <td>trace backend、OpenTelemetry-native ingestion、log correlation</td>
      </tr>
      <tr>
          <td>Logs / pipeline</td>
          <td>Fluent Bit、Fluentd、Vector、OpenSearch</td>
          <td>log shipping、filtering、index lifecycle、cost</td>
      </tr>
      <tr>
          <td>Error tracking</td>
          <td>Bugsnag、Rollbar、Raygun</td>
          <td>release health、frontend / backend error ownership</td>
      </tr>
      <tr>
          <td>Cloud-native</td>
          <td>Azure Monitor</td>
          <td>Azure resource model、Log Analytics、cost boundary</td>
      </tr>
  </tbody>
</table>
<p>主流覆蓋檢查的重點是分開 instrumentation、metrics、logs、traces、APM 與 error tracking。OpenTelemetry 是標準入口，Prometheus / Thanos / Cortex / VictoriaMetrics 是 metrics 路線，Loki / OpenSearch / Elastic 是 logs / search 路線，Jaeger / Tempo 是 tracing 路線，Datadog / New Relic / Dynatrace / Splunk 是 SaaS APM 路線。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/04-observability/telemetry-data-quality/" data-link-title="4.17 Telemetry Data Quality" data-link-desc="把 missing signal、schema drift、sampling bias 與 timestamp skew 變成資料品質問題">4.17 Telemetry Data Quality</a></li>
<li>上游：<a href="/blog/backend/04-observability/observability-evidence-package/" data-link-title="4.20 Observability Evidence Package" data-link-desc="把 log、metric、trace、audit 與資料品質限制包成可交接證據">4.20 Observability Evidence Package</a></li>
<li>服務路徑：<a href="/blog/backend/04-observability/checkout-api-evidence-package/" data-link-title="4.22 Checkout API Evidence Package 實作示範" data-link-desc="用 checkout 路徑示範 evidence package 如何交接給 release gate 與 incident decision。">4.22 Checkout API Evidence Package 實作示範</a></li>
<li>跨模組：<a href="/blog/backend/09-performance-capacity/performance-observability/" data-link-title="9.8 效能可觀測性" data-link-desc="saturation metric、USE / RED method、cost dashboard">9.8 效能可觀測性</a></li>
</ul>
]]></content:encoded></item><item><title>快取 Vendor 清單</title><link>https://tarrragon.github.io/blog/backend/02-cache-redis/vendors/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/02-cache-redis/vendors/</guid><description>&lt;p>快取 Vendor 清單的核心責任是把 cache 服務名稱放回副本語意、資料新鮮度、回源保護與操作成本的判斷。每個服務頁先回答它承擔哪種暫存責任，再討論資料型別、失效策略、容量模型、HA / managed 邊界與案例回寫。在挑單一服務之前先有一個更上層的判斷：這塊快取能力該自管 Redis、用 managed cache（ElastiCache、MemoryDB）、還是用 serverless cache（Upstash）或含 cache 的 BaaS bundle — 逐能力的買 vs 建判讀見 &lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/capability-buy-vs-build/" data-link-title="0.22 能力級買 vs 建：feature-as-a-service 與 BaaS bundle 選型" data-link-desc="在交付形態決定整個系統要不要自建之後、逐能力判斷該外包還是自建：辨識 managed 基礎設施、feature SaaS 與 BaaS bundle 三種外包深度、no-code 到 dev-tool 的服務光譜、買 vs 建判準與權重浮動、整合接縫與遷出代價">0.22 能力級買 vs 建&lt;/a>。&lt;/p>
&lt;h2 id="讀法">讀法&lt;/h2>
&lt;p>快取服務要從資料生命週期進入。讀者如果要保護資料庫讀取壓力，先回到 &lt;a href="https://tarrragon.github.io/blog/backend/02-cache-redis/cache-aside/" data-link-title="2.2 cache aside 與失效策略" data-link-desc="整理 read-through 思路、cache miss 與 invalidation">2.2 Cache Aside&lt;/a>；如果要判斷 TTL 與淘汰，先回到 &lt;a href="https://tarrragon.github.io/blog/backend/02-cache-redis/ttl-eviction/" data-link-title="2.3 TTL 與 eviction" data-link-desc="整理過期策略、容量控制與熱點資料">2.3 TTL 與 eviction&lt;/a>；如果服務已經把 cache 當主要 serving layer，先回到 &lt;a href="https://tarrragon.github.io/blog/backend/02-cache-redis/cache-copy-freshness-boundary/" data-link-title="2.7 Cache Copy Boundary 與 Freshness" data-link-desc="說明快取何時只是可重建副本，何時會影響交易、權限或配額正確性。">2.7 Cache Copy Boundary&lt;/a>。&lt;/p>
&lt;h2 id="教學順序同步">教學順序同步&lt;/h2>
&lt;p>快取服務頁的教學順序是先建立 Redis / Valkey baseline，再比較 Memcached、DragonflyDB 與 managed cache。這個順序對齊 checkout E2：讀者先理解可重建副本、新鮮度與回源保護，再比較同類服務如何改變相容性、memory model、failover 與 managed operation。&lt;/p>
&lt;h2 id="t1-服務頁大綱">T1 服務頁大綱&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>服務&lt;/th>
 &lt;th>類型&lt;/th>
 &lt;th>頁面要回答的核心問題&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/02-cache-redis/vendors/redis/" data-link-title="Redis" data-link-desc="OSS in-memory data structure store、cache 主流">Redis&lt;/a>&lt;/td>
 &lt;td>Data structure cache&lt;/td>
 &lt;td>data types、persistence、cluster 與授權變動如何影響選型&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/02-cache-redis/vendors/valkey/" data-link-title="Valkey" data-link-desc="Redis fork、Linux Foundation 託管、BSD 授權">Valkey&lt;/a>&lt;/td>
 &lt;td>Redis-compatible&lt;/td>
 &lt;td>Redis 相容性、開源治理與 managed ecosystem 如何取捨&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/02-cache-redis/vendors/memcached/" data-link-title="Memcached" data-link-desc="純記憶體 key-value cache、無持久化">Memcached&lt;/a>&lt;/td>
 &lt;td>Simple KV cache&lt;/td>
 &lt;td>純快取、低語意與水平擴張如何降低操作成本&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/02-cache-redis/vendors/dragonflydb/" data-link-title="DragonflyDB" data-link-desc="高效能 Redis / Memcached 相容替代、多核架構">DragonflyDB&lt;/a>&lt;/td>
 &lt;td>Redis-compatible&lt;/td>
 &lt;td>多核心架構、相容性與高吞吐 cache workload 如何評估&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/02-cache-redis/vendors/aws-elasticache/" data-link-title="AWS ElastiCache" data-link-desc="AWS managed Redis / Valkey / Memcached">AWS ElastiCache&lt;/a>&lt;/td>
 &lt;td>Managed cache&lt;/td>
 &lt;td>managed Redis / Valkey / Memcached 如何轉移維運責任&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="內容覆蓋進度">內容覆蓋進度&lt;/h2>
&lt;p>每個 vendor 服務頁下會擴充兩類文章：deep article（vendor 自身的配置、故障、容量、走 &lt;a href="https://tarrragon.github.io/blog/posts/vendor-%E6%B7%B1%E5%BA%A6%E6%8A%80%E8%A1%93%E6%96%87%E7%AB%A0%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84%E5%90%8C-vendor-%E7%B3%BB%E5%88%97%E7%9A%84%E9%96%8B%E5%A0%B4%E8%BC%AA%E6%9B%BF%E9%A9%97%E8%AD%89/" data-link-title="Vendor 深度技術文章方法論的演化紀錄：同 vendor 系列的開場輪替驗證" data-link-desc="vendor overview 飽和後要寫單一功能深度文章、需要選題與結構依據時回來。這套方法論的驗證來源與 cadence variant 在高風險場景（同 vendor sub-tool 系列）的實證。">6-section 模板&lt;/a>）跟 migration playbook（跨 vendor 遷移流程、走 &lt;a href="https://tarrragon.github.io/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">6-type 結構&lt;/a>）。「→ X」代表遷移到 X 的 playbook、其他形式代表 same-vendor 的 topology / version / config 變動。&lt;/p></description><content:encoded><![CDATA[<p>快取 Vendor 清單的核心責任是把 cache 服務名稱放回副本語意、資料新鮮度、回源保護與操作成本的判斷。每個服務頁先回答它承擔哪種暫存責任，再討論資料型別、失效策略、容量模型、HA / managed 邊界與案例回寫。在挑單一服務之前先有一個更上層的判斷：這塊快取能力該自管 Redis、用 managed cache（ElastiCache、MemoryDB）、還是用 serverless cache（Upstash）或含 cache 的 BaaS bundle — 逐能力的買 vs 建判讀見 <a href="/blog/backend/00-service-selection/capability-buy-vs-build/" data-link-title="0.22 能力級買 vs 建：feature-as-a-service 與 BaaS bundle 選型" data-link-desc="在交付形態決定整個系統要不要自建之後、逐能力判斷該外包還是自建：辨識 managed 基礎設施、feature SaaS 與 BaaS bundle 三種外包深度、no-code 到 dev-tool 的服務光譜、買 vs 建判準與權重浮動、整合接縫與遷出代價">0.22 能力級買 vs 建</a>。</p>
<h2 id="讀法">讀法</h2>
<p>快取服務要從資料生命週期進入。讀者如果要保護資料庫讀取壓力，先回到 <a href="/blog/backend/02-cache-redis/cache-aside/" data-link-title="2.2 cache aside 與失效策略" data-link-desc="整理 read-through 思路、cache miss 與 invalidation">2.2 Cache Aside</a>；如果要判斷 TTL 與淘汰，先回到 <a href="/blog/backend/02-cache-redis/ttl-eviction/" data-link-title="2.3 TTL 與 eviction" data-link-desc="整理過期策略、容量控制與熱點資料">2.3 TTL 與 eviction</a>；如果服務已經把 cache 當主要 serving layer，先回到 <a href="/blog/backend/02-cache-redis/cache-copy-freshness-boundary/" data-link-title="2.7 Cache Copy Boundary 與 Freshness" data-link-desc="說明快取何時只是可重建副本，何時會影響交易、權限或配額正確性。">2.7 Cache Copy Boundary</a>。</p>
<h2 id="教學順序同步">教學順序同步</h2>
<p>快取服務頁的教學順序是先建立 Redis / Valkey baseline，再比較 Memcached、DragonflyDB 與 managed cache。這個順序對齊 checkout E2：讀者先理解可重建副本、新鮮度與回源保護，再比較同類服務如何改變相容性、memory model、failover 與 managed operation。</p>
<h2 id="t1-服務頁大綱">T1 服務頁大綱</h2>
<table>
  <thead>
      <tr>
          <th>服務</th>
          <th>類型</th>
          <th>頁面要回答的核心問題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/vendors/redis/" data-link-title="Redis" data-link-desc="OSS in-memory data structure store、cache 主流">Redis</a></td>
          <td>Data structure cache</td>
          <td>data types、persistence、cluster 與授權變動如何影響選型</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/vendors/valkey/" data-link-title="Valkey" data-link-desc="Redis fork、Linux Foundation 託管、BSD 授權">Valkey</a></td>
          <td>Redis-compatible</td>
          <td>Redis 相容性、開源治理與 managed ecosystem 如何取捨</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/vendors/memcached/" data-link-title="Memcached" data-link-desc="純記憶體 key-value cache、無持久化">Memcached</a></td>
          <td>Simple KV cache</td>
          <td>純快取、低語意與水平擴張如何降低操作成本</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/vendors/dragonflydb/" data-link-title="DragonflyDB" data-link-desc="高效能 Redis / Memcached 相容替代、多核架構">DragonflyDB</a></td>
          <td>Redis-compatible</td>
          <td>多核心架構、相容性與高吞吐 cache workload 如何評估</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/02-cache-redis/vendors/aws-elasticache/" data-link-title="AWS ElastiCache" data-link-desc="AWS managed Redis / Valkey / Memcached">AWS ElastiCache</a></td>
          <td>Managed cache</td>
          <td>managed Redis / Valkey / Memcached 如何轉移維運責任</td>
      </tr>
  </tbody>
</table>
<h2 id="內容覆蓋進度">內容覆蓋進度</h2>
<p>每個 vendor 服務頁下會擴充兩類文章：deep article（vendor 自身的配置、故障、容量、走 <a href="/blog/posts/vendor-%E6%B7%B1%E5%BA%A6%E6%8A%80%E8%A1%93%E6%96%87%E7%AB%A0%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84%E5%90%8C-vendor-%E7%B3%BB%E5%88%97%E7%9A%84%E9%96%8B%E5%A0%B4%E8%BC%AA%E6%9B%BF%E9%A9%97%E8%AD%89/" data-link-title="Vendor 深度技術文章方法論的演化紀錄：同 vendor 系列的開場輪替驗證" data-link-desc="vendor overview 飽和後要寫單一功能深度文章、需要選題與結構依據時回來。這套方法論的驗證來源與 cadence variant 在高風險場景（同 vendor sub-tool 系列）的實證。">6-section 模板</a>）跟 migration playbook（跨 vendor 遷移流程、走 <a href="/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">6-type 結構</a>）。「→ X」代表遷移到 X 的 playbook、其他形式代表 same-vendor 的 topology / version / config 變動。</p>
<table>
  <thead>
      <tr>
          <th>Vendor</th>
          <th>Deep article</th>
          <th>Migration playbook</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="redis/">Redis</a></td>
          <td><a href="redis/memory-eviction-tuning/">memory-eviction-tuning</a> / <a href="redis/persistence-fork-latency/">persistence-fork-latency</a> / <a href="redis/sentinel-ha-failover/">sentinel-ha-failover</a> / <a href="redis/connection-pipeline-latency/">connection-pipeline-latency</a> / <a href="redis/cluster-resharding/">cluster-resharding</a></td>
          <td><a href="redis/migrate-to-valkey/">→ Valkey</a> / <a href="redis/migrate-to-dragonflydb/">→ DragonflyDB</a> / <a href="redis/migrate-to-memcached/">→ Memcached</a> / <a href="redis/migrate-to-elasticache/">→ ElastiCache</a></td>
      </tr>
      <tr>
          <td><a href="valkey/">Valkey</a></td>
          <td><a href="valkey/redis-compatibility-and-io-threads/">redis-compatibility-and-io-threads</a></td>
          <td>（沿用 Redis → ElastiCache：自管 Valkey 同路徑）</td>
      </tr>
      <tr>
          <td><a href="memcached/">Memcached</a></td>
          <td><a href="memcached/slab-allocator-memory-economics/">slab-allocator-memory-economics</a></td>
          <td><a href="memcached/migrate-to-redis/">→ Redis</a></td>
      </tr>
      <tr>
          <td><a href="dragonflydb/">DragonflyDB</a></td>
          <td><a href="dragonflydb/shared-nothing-multicore-architecture/">shared-nothing-multicore-architecture</a></td>
          <td><a href="dragonflydb/migrate-to-redis/">→ Redis/Valkey</a></td>
      </tr>
      <tr>
          <td><a href="aws-elasticache/">AWS ElastiCache</a></td>
          <td><a href="aws-elasticache/managed-responsibility-boundary/">managed-responsibility-boundary</a></td>
          <td><a href="aws-elasticache/migrate-to-self-managed/">→ 自管 Redis/Valkey</a></td>
      </tr>
      <tr>
          <td><a href="keydb/">KeyDB</a></td>
          <td><a href="keydb/active-active-replication/">active-active-replication</a></td>
          <td><a href="keydb/migrate-to-redis/">→ Redis/Valkey</a></td>
      </tr>
      <tr>
          <td><a href="momento/">Momento</a></td>
          <td>overview-only（見下方註）</td>
          <td>—</td>
      </tr>
      <tr>
          <td><a href="caffeine/">Caffeine</a></td>
          <td><a href="caffeine/two-tier-cache-invalidation/">two-tier-cache-invalidation</a></td>
          <td>—</td>
      </tr>
  </tbody>
</table>
<p>備註：<a href="redis/cluster-resharding/">cluster-resharding</a> 是同 cluster 的 topology 重劃（5 type migration 漏類驗證、形式上歸在 deep article 欄、不是跨 vendor 遷移）。</p>
<p>Momento overview-only 的理由：Momento 是 serverless cache、實作面（無 server 參數、無容量規劃、無 cluster topology）相對薄；本 blog case 庫無 Momento production case、且 SaaS 無法本機驗證。依 <a href="/blog/posts/vendor-%E6%B7%B1%E5%BA%A6%E6%8A%80%E8%A1%93%E6%96%87%E7%AB%A0%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84%E5%90%8C-vendor-%E7%B3%BB%E5%88%97%E7%9A%84%E9%96%8B%E5%A0%B4%E8%BC%AA%E6%9B%BF%E9%A9%97%E8%AD%89/" data-link-title="Vendor 深度技術文章方法論的演化紀錄：同 vendor 系列的開場輪替驗證" data-link-desc="vendor overview 飽和後要寫單一功能深度文章、需要選題與結構依據時回來。這套方法論的驗證來源與 cadence variant 在高風險場景（同 vendor sub-tool 系列）的實證。">deep article 方法論</a> 反向判準（無 production 經驗 / case 支撐的純 spec 復述不該寫 deep article），Momento 維持 overview-only、待有 case 或 serverless cost 實證再評估。</p>
<p>進度（2026-06-22）：8 個 vendor 的 deep-article 層收尾完成。Migration playbook 覆蓋更新：ElastiCache → 自管 Redis/Valkey、DragonflyDB → Redis/Valkey、KeyDB → Redis/Valkey 三條回退路徑已補齊。目前只剩 Momento（overview-only、無 migration 需求）跟 Caffeine（local cache、無跨 vendor migration 概念）的 migration 欄為空白、屬設計決策。剩餘獨立 track：各 T1 vendor 進階主題的更多 deep article（Redis distributed lock / modules、Memcached CAS、ElastiCache Global Datastore DR）、後續候選的 Garnet / Hazelcast / Aerospike / Varnish edge cache。</p>
<h2 id="服務頁撰寫欄位">服務頁撰寫欄位</h2>
<table>
  <thead>
      <tr>
          <th>欄位</th>
          <th>快取服務頁要保留的問題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>服務責任</td>
          <td>它承擔 cache copy、data structure、presence、counter 還是 managed operation</td>
      </tr>
      <tr>
          <td>適用壓力</td>
          <td>hot key、read QPS、origin cost、latency、multi-region、memory cost 哪個壓力最明顯</td>
      </tr>
      <tr>
          <td>替代邊界</td>
          <td>同類 Redis 相容服務、Memcached、managed cache、local cache 的機會成本</td>
      </tr>
      <tr>
          <td>操作成本</td>
          <td>memory sizing、eviction、backup、failover、cluster upgrade、client compatibility</td>
      </tr>
      <tr>
          <td>Evidence</td>
          <td>hit rate、miss rate、origin QPS、stale read、eviction、hot key、replication lag</td>
      </tr>
      <tr>
          <td>案例回寫</td>
          <td>Meta、Shopify、Netflix、Cloudflare、Tinder、Tubi、Snap 案例如何提供判準</td>
      </tr>
  </tbody>
</table>
<p>服務責任段要先分辨副本與正式狀態。Redis、Valkey、DragonflyDB 與 ElastiCache 都可能承擔 cache serving layer，但資料是否可重建、stale window 多長、回源壓力是否受控，才是選型判斷的起點。</p>
<p>適用壓力段要保留 workload 語言。商品詳情、session、presence、rate limit、leaderboard、ML feature store 與 edge cache 的資料形狀不同，服務頁要用各自的 freshness、memory、QPS 與回退條件寫。</p>
<h2 id="服務頁標準章節">服務頁標準章節</h2>
<table>
  <thead>
      <tr>
          <th>章節</th>
          <th>快取服務頁要補的內容</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>服務定位</td>
          <td>它是 data structure cache、simple KV、managed cache、local cache 還是 HTTP cache</td>
      </tr>
      <tr>
          <td>本章目標</td>
          <td>讀者能判斷資料是否可重建、stale window、origin protection 與 memory cost</td>
      </tr>
      <tr>
          <td>最短判讀路徑</td>
          <td>用「miss 打回 origin 是否可承受」快速判斷是否能引入或擴大快取</td>
      </tr>
      <tr>
          <td>日常操作與決策形狀</td>
          <td>key design、TTL、eviction、warmup、failover、client timeout</td>
      </tr>
      <tr>
          <td>核心取捨表</td>
          <td>Redis 相容服務、Memcached、managed cache、local cache 的機會成本</td>
      </tr>
      <tr>
          <td>進階主題</td>
          <td>cluster、persistence、multi-region、serverless cache、module / data type</td>
      </tr>
      <tr>
          <td>排錯與失敗快速判讀</td>
          <td>hit rate、miss rate、origin QPS、hot key、eviction、replication lag</td>
      </tr>
      <tr>
          <td>何時改走其他服務</td>
          <td>durable workflow 轉 queue、正式狀態轉 database、全文查詢轉 search</td>
      </tr>
      <tr>
          <td>不在本頁內的主題</td>
          <td>Redis command 百科、語言 client API 細節、完整調參手冊</td>
      </tr>
      <tr>
          <td>案例回寫與下一步路由</td>
          <td>回到 2.C cases、9.C cache capacity cases、4.20 evidence package</td>
      </tr>
  </tbody>
</table>
<h2 id="跨-vendor-議題對照">跨 vendor 議題對照</h2>
<p>橫向議題在不同 vendor 用不同 mechanism 達成。本表列同一議題在 5 個 vendor 的對應位置、確保大綱不缺漏、讀者跨 vendor 查找時有索引。</p>
<table>
  <thead>
      <tr>
          <th>議題</th>
          <th>Redis</th>
          <th>Valkey</th>
          <th>Memcached</th>
          <th>DragonflyDB</th>
          <th>AWS ElastiCache</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Redis API 相容度</td>
          <td>原生（最高）</td>
          <td>100%（fork 7.2.4）</td>
          <td>不相容（純 KV）</td>
          <td>高（少數 commands 不支援）</td>
          <td>Engine 決定（Redis/Valkey 100%、Memcached 不適用）</td>
      </tr>
      <tr>
          <td>Data types</td>
          <td>6 大 + Stream / Geo</td>
          <td>跟 Redis 一致</td>
          <td>純 string KV</td>
          <td>跟 Redis 一致</td>
          <td>跟 engine 一致</td>
      </tr>
      <tr>
          <td>多核 / 多執行緒</td>
          <td>I/O threads（main 仍單線）</td>
          <td>Valkey 8 強化 async I/O threading（超出 Redis）</td>
          <td>原生多執行緒</td>
          <td>完全 shared-nothing 多核</td>
          <td>跟 engine 一致</td>
      </tr>
      <tr>
          <td>Cluster mode</td>
          <td>Cluster + Sentinel</td>
          <td>跟 Redis 一致</td>
          <td>Client-side ketama hashing</td>
          <td>Single instance scale-up（無 Cluster）</td>
          <td>Cluster mode enabled/disabled</td>
      </tr>
      <tr>
          <td>持久化策略</td>
          <td>AOF + RDB</td>
          <td>跟 Redis 一致</td>
          <td>無持久化</td>
          <td>Fork-less snapshot</td>
          <td>Automatic + manual snapshot</td>
      </tr>
      <tr>
          <td>跨 AZ / 多 region</td>
          <td>Sentinel + replication / Cluster geo</td>
          <td>跟 Redis 一致</td>
          <td>需 Mcrouter / EVCache 等代理</td>
          <td>Replica 模式</td>
          <td>Multi-AZ + Global Datastore</td>
      </tr>
      <tr>
          <td>授權模式</td>
          <td>RSALv2 / SSPL（非 OSI）</td>
          <td>BSD 3-clause（OSI）</td>
          <td>BSD（OSI）</td>
          <td>BSL（4 年後轉 Apache 2.0）</td>
          <td>AWS managed pricing</td>
      </tr>
      <tr>
          <td>Managed level</td>
          <td>自管</td>
          <td>自管 / managed Valkey 可選</td>
          <td>自管</td>
          <td>自管（無 Dragonfly managed）</td>
          <td>Fully managed</td>
      </tr>
      <tr>
          <td>主討論案例</td>
          <td>2.C1-C8（跨 Meta / Netflix / Shopify）</td>
          <td>待補（fork 較新）</td>
          <td>2.C4 Mcrouter / 2.C5 EVCache</td>
          <td>待補（採用較新）</td>
          <td>2.C5 EVCache / 2.C8 Shopify</td>
      </tr>
  </tbody>
</table>
<p>對照表的用途有三：</p>
<ul>
<li>寫某 vendor 頁時、檢查橫向議題是否都有對應的進階主題子段</li>
<li>讀者在 vendor 間遷移時、知道對應 mechanism 在另一個 vendor 叫什麼</li>
<li>評估遷移風險：相容度 + 授權 + 生態三維度合併判讀</li>
</ul>
<p>下面 8 段把對照表的每行展開、避免裸表格成為終點。</p>
<h3 id="redis-api-相容度">Redis API 相容度</h3>
<p>API 相容度決定 client / 工具 / module 是否能直接遷移。<strong>Redis</strong> 是 reference 實作；<strong>Valkey</strong> 100% 相容（直接 drop-in、所有 client library 可用）；<strong>DragonflyDB</strong> 相容核心 commands 但部分 module / Lua 行為差異、不支援 Redis Cluster mode；<strong>Memcached</strong> 跟 Redis 完全不相容（protocol 不同、無 data types）；<strong>ElastiCache</strong> 取決於 engine（Redis / Valkey 100%、Memcached 是另一條線）。</p>
<p>選型判讀：既有 Redis 部署遷移 → Valkey 最低風險；要 scale up single instance → DragonflyDB 可評估但確認 module 跟 Cluster mode 影響；純 KV 從 Redis 改 Memcached → 等同重寫（不是相容問題、是 capability 差異）。</p>
<h3 id="data-types">Data types</h3>
<p>Data types 影響可用場景。<strong>Redis / Valkey</strong> 提供 string / hash / list / set / sorted set / stream / hyperloglog / geo — leaderboard / session / counter / distributed lock 等都有原生支援；<strong>Memcached</strong> 純 string KV — 任何複雜結構要在 application 層自己處理（serialize JSON 等）；<strong>DragonflyDB</strong> 跟 Redis 一致；<strong>ElastiCache</strong> 取決於 engine。</p>
<p>選型判讀：需要 sorted set / streams / hash → Redis 系列；純 cache GET/SET → Memcached 更輕；想用 Redis data types 但要極高 throughput → DragonflyDB。</p>
<h3 id="多核--多執行緒">多核 / 多執行緒</h3>
<p>多核利用度差異大。<strong>Redis</strong> 主執行緒 + I/O threads（Redis 6+）— main thread 仍處理所有 command；<strong>Valkey</strong> 8.x 強化 async I/O threading、把更多 I/O 路徑非同步化、多核吞吐超出 Redis（這是 Valkey fork 後第一個實質技術分歧、見 <a href="/blog/backend/02-cache-redis/vendors/valkey/redis-compatibility-and-io-threads/" data-link-title="Valkey 相容性驗證與 io-threads 調校：drop-in 切換與多執行緒的實機判讀" data-link-desc="Valkey 跟 Redis 100% 相容這句話要怎麼驗證、切換才敢上線。本文用 INFO server 的雙版本回報拆解相容性的真實邊界、展開 Valkey 8 的 io-threads 多執行緒調校、5 個把 drop-in 切換或執行緒配置寫成事故的 production 踩坑，以及相容性撞牆該怎麼判斷的邊界">Valkey deep article</a>）；<strong>Memcached</strong> 原生 multi-threaded（<code>-t</code> 指定 thread 數）— 適合多核機器；<strong>DragonflyDB</strong> 完全 shared-nothing 多核 — 官方宣稱比 Redis 高 25× throughput（依 workload、以官方 benchmark 為準）；<strong>ElastiCache</strong> 取決於 engine、不能改變。</p>
<p>選型判讀：單 instance 想充分利用 16+ core → DragonflyDB / Memcached；4-8 core 中等場景 → Redis 加 I/O threads 已夠；需要 Redis API + 高 throughput → DragonflyDB 是 sweet spot。</p>
<h3 id="cluster-mode">Cluster mode</h3>
<p>擴展拓樸不同。<strong>Redis</strong> Cluster mode（16384 hash slot、可加減 shard）跟 Sentinel mode（HA 無 sharding）；<strong>Valkey</strong> 跟 Redis 一致；<strong>Memcached</strong> 沒有 server-side cluster、靠 client-side consistent hashing（ketama）；<strong>DragonflyDB</strong> 完全沒有 Cluster mode — 哲學是「single instance 撐到很大規模」；<strong>ElastiCache</strong> 提供 Cluster mode enabled / disabled 兩選項、disabled 上限 ~340GB。</p>
<p>選型判讀：超 single instance 容量 → Redis Cluster / ElastiCache Cluster enabled；HA 但容量在單 master → Redis Sentinel / ElastiCache disabled；scale up 機制 → DragonflyDB；極簡 client-side sharding → Memcached。</p>
<h3 id="持久化策略">持久化策略</h3>
<p>cache 是否需要持久化、view 不一。<strong>Redis</strong> AOF（append-only）+ RDB（snapshot）+ 混合模式；<strong>Valkey</strong> 跟 Redis 一致；<strong>Memcached</strong> 無持久化 — 重啟即 cold cache（嚴格 cache 哲學）；<strong>DragonflyDB</strong> fork-less snapshot（大記憶體場景比 Redis fork 高效）；<strong>ElastiCache</strong> 自動 snapshot + manual snapshot、跨 region 複製。</p>
<p>選型判讀：cache warmup 後不想全失 → Redis AOF / Valkey；純 cache 接受 cold start → Memcached；大記憶體 + snapshot 頻繁 → DragonflyDB fork-less；managed snapshot 不想處理 → ElastiCache。</p>
<h3 id="跨-az--多-region">跨 AZ / 多 region</h3>
<p>HA 拓樸三類。<strong>Redis</strong> Sentinel + replication（單 region 多 AZ）/ Cluster geo replication（規劃中）；<strong>Valkey</strong> 跟 Redis 一致；<strong>Memcached</strong> 沒有原生 — 靠 Mcrouter / EVCache 等代理做跨 AZ；<strong>DragonflyDB</strong> Replica 模式（primary-replica）跨 AZ 可行、跨 region 需自建；<strong>ElastiCache</strong> Multi-AZ replica（內建）+ Global Datastore（跨 region active-passive）。</p>
<p>選型判讀：自管跨 AZ → Redis Sentinel / Valkey；自管跨 region → Mcrouter 或自建；不想處理跨區 → ElastiCache Multi-AZ + Global Datastore。</p>
<h3 id="授權模式">授權模式</h3>
<p>授權直接影響商業使用權利。<strong>Redis</strong> 2024 起 RSALv2 / SSPL（非 OSI 認可）— SaaS 提供 Redis-as-service 受限；<strong>Valkey</strong> BSD 3-clause（OSI 認可）— 商業使用無限制；<strong>Memcached</strong> BSD（OSI）— 開源無限制；<strong>DragonflyDB</strong> BSL（Business Source License）— 4 年後轉 Apache 2.0、目前商業 managed service 提供受限；<strong>ElastiCache</strong> AWS managed pricing — 跟 license 無關（你付的是 AWS 服務費）。</p>
<p>選型判讀：開源合規敏感（公部門 / 企業政策）→ Valkey / Memcached；新部署不在乎 license → Redis / DragonflyDB；不想處理 license → ElastiCache（AWS 處理）。</p>
<h3 id="managed-level">Managed level</h3>
<p>運維責任轉移程度。<strong>Redis / Valkey</strong> 自管或選 managed（ElastiCache / Memorystore / Azure Cache）；<strong>Memcached</strong> 自管或 ElastiCache；<strong>DragonflyDB</strong> 目前只能自管（無 fully managed offering）；<strong>ElastiCache</strong> 完全 managed（auto failover / snapshot / patching）— 付 managed premium。</p>
<p>選型判讀：team 沒運維 Redis 經驗 → managed（ElastiCache / Memorystore）；要極致控制 → 自管；DragonflyDB 必自管（無 managed）。</p>
<h2 id="撰寫批次">撰寫批次</h2>
<table>
  <thead>
      <tr>
          <th>批次</th>
          <th>服務頁</th>
          <th>撰寫目的</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>C1</td>
          <td>Redis / Valkey</td>
          <td>建立 Redis baseline、開源治理與相容性判準</td>
      </tr>
      <tr>
          <td>C2</td>
          <td>Memcached</td>
          <td>建立 simple KV cache、低語意副本與水平擴張邊界</td>
      </tr>
      <tr>
          <td>C3</td>
          <td>DragonflyDB / AWS ElastiCache</td>
          <td>建立高吞吐 Redis-compatible 與 managed cache 的操作取捨</td>
      </tr>
      <tr>
          <td>C4</td>
          <td>KeyDB / Momento / Caffeine</td>
          <td>補 multi-threaded fork、serverless cache、local cache 對照（overview 完成 2026-06-16）</td>
      </tr>
  </tbody>
</table>
<h2 id="後續候選">後續候選</h2>
<p>C4 已建立 <a href="keydb/">KeyDB</a> / <a href="momento/">Momento</a> / <a href="caffeine/">Caffeine</a> overview。剩餘候選：</p>
<table>
  <thead>
      <tr>
          <th>類型</th>
          <th>候選服務</th>
          <th>寫作重點</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Redis fork / compat</td>
          <td>Garnet（Microsoft）</td>
          <td>相容性、multi-threading、client behavior</td>
      </tr>
      <tr>
          <td>Managed cache</td>
          <td>Azure Cache for Redis、GCP Memorystore</td>
          <td>managed SLA、vendor boundary</td>
      </tr>
      <tr>
          <td>Distributed cache</td>
          <td>Hazelcast、Aerospike</td>
          <td>cluster memory、near-cache、durability boundary</td>
      </tr>
      <tr>
          <td>Local cache</td>
          <td>Guava Cache、Ehcache（off-heap）</td>
          <td>process-local cache、invalidation、memory pressure</td>
      </tr>
      <tr>
          <td>HTTP / edge cache</td>
          <td>Varnish、Cloudflare Cache、Fastly、CloudFront</td>
          <td>edge TTL、origin protection、purge workflow</td>
      </tr>
  </tbody>
</table>
<p>主流覆蓋檢查的重點是把 cache 分成 process-local、service-local、distributed 與 edge 四層。Redis 系列 / KeyDB / DragonflyDB 解 service-local / distributed data structure cache；<a href="caffeine/">Caffeine</a> 解 process-local、<a href="momento/">Momento</a> 解 serverless cache；Varnish、Cloudflare、Fastly、CloudFront 解 HTTP / edge cache；Hazelcast、Aerospike 解更重的 distributed data / cache 邊界。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/02-cache-redis/cache-aside/" data-link-title="2.2 cache aside 與失效策略" data-link-desc="整理 read-through 思路、cache miss 與 invalidation">2.2 Cache Aside</a></li>
<li>上游：<a href="/blog/backend/02-cache-redis/cache-copy-freshness-boundary/" data-link-title="2.7 Cache Copy Boundary 與 Freshness" data-link-desc="說明快取何時只是可重建副本，何時會影響交易、權限或配額正確性。">2.7 Cache Copy Boundary</a></li>
<li>案例：<a href="/blog/backend/02-cache-redis/cases/" data-link-title="模組二案例正文" data-link-desc="快取策略與快取平台演進案例入口。">2.C 快取案例正文</a></li>
<li>服務路徑：<a href="/blog/backend/02-cache-redis/cache-migration-stampede-rollback/" data-link-title="2.9 Cache Migration 與 Stampede Rollback（實作示範）" data-link-desc="以商品詳情與價格快取示範 cache migration 如何交付 evidence package、release gate 與 incident decision log。">2.9 Cache Migration 與 Stampede Rollback</a></li>
</ul>
]]></content:encoded></item><item><title>訊息佇列 Vendor 清單</title><link>https://tarrragon.github.io/blog/backend/03-message-queue/vendors/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/03-message-queue/vendors/</guid><description>&lt;p>訊息佇列 Vendor 清單的核心責任是把 broker 名稱放回 delivery semantics、processing semantics、replay boundary 與操作治理的判斷。每個服務頁先回答它提供哪種投遞與消費模型，再討論 ordering、retention、consumer group、DLQ、managed 邊界與案例回寫。選 broker 之前、佇列這塊能力先過一次買 vs 建：自管 broker（RabbitMQ、Kafka）自己扛 ordering、retention、DLQ 的運維、managed（SQS、SNS、MSK、Confluent Cloud）把這層交出去、雲端原生事件匯流更省 — 逐能力的判讀見 &lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/capability-buy-vs-build/" data-link-title="0.22 能力級買 vs 建：feature-as-a-service 與 BaaS bundle 選型" data-link-desc="在交付形態決定整個系統要不要自建之後、逐能力判斷該外包還是自建：辨識 managed 基礎設施、feature SaaS 與 BaaS bundle 三種外包深度、no-code 到 dev-tool 的服務光譜、買 vs 建判準與權重浮動、整合接縫與遷出代價">0.22 能力級買 vs 建&lt;/a>。&lt;/p>
&lt;h2 id="讀法">讀法&lt;/h2>
&lt;p>佇列服務要從處理語意進入。讀者如果要處理一般工作佇列，先回到 &lt;a href="https://tarrragon.github.io/blog/backend/03-message-queue/durable-queue/" data-link-title="3.2 durable queue 與重試策略" data-link-desc="整理持久化佇列、DLQ 與重試流程">3.2 durable queue&lt;/a>；如果要處理事件流與 replay，先回到 &lt;a href="https://tarrragon.github.io/blog/backend/03-message-queue/consumer-design/" data-link-title="3.4 consumer 設計與去重" data-link-desc="整理 consumer、checkpoint 與 replay safety">3.4 consumer design&lt;/a>；如果問題是資料庫交易與事件發布一致性，先回到 &lt;a href="https://tarrragon.github.io/blog/backend/03-message-queue/outbox-pattern/" data-link-title="3.3 outbox pattern 與發佈一致性" data-link-desc="把 transaction 與 event publish 分離">3.3 outbox pattern&lt;/a>。&lt;/p>
&lt;h2 id="教學順序同步">教學順序同步&lt;/h2>
&lt;p>佇列服務頁的教學順序是先建立 work queue baseline，再進入 event log、managed delivery、lightweight messaging 與 embedded stream。這個順序對齊 checkout E3：讀者先理解 delivery、processing、recovery 三層語意，再比較 broker、managed queue、pub/sub 與 stream 如何影響 retry、DLQ、ordering 與 replay。&lt;/p>
&lt;h2 id="t1-服務頁大綱">T1 服務頁大綱&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>服務&lt;/th>
 &lt;th>類型&lt;/th>
 &lt;th>頁面要回答的核心問題&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/03-message-queue/vendors/rabbitmq/" data-link-title="RabbitMQ" data-link-desc="Classic message broker、AMQP routing 為主">RabbitMQ&lt;/a>&lt;/td>
 &lt;td>Classic broker&lt;/td>
 &lt;td>exchange、routing、ack/nack 與 DLQ 如何支援工作分派&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/03-message-queue/vendors/kafka/" data-link-title="Apache Kafka" data-link-desc="Distributed event streaming platform、log-based 模型">Apache Kafka&lt;/a>&lt;/td>
 &lt;td>Event streaming&lt;/td>
 &lt;td>partition、offset、retention 與 replay 如何支援事件流&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/03-message-queue/vendors/nats/" data-link-title="NATS" data-link-desc="Lightweight messaging、JetStream 加持久化與 streams">NATS&lt;/a>&lt;/td>
 &lt;td>Messaging / stream&lt;/td>
 &lt;td>subject、JetStream、low-latency 與 durability 如何取捨&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/03-message-queue/vendors/redis-streams/" data-link-title="Redis Streams" data-link-desc="Redis 生態內的 streams、append-only log &amp;#43; consumer group">Redis Streams&lt;/a>&lt;/td>
 &lt;td>Embedded stream&lt;/td>
 &lt;td>Redis 生態中的 stream、consumer group 與 pending entry 邊界&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/03-message-queue/vendors/aws-sqs/" data-link-title="AWS SQS" data-link-desc="AWS managed queue、簡單可靠、無 ordering（standard）">AWS SQS&lt;/a>&lt;/td>
 &lt;td>Managed queue&lt;/td>
 &lt;td>standard / FIFO、visibility timeout 與 DLQ 如何支援 managed delivery&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/03-message-queue/vendors/google-pubsub/" data-link-title="Google Cloud Pub/Sub" data-link-desc="GCP managed pub/sub、global routing、push/pull">Google Cloud Pub/Sub&lt;/a>&lt;/td>
 &lt;td>Managed pub/sub&lt;/td>
 &lt;td>topic / subscription、push / pull 與 global delivery 如何取捨&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="內容覆蓋進度">內容覆蓋進度&lt;/h2>
&lt;p>每個 vendor 服務頁下會擴充兩類文章：deep article（vendor 自身的配置、故障、容量、走 &lt;a href="https://tarrragon.github.io/blog/posts/vendor-%E6%B7%B1%E5%BA%A6%E6%8A%80%E8%A1%93%E6%96%87%E7%AB%A0%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84%E5%90%8C-vendor-%E7%B3%BB%E5%88%97%E7%9A%84%E9%96%8B%E5%A0%B4%E8%BC%AA%E6%9B%BF%E9%A9%97%E8%AD%89/" data-link-title="Vendor 深度技術文章方法論的演化紀錄：同 vendor 系列的開場輪替驗證" data-link-desc="vendor overview 飽和後要寫單一功能深度文章、需要選題與結構依據時回來。這套方法論的驗證來源與 cadence variant 在高風險場景（同 vendor sub-tool 系列）的實證。">6-section 模板&lt;/a>）跟 migration playbook（跨 vendor 遷移流程、走 &lt;a href="https://tarrragon.github.io/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">6-type 結構&lt;/a>）。「→ X」代表遷移到 X 的 playbook、「↔ X」代表雙向遷移、其他形式代表 same-vendor 的 topology / version / config 變動。&lt;/p></description><content:encoded><![CDATA[<p>訊息佇列 Vendor 清單的核心責任是把 broker 名稱放回 delivery semantics、processing semantics、replay boundary 與操作治理的判斷。每個服務頁先回答它提供哪種投遞與消費模型，再討論 ordering、retention、consumer group、DLQ、managed 邊界與案例回寫。選 broker 之前、佇列這塊能力先過一次買 vs 建：自管 broker（RabbitMQ、Kafka）自己扛 ordering、retention、DLQ 的運維、managed（SQS、SNS、MSK、Confluent Cloud）把這層交出去、雲端原生事件匯流更省 — 逐能力的判讀見 <a href="/blog/backend/00-service-selection/capability-buy-vs-build/" data-link-title="0.22 能力級買 vs 建：feature-as-a-service 與 BaaS bundle 選型" data-link-desc="在交付形態決定整個系統要不要自建之後、逐能力判斷該外包還是自建：辨識 managed 基礎設施、feature SaaS 與 BaaS bundle 三種外包深度、no-code 到 dev-tool 的服務光譜、買 vs 建判準與權重浮動、整合接縫與遷出代價">0.22 能力級買 vs 建</a>。</p>
<h2 id="讀法">讀法</h2>
<p>佇列服務要從處理語意進入。讀者如果要處理一般工作佇列，先回到 <a href="/blog/backend/03-message-queue/durable-queue/" data-link-title="3.2 durable queue 與重試策略" data-link-desc="整理持久化佇列、DLQ 與重試流程">3.2 durable queue</a>；如果要處理事件流與 replay，先回到 <a href="/blog/backend/03-message-queue/consumer-design/" data-link-title="3.4 consumer 設計與去重" data-link-desc="整理 consumer、checkpoint 與 replay safety">3.4 consumer design</a>；如果問題是資料庫交易與事件發布一致性，先回到 <a href="/blog/backend/03-message-queue/outbox-pattern/" data-link-title="3.3 outbox pattern 與發佈一致性" data-link-desc="把 transaction 與 event publish 分離">3.3 outbox pattern</a>。</p>
<h2 id="教學順序同步">教學順序同步</h2>
<p>佇列服務頁的教學順序是先建立 work queue baseline，再進入 event log、managed delivery、lightweight messaging 與 embedded stream。這個順序對齊 checkout E3：讀者先理解 delivery、processing、recovery 三層語意，再比較 broker、managed queue、pub/sub 與 stream 如何影響 retry、DLQ、ordering 與 replay。</p>
<h2 id="t1-服務頁大綱">T1 服務頁大綱</h2>
<table>
  <thead>
      <tr>
          <th>服務</th>
          <th>類型</th>
          <th>頁面要回答的核心問題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/03-message-queue/vendors/rabbitmq/" data-link-title="RabbitMQ" data-link-desc="Classic message broker、AMQP routing 為主">RabbitMQ</a></td>
          <td>Classic broker</td>
          <td>exchange、routing、ack/nack 與 DLQ 如何支援工作分派</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/vendors/kafka/" data-link-title="Apache Kafka" data-link-desc="Distributed event streaming platform、log-based 模型">Apache Kafka</a></td>
          <td>Event streaming</td>
          <td>partition、offset、retention 與 replay 如何支援事件流</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/vendors/nats/" data-link-title="NATS" data-link-desc="Lightweight messaging、JetStream 加持久化與 streams">NATS</a></td>
          <td>Messaging / stream</td>
          <td>subject、JetStream、low-latency 與 durability 如何取捨</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/vendors/redis-streams/" data-link-title="Redis Streams" data-link-desc="Redis 生態內的 streams、append-only log &#43; consumer group">Redis Streams</a></td>
          <td>Embedded stream</td>
          <td>Redis 生態中的 stream、consumer group 與 pending entry 邊界</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/vendors/aws-sqs/" data-link-title="AWS SQS" data-link-desc="AWS managed queue、簡單可靠、無 ordering（standard）">AWS SQS</a></td>
          <td>Managed queue</td>
          <td>standard / FIFO、visibility timeout 與 DLQ 如何支援 managed delivery</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/03-message-queue/vendors/google-pubsub/" data-link-title="Google Cloud Pub/Sub" data-link-desc="GCP managed pub/sub、global routing、push/pull">Google Cloud Pub/Sub</a></td>
          <td>Managed pub/sub</td>
          <td>topic / subscription、push / pull 與 global delivery 如何取捨</td>
      </tr>
  </tbody>
</table>
<h2 id="內容覆蓋進度">內容覆蓋進度</h2>
<p>每個 vendor 服務頁下會擴充兩類文章：deep article（vendor 自身的配置、故障、容量、走 <a href="/blog/posts/vendor-%E6%B7%B1%E5%BA%A6%E6%8A%80%E8%A1%93%E6%96%87%E7%AB%A0%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84%E5%90%8C-vendor-%E7%B3%BB%E5%88%97%E7%9A%84%E9%96%8B%E5%A0%B4%E8%BC%AA%E6%9B%BF%E9%A9%97%E8%AD%89/" data-link-title="Vendor 深度技術文章方法論的演化紀錄：同 vendor 系列的開場輪替驗證" data-link-desc="vendor overview 飽和後要寫單一功能深度文章、需要選題與結構依據時回來。這套方法論的驗證來源與 cadence variant 在高風險場景（同 vendor sub-tool 系列）的實證。">6-section 模板</a>）跟 migration playbook（跨 vendor 遷移流程、走 <a href="/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">6-type 結構</a>）。「→ X」代表遷移到 X 的 playbook、「↔ X」代表雙向遷移、其他形式代表 same-vendor 的 topology / version / config 變動。</p>
<table>
  <thead>
      <tr>
          <th>Vendor</th>
          <th>Deep article</th>
          <th>Migration playbook</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="kafka/">Kafka</a></td>
          <td><a href="kafka/consumer-rebalance-lag-diagnosis/">rebalance/lag</a> / <a href="kafka/replication-isr-exactly-once/">replication/ISR</a> / <a href="kafka/retention-tiered-storage/">retention/tiered</a> / <a href="kafka/schema-registry-evolution/">schema registry</a> / <a href="kafka/multi-tenant-quota-acl/">multi-tenant</a></td>
          <td><a href="kafka/migrate-from-to-nats/">↔ NATS</a> / <a href="kafka/migrate-to-msk/">→ MSK</a></td>
      </tr>
      <tr>
          <td><a href="rabbitmq/">RabbitMQ</a></td>
          <td><a href="rabbitmq/queue-types-classic-quorum-stream/">queue 模型選型</a> / <a href="rabbitmq/network-partition-clustering/">network partition</a> / <a href="rabbitmq/dlq-retry-escalation/">DLQ retry escalation</a></td>
          <td><a href="rabbitmq/migrate-to-kafka/">→ Kafka</a> / <a href="rabbitmq/migrate-to-aws-sqs/">→ AWS SQS</a></td>
      </tr>
      <tr>
          <td><a href="nats/">NATS</a></td>
          <td><a href="nats/jetstream-supercluster-design/">JetStream/supercluster</a> / <a href="nats/jetstream-durability-consumer/">JetStream durability/consumer</a></td>
          <td>↔ Kafka（見 Kafka 列）</td>
      </tr>
      <tr>
          <td><a href="redis-streams/">Redis Streams</a></td>
          <td><a href="redis-streams/xclaim-pel-recovery/">XCLAIM/PEL</a></td>
          <td><a href="redis-streams/migrate-to-kafka/">→ Kafka</a></td>
      </tr>
      <tr>
          <td><a href="aws-sqs/">AWS SQS</a></td>
          <td><a href="aws-sqs/visibility-polling-lambda-cost/">visibility/polling/Lambda</a></td>
          <td><a href="aws-sqs/migrate-to-google-pubsub/">→ Google Pub/Sub</a></td>
      </tr>
      <tr>
          <td><a href="google-pubsub/">Google Pub/Sub</a></td>
          <td><a href="google-pubsub/ordering-dlt-schema/">ordering/DLT/schema</a> / <a href="google-pubsub/push-pull-ack-flow-control/">push/pull/ack flow control</a></td>
          <td><a href="google-pubsub/migrate-from-kafka/">← Kafka</a></td>
      </tr>
  </tbody>
</table>
<p>deep article 走 <a href="/blog/posts/vendor-%E6%B7%B1%E5%BA%A6%E6%8A%80%E8%A1%93%E6%96%87%E7%AB%A0%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84%E5%90%8C-vendor-%E7%B3%BB%E5%88%97%E7%9A%84%E9%96%8B%E5%A0%B4%E8%BC%AA%E6%9B%BF%E9%A9%97%E8%AD%89/" data-link-title="Vendor 深度技術文章方法論的演化紀錄：同 vendor 系列的開場輪替驗證" data-link-desc="vendor overview 飽和後要寫單一功能深度文章、需要選題與結構依據時回來。這套方法論的驗證來源與 cadence variant 在高風險場景（同 vendor sub-tool 系列）的實證。">6-section 模板</a>、指令均經 Docker / emulator 實機驗證（驗不了的標 caveat）；migration playbook 走 <a href="/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">6-type 結構</a>。</p>
<p>main 與 feat/backend_03 兩批平行撰寫過 03 deep article、重疊主題已去重：RabbitMQ quorum、Redis Streams PEL、AWS SQS visibility 三組各保留涵蓋較完整、經實機驗證的一篇（主題框架已併入）。NATS 保留兩篇互補定位——<a href="nats/jetstream-durability-consumer/">core 到 JetStream 邊界</a> 是採用決策入口、<a href="nats/jetstream-supercluster-design/">JetStream 設計與 supercluster/leaf</a> 是完整實作。後續候選見上方「T1 服務頁大綱」段、各 vendor <code>_index.md</code> 進階主題段與下方「後續候選」表。</p>
<h2 id="服務頁撰寫欄位">服務頁撰寫欄位</h2>
<table>
  <thead>
      <tr>
          <th>欄位</th>
          <th>佇列服務頁要保留的問題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>服務責任</td>
          <td>它承擔 work queue、event log、pub/sub、stream 還是 workflow handoff</td>
      </tr>
      <tr>
          <td>適用壓力</td>
          <td>throughput、ordering、fan-out、retention、replay、managed operation 哪個壓力最明顯</td>
      </tr>
      <tr>
          <td>替代邊界</td>
          <td>broker、event streaming、managed queue、workflow engine 的機會成本</td>
      </tr>
      <tr>
          <td>操作成本</td>
          <td>partition、consumer lag、DLQ drain、schema、ACL、upgrade、quota</td>
      </tr>
      <tr>
          <td>Evidence</td>
          <td>publish rate、consume rate、lag、redelivery、DLQ depth、replay window</td>
      </tr>
      <tr>
          <td>案例回寫</td>
          <td>Meta FOQS、VMware MSK、LinkedIn TopicGC 如何提供治理判準</td>
      </tr>
  </tbody>
</table>
<p>服務責任段要先分辨投遞成功與處理成功。Broker 可以保存訊息與重新投遞，但 consumer 的 idempotency、side effect、checkpoint 與補償流程才決定業務結果是否可恢復。</p>
<p>適用壓力段要保留副作用語言。寄信、轉檔、invoice、search index sync、webhook fan-out 與 audit event 的 retry、ordering、DLQ 與 replay 條件不同，服務頁要分別展開。</p>
<h2 id="服務頁標準章節">服務頁標準章節</h2>
<table>
  <thead>
      <tr>
          <th>章節</th>
          <th>佇列服務頁要補的內容</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>服務定位</td>
          <td>它是 work queue、event log、pub/sub、embedded stream 還是 workflow engine</td>
      </tr>
      <tr>
          <td>本章目標</td>
          <td>讀者能判斷 delivery、processing、recovery、ordering 與 replay 邊界</td>
      </tr>
      <tr>
          <td>最短判讀路徑</td>
          <td>用「是否需要 durable retry、fan-out、ordering、replay」快速定位工具類型</td>
      </tr>
      <tr>
          <td>日常操作與決策形狀</td>
          <td>ack/nack、visibility timeout、DLQ、consumer group、schema、quota</td>
      </tr>
      <tr>
          <td>核心取捨表</td>
          <td>RabbitMQ、Kafka、SQS、Pub/Sub、NATS、Redis Streams 的機會成本</td>
      </tr>
      <tr>
          <td>進階主題</td>
          <td>partition、retention、exactly-once claims、multi-region、managed quota</td>
      </tr>
      <tr>
          <td>排錯與失敗快速判讀</td>
          <td>lag、redelivery、DLQ depth、poison message、consumer pause、offset</td>
      </tr>
      <tr>
          <td>何時改走其他服務</td>
          <td>human workflow 轉 workflow engine、同步查詢回 API、正式狀態回 database</td>
      </tr>
      <tr>
          <td>不在本頁內的主題</td>
          <td>完整 client API、framework adapter、所有 broker plugin</td>
      </tr>
      <tr>
          <td>案例回寫與下一步路由</td>
          <td>回到 3.C cases、6.12 replay verification、8.19 decision log</td>
      </tr>
  </tbody>
</table>
<h2 id="跨-vendor-議題對照">跨 vendor 議題對照</h2>
<p>橫向議題在不同 vendor 用不同旋鈕達成。本表把同一議題在 6 個 vendor 的對應位置列出、確保大綱不缺漏議題、且讀者跨 vendor 查找對照位置時有索引。</p>
<table>
  <thead>
      <tr>
          <th>議題</th>
          <th>Kafka</th>
          <th>RabbitMQ</th>
          <th>NATS</th>
          <th>Redis Streams</th>
          <th>AWS SQS</th>
          <th>Pub/Sub</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>多租戶配額 / 隔離</td>
          <td>quota + ACL</td>
          <td>vhost + user permission</td>
          <td>account + subject ACL</td>
          <td>Redis ACL</td>
          <td>IAM policy</td>
          <td>IAM + Service Account</td>
      </tr>
      <tr>
          <td>跨區 / 全球交付</td>
          <td>MirrorMaker 2</td>
          <td>Federation / Shovel</td>
          <td>Supercluster + Leaf node</td>
          <td>Redis Cluster（受限）</td>
          <td>Cross-region replication</td>
          <td>內建 global routing</td>
      </tr>
      <tr>
          <td>Topic 生命週期治理</td>
          <td>TopicGC、auto-cleanup</td>
          <td>vhost / queue lifecycle</td>
          <td>Stream lifecycle</td>
          <td>MAXLEN / XTRIM</td>
          <td>DLQ + redrive policy</td>
          <td>Subscription expiration</td>
      </tr>
      <tr>
          <td>自動修復</td>
          <td>Self-healing automation</td>
          <td>cluster_partition_handling</td>
          <td>JetStream raft</td>
          <td>Sentinel / Cluster failover</td>
          <td>managed 內建</td>
          <td>managed 內建</td>
      </tr>
      <tr>
          <td>Delivery 機制</td>
          <td>acks + idempotence + ISR</td>
          <td>manual ack + DLX</td>
          <td>JetStream ack + AckWait</td>
          <td>XACK + XCLAIM + PEL</td>
          <td>visibility timeout + DLQ</td>
          <td>ack deadline + DLT</td>
      </tr>
      <tr>
          <td>路由模型</td>
          <td>partition + key</td>
          <td>exchange + routing key</td>
          <td>subject + wildcard</td>
          <td>stream key（無 partition）</td>
          <td>queue URL</td>
          <td>topic + subscription</td>
      </tr>
      <tr>
          <td>持久化模型</td>
          <td>log + retention policy</td>
          <td>durable queue + TTL</td>
          <td>JetStream storage</td>
          <td>append-only log（RAM）</td>
          <td>managed durable</td>
          <td>managed durable</td>
      </tr>
      <tr>
          <td>Schema 治理</td>
          <td>Schema Registry</td>
          <td>（無原生）</td>
          <td>（無原生、靠 JSON Schema 慣例）</td>
          <td>（無）</td>
          <td>（無）</td>
          <td>Schema enforcement</td>
      </tr>
      <tr>
          <td>主討論案例</td>
          <td>C1/C3-C7 + C11-C22</td>
          <td>C23-C33</td>
          <td>C34-C41</td>
          <td>C42-C47</td>
          <td>C48-C59 + C2 反面</td>
          <td>C60-C69</td>
      </tr>
  </tbody>
</table>
<p>對照表的用途有三：</p>
<ul>
<li>寫某 vendor 頁時、檢查橫向議題是否都有對應的進階主題子段、避免缺漏</li>
<li>讀者在 vendor 間遷移時、知道對應旋鈕在另一個 vendor 叫什麼</li>
<li>未來擴充案例時、依 <a href="/blog/backend/03-message-queue/cases/" data-link-title="模組三案例正文" data-link-desc="訊息佇列與事件傳遞的轉換案例入口、含通用案例與 6 個 vendor 的真實 production case 庫。">cases/_index 的「案例覆蓋缺口」段</a> 判定優先補的章節</li>
</ul>
<p>下面 8 段把對照表的每行展開、避免單純的表格成為「終點」。每段先解釋議題本質、再展開不同 vendor 的 mechanism 差異、最後給選型判讀。</p>
<h3 id="路由模型">路由模型</h3>
<p>路由模型決定「訊息怎麼送到對的 consumer」、不是同概念換名字。<strong>Kafka</strong> partition + key 透過 hash 把訊息落在固定 partition、consumer group 靠 rebalance 綁定 partition 跟 consumer；<strong>RabbitMQ</strong> exchange + routing key 透過 binding rule 比對、可 broadcast（fanout）/ 精準（direct）/ pattern（topic + <code>*</code> 單層 / <code>#</code> 多層）；<strong>NATS</strong> subject + wildcard（<code>*</code> 單層、<code>&gt;</code> 多層）讓 subscriber 用 pattern 訂閱主題層級；<strong>Redis Streams</strong> 是單一 stream key、無 partition、跨 shard 要靠 hash tag 強制分散；<strong>SQS</strong> queue URL 直接對應、無 routing 邏輯；<strong>Pub/Sub</strong> topic + subscription、subscription 是 first-class entity（跟 Kafka topic + consumer group 不同）。</p>
<p>選型判讀：需要 fan-out 多 subscriber → fanout exchange / subject pattern / multi-subscription；需要 per-key ordering → Kafka partition+key / RabbitMQ consistent hash exchange / NATS queue group；不需 routing 邏輯 → SQS 最簡單。</p>
<h3 id="delivery-機制">Delivery 機制</h3>
<p>Delivery 機制是「broker 怎麼保證訊息被處理」、不同 vendor 用不同協議層級達成同語意。詳見 <a href="/blog/backend/03-message-queue/broker-basics/#%e8%aa%9e%e6%84%8f%e4%bf%9d%e8%ad%89%e7%9a%84%e4%b8%8d%e5%90%8c%e5%af%a6%e4%bd%9c%e6%a9%9f%e5%88%b6" data-link-title="3.1 broker 基礎與投遞模型" data-link-desc="先理解 broker、queue、consumer 與 delivery semantics">3.1 broker-basics 的「語意保證的不同實作機制」</a>。三層核心旋鈕：<strong>Kafka</strong> acks（0/1/all）+ idempotence + ISR（min.insync.replicas）；<strong>RabbitMQ</strong> manual ack + DLX + prefetch；<strong>NATS</strong> JetStream ack + AckWait + MaxDeliver；<strong>Redis Streams</strong> XACK + XCLAIM + PEL；<strong>SQS</strong> visibility timeout + DLQ + maxReceiveCount；<strong>Pub/Sub</strong> ack deadline + DLT + ack extension。</p>
<p>選型判讀：寫入即承諾（事件流）→ Kafka acks=all + ISR；處理即承諾（任務隊列）→ RabbitMQ manual ack / SQS visibility timeout / Pub/Sub ack deadline；wire-level handshake（device 端）→ MQTT QoS（透過 RabbitMQ MQTT plugin 或 EMQX）。</p>
<h3 id="持久化模型">持久化模型</h3>
<p>持久化模型決定「訊息能保留多久、能不能 replay」。<strong>Kafka</strong> log + retention policy（time / size、compact / delete）— 訊息保留到 retention 過期、consumer 可任意 offset replay；<strong>RabbitMQ</strong> durable queue + TTL — 訊息持久化但 ack 後即刪、不能 replay；<strong>NATS</strong> JetStream storage（file / memory、配 MaxMsgs / MaxBytes / MaxAge）— 介於 log 跟 queue 之間；<strong>Redis Streams</strong> append-only log 但受 RAM 限制 — retention 短期、replay 視 MAXLEN 設定；<strong>SQS / Pub/Sub</strong> managed durable — SQS 最長 14 天、Pub/Sub 7 天、不適合長期 archive。</p>
<p>選型判讀：需要事件 replay（多 consumer 各自進度、長期保留）→ Kafka / Pulsar / JetStream；任務處理即刪（worker pool）→ RabbitMQ / SQS / Pub/Sub；中期 stream 但已在 Redis 生態 → Redis Streams + MAXLEN。</p>
<h3 id="topic-生命週期治理">Topic 生命週期治理</h3>
<p>當 topic / queue 數量上萬、metadata 本身變成 broker 壓力。<strong>Kafka</strong> 早期靠人工管 topic、規模化後需 TopicGC（自動清理 unused topic）+ partition 數量上限；<strong>RabbitMQ</strong> vhost / queue lifecycle 通常手動、queue auto-delete + TTL 是常見 pattern；<strong>NATS</strong> JetStream stream 有 lifecycle policy（DiscardPolicy / MaxAge）；<strong>Redis Streams</strong> MAXLEN / XTRIM 手動修剪、無自動 GC；<strong>SQS</strong> DLQ + redrive policy 是 lifecycle 核心、queue 本身不自動刪；<strong>Pub/Sub</strong> subscription expiration policy（閒置 N 天自動刪）。</p>
<p>選型判讀：metadata 量大（topic 數 / partition 數）→ 需 Kafka TopicGC 模式；任務隊列 → 需 DLQ + redrive 規範；長期 stream → 需明示 retention policy。</p>
<h3 id="自動修復">自動修復</h3>
<p>自動修復把 SRE 從人工值班轉到自動化、但層次不同。<strong>Kafka</strong> Self-healing（disk full / broker offline / under-replicated partition 自動處理）；<strong>RabbitMQ</strong> cluster_partition_handling（ignore / autoheal / pause_minority）— 偏向「腦裂處理策略」、不是全自動 SRE；<strong>NATS</strong> JetStream raft 自動 leader election + replica sync；<strong>Redis Streams</strong> 靠 Sentinel / Cluster failover、failover 期間 PEL 可能不一致；<strong>SQS / Pub/Sub</strong> managed 內建、不需用戶管。</p>
<p>選型判讀：自管要 24/7 → Kafka self-healing 或 NATS raft；不要值班 → managed（SQS / Pub/Sub）；中等規模容忍人工 → RabbitMQ cluster_partition_handling。</p>
<h3 id="多租戶配額--隔離">多租戶配額 / 隔離</h3>
<p>隔離粒度跟 mechanism 不同。<strong>Kafka</strong> quota（byte rate / request rate）+ ACL（principal / resource / operation）— 流量級 + identity 級；<strong>RabbitMQ</strong> vhost + user permission — namespace 級隔離（最強）；<strong>NATS</strong> account + subject ACL — account 是 namespace、subject ACL 是細粒度權限；<strong>Redis Streams</strong> Redis ACL — command-level 權限；<strong>SQS / Pub/Sub</strong> IAM policy + Service Account — identity 級、無 namespace 概念。</p>
<p>選型判讀：跨 team 共用 cluster → 需 namespace 隔離（vhost / account）；多 client app → identity 隔離（IAM）；流量公平 → 需 quota（Kafka quota / 自建 rate limit）。</p>
<h3 id="跨區--全球交付">跨區 / 全球交付</h3>
<p>跨區拓樸三類：mesh（broker 自己同步）vs hub-spoke（單向轉發）vs managed global。<strong>Kafka</strong> MirrorMaker 2 是 mesh（active-active / active-passive）；<strong>RabbitMQ</strong> Federation 是 hub-spoke（upstream → downstream 鬆耦合）、Shovel 是點對點搬運；<strong>NATS</strong> Supercluster + Leaf node 是 mesh + edge（適合 IoT 廠區）；<strong>Redis Cluster</strong> 跨區受限（Cluster 是 shard、不是 region）；<strong>SQS</strong> Cross-region replication（managed）；<strong>Pub/Sub</strong> 內建 global routing — 無需設定。</p>
<p>選型判讀：自管要 mesh → MirrorMaker 2 / NATS Supercluster；hub-spoke 簡單 → Federation；不想處理跨區 → Pub/Sub global 或 SQS replication。</p>
<h3 id="schema-治理">Schema 治理</h3>
<p>Schema 強制度跨 vendor 差異最大。<strong>Kafka</strong> Schema Registry（Confluent / Apicurio）+ Avro / Protobuf — 強制 producer 帶 schema ID、enforce compatibility；<strong>RabbitMQ</strong> 無原生 schema 機制 — 靠 application 層約定；<strong>NATS</strong> 無原生、靠 JSON Schema 慣例；<strong>Redis Streams</strong> 無 schema 概念；<strong>SQS</strong> message attribute + body string — 無 enforce；<strong>Pub/Sub</strong> Schema enforcement（topic 綁 Avro / Protobuf schema）。</p>
<p>選型判讀：跨服務契約嚴 → Kafka + Schema Registry / Pub/Sub Schema enforcement；內部簡單通訊 → RabbitMQ / NATS 靠慣例；schema 演進頻繁 → 需 forward / backward / full compatibility 規範。</p>
<h2 id="服務頁大綱對齊">服務頁大綱對齊</h2>
<p>6 個 vendor 頁套同樣的章節結構、方便讀者跨 vendor 跳讀。對齊參考 <a href="/blog/llm/01-local-llm-services/ollama/" data-link-title="1.0 Ollama：主流推論伺服器" data-link-desc="一行 brew 裝完、ollama run 一鍵跑 Gemma 4 MTP、OpenAI 相容 API on localhost:11434">LLM 模組 1.0 Ollama</a> 的「觀念 → 原理 → 操作指令」分層寫法：</p>
<ol>
<li><strong>服務定位</strong>（段首段、3 個責任 + 設計取捨）</li>
<li><strong>本章目標</strong>（5 條可驗證能力 checklist）</li>
<li><strong>最短路徑</strong>（5 分鐘可跑通的 install + verify、bash 範例 placeholder）</li>
<li><strong>日常操作與決策形狀</strong>（CLI / API、路由設計、ack 策略三個子段）</li>
<li><strong>進階主題</strong>（按需閱讀、每子段對應一個 case 或 vendor 專長議題）</li>
<li><strong>排錯快速判讀</strong>（每情境：操作原則 + 指令 + 解法）</li>
<li><strong>何時改走其他服務</strong>（對照表）</li>
<li><strong>不在本頁內的主題</strong>（明確邊界）</li>
<li><strong>案例回寫</strong>（cases/ 引用 + 主討論議題）</li>
<li><strong>下一步路由</strong>（上游概念 / 平行 vendor / 下游能力）</li>
</ol>
<p>每個章節「要回答的問題」「要包含的指令範例 placeholder」「對應 case」都已寫在各 vendor 頁的大綱、但未寫實際正文 — 等到撰寫批次（見下節）開始時才展開。</p>
<h2 id="撰寫批次">撰寫批次</h2>
<table>
  <thead>
      <tr>
          <th>批次</th>
          <th>服務頁</th>
          <th>撰寫目的</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Q1</td>
          <td>RabbitMQ</td>
          <td>建立 work queue、routing、ack/nack 與 DLQ baseline</td>
      </tr>
      <tr>
          <td>Q2</td>
          <td>Kafka</td>
          <td>建立 event log、partition、retention 與 replay 判準</td>
      </tr>
      <tr>
          <td>Q3</td>
          <td>AWS SQS / Google Pub/Sub</td>
          <td>建立 managed delivery、visibility timeout 與 cloud pub/sub 邊界</td>
      </tr>
      <tr>
          <td>Q4</td>
          <td>NATS / Redis Streams</td>
          <td>建立 lightweight messaging 與 embedded stream 的邊界</td>
      </tr>
      <tr>
          <td>Q5</td>
          <td>Pulsar / Kinesis / Temporal</td>
          <td>補 multi-tenant streaming、managed stream 與 workflow engine 對照</td>
      </tr>
  </tbody>
</table>
<h2 id="後續候選">後續候選</h2>
<table>
  <thead>
      <tr>
          <th>類型</th>
          <th>候選服務</th>
          <th>寫作重點</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Streaming</td>
          <td>Apache Pulsar、Redpanda、AWS Kinesis、Confluent Cloud / MSK</td>
          <td>retention、partition、managed Kafka、serverless stream</td>
      </tr>
      <tr>
          <td>Managed event bus</td>
          <td>AWS SNS、EventBridge、Azure Event Grid</td>
          <td>fan-out、event routing、schema、cloud-native integration</td>
      </tr>
      <tr>
          <td>Enterprise queue</td>
          <td>Azure Service Bus、ActiveMQ、IBM MQ</td>
          <td>enterprise integration、session、routing、DLQ</td>
      </tr>
      <tr>
          <td>Workflow engine</td>
          <td>Temporal、Cadence</td>
          <td>durable workflow、activity retry、human / machine workflow 邊界</td>
      </tr>
      <tr>
          <td>Lightweight</td>
          <td>NSQ、ZeroMQ</td>
          <td>simple broker、library messaging、durability trade-off</td>
      </tr>
      <tr>
          <td>IoT messaging</td>
          <td>MQTT、EMQX、HiveMQ、Mosquitto</td>
          <td>device connection、QoS、topic hierarchy、edge constraints</td>
      </tr>
  </tbody>
</table>
<p>主流覆蓋檢查的重點是分開 queue、stream、event bus、workflow 與 device messaging。Kafka / Pulsar / Kinesis 解 event stream；SQS / Service Bus 解 managed queue；SNS / EventBridge / Event Grid 解 cloud event routing；Temporal 解 workflow state；MQTT broker 解 IoT device delivery。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/03-message-queue/durable-queue/" data-link-title="3.2 durable queue 與重試策略" data-link-desc="整理持久化佇列、DLQ 與重試流程">3.2 durable queue</a></li>
<li>上游：<a href="/blog/backend/03-message-queue/consumer-design/" data-link-title="3.4 consumer 設計與去重" data-link-desc="整理 consumer、checkpoint 與 replay safety">3.4 consumer design</a></li>
<li>案例：<a href="/blog/backend/03-message-queue/cases/" data-link-title="模組三案例正文" data-link-desc="訊息佇列與事件傳遞的轉換案例入口、含通用案例與 6 個 vendor 的真實 production case 庫。">3.C 佇列案例正文</a></li>
<li>服務路徑：<a href="/blog/backend/03-message-queue/queue-consumer-retry-replay-handoff/" data-link-title="3.8 Queue Consumer Retry 與 Replay Handoff（實作示範）" data-link-desc="以 order_created consumer 示範 queue 路徑如何交付 idempotency evidence、DLQ handling、replay runbook 與 incident decision log。">3.8 Queue Consumer Retry 與 Replay Handoff</a></li>
</ul>
]]></content:encoded></item><item><title>部署平台 Vendor 清單</title><link>https://tarrragon.github.io/blog/backend/05-deployment-platform/vendors/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/05-deployment-platform/vendors/</guid><description>&lt;p>部署平台 Vendor 清單的核心責任是把平台名稱放回 runtime contract、lifecycle contract、traffic contract、control plane 與 rollout governance 的判斷。每個服務頁先回答它承擔啟動、調度、入口、設定、基礎設施狀態或 service discovery 的哪一段，再討論操作成本與案例回寫。部署這塊能力的買 vs 建是一條深度光譜：自管 Kubernetes、用 managed K8s（EKS、GKE、AKS）、用 PaaS（Fly、Render、Railway），到完全 serverless — 越往右維運越少、客製與可攜性也越受限，取捨見 &lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/capability-buy-vs-build/" data-link-title="0.22 能力級買 vs 建：feature-as-a-service 與 BaaS bundle 選型" data-link-desc="在交付形態決定整個系統要不要自建之後、逐能力判斷該外包還是自建：辨識 managed 基礎設施、feature SaaS 與 BaaS bundle 三種外包深度、no-code 到 dev-tool 的服務光譜、買 vs 建判準與權重浮動、整合接縫與遷出代價">0.22 能力級買 vs 建&lt;/a>。&lt;/p>
&lt;h2 id="讀法">讀法&lt;/h2>
&lt;p>部署服務要從服務生命週期進入。讀者如果要處理 container 與 runtime，先回到 &lt;a href="https://tarrragon.github.io/blog/backend/05-deployment-platform/container-runtime/" data-link-title="5.1 container 與 runtime" data-link-desc="整理 image、resource limit 與啟動行為">5.1 container runtime&lt;/a>；如果要處理 rollout 與 probe，先回到 &lt;a href="https://tarrragon.github.io/blog/backend/05-deployment-platform/kubernetes-deployment/" data-link-title="5.2 Kubernetes 部署策略" data-link-desc="整理 deployment、probe 與 rolling update">5.2 Kubernetes deployment&lt;/a>；如果要處理入口與 drain，先回到 &lt;a href="https://tarrragon.github.io/blog/backend/05-deployment-platform/load-balancer-contract/" data-link-title="5.3 load balancer 合約" data-link-desc="整理 idle timeout、draining 與 health check">5.3 Load Balancer Contract&lt;/a>。&lt;/p>
&lt;h2 id="教學順序同步">教學順序同步&lt;/h2>
&lt;p>部署平台服務頁的教學順序是先建立 workload runtime，再進入 orchestration、traffic entry、infra state 與 discovery。這個順序對齊 checkout E4：讀者先理解服務如何啟動、接流量、drain 與 rollback，再比較 Kubernetes、systemd、Docker、load balancer、proxy、Terraform 與 Consul 分別承擔哪一層平台責任。&lt;/p>
&lt;h2 id="t1-服務頁大綱">T1 服務頁大綱&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>服務&lt;/th>
 &lt;th>類型&lt;/th>
 &lt;th>頁面要回答的核心問題&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/05-deployment-platform/vendors/kubernetes/" data-link-title="Kubernetes" data-link-desc="Container orchestration 主流、GKE / EKS / AKS / 自管">Kubernetes&lt;/a>&lt;/td>
 &lt;td>Orchestration&lt;/td>
 &lt;td>pod lifecycle、probe、rolling update 與 resource limit 如何成為平台契約&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/05-deployment-platform/vendors/docker/" data-link-title="Docker" data-link-desc="Container runtime / image 標準">Docker&lt;/a>&lt;/td>
 &lt;td>Container runtime&lt;/td>
 &lt;td>image、entrypoint、runtime config 與 local / prod parity 如何管理&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/05-deployment-platform/vendors/systemd/" data-link-title="systemd" data-link-desc="Linux init system、VM / 單機 service lifecycle">systemd&lt;/a>&lt;/td>
 &lt;td>Process supervisor&lt;/td>
 &lt;td>unit、restart policy、signal 與 journal 如何支援單機服務&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/05-deployment-platform/vendors/nginx/" data-link-title="nginx" data-link-desc="HTTP server / reverse proxy / LB / ingress">nginx&lt;/a>&lt;/td>
 &lt;td>Reverse proxy / LB&lt;/td>
 &lt;td>reverse proxy、timeout、buffering、TLS 與 ingress 如何取捨&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/05-deployment-platform/vendors/envoy/" data-link-title="Envoy" data-link-desc="Cloud-native service proxy、xDS dynamic config、Istio / Gateway 底層">Envoy&lt;/a>&lt;/td>
 &lt;td>Service proxy&lt;/td>
 &lt;td>xDS、dynamic config、mesh data plane 與 traffic policy 如何治理&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/05-deployment-platform/vendors/aws-elb/" data-link-title="AWS ELB（ALB / NLB / CLB）" data-link-desc="AWS managed load balancer、ALB（L7）/ NLB（L4）/ CLB（legacy）">AWS ELB&lt;/a>&lt;/td>
 &lt;td>Managed LB&lt;/td>
 &lt;td>ALB / NLB、health check、draining 與 target group 如何支援 AWS 入口&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/05-deployment-platform/vendors/terraform/" data-link-title="Terraform / OpenTofu" data-link-desc="Infrastructure as Code 主流工具">Terraform / OpenTofu&lt;/a>&lt;/td>
 &lt;td>IaC&lt;/td>
 &lt;td>state、plan、provider、drift 與 review gate 如何管理 infra 變更&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/05-deployment-platform/vendors/traefik/" data-link-title="Traefik" data-link-desc="Cloud-native ingress / reverse proxy、auto-discovery">Traefik&lt;/a>&lt;/td>
 &lt;td>Ingress / proxy&lt;/td>
 &lt;td>auto-discovery、dynamic routing 與 cloud-native ingress 如何取捨&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/05-deployment-platform/vendors/consul/" data-link-title="Consul" data-link-desc="Service registry / mesh / KV / DNS">Consul&lt;/a>&lt;/td>
 &lt;td>Registry / mesh&lt;/td>
 &lt;td>service registry、DNS、health check、KV 與 mesh 邊界如何取捨&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="內容覆蓋進度">內容覆蓋進度&lt;/h2>
&lt;p>每個 vendor 服務頁下會擴充兩類文章：deep article（vendor 自身的配置、故障、容量、走 &lt;a href="https://tarrragon.github.io/blog/posts/vendor-%E6%B7%B1%E5%BA%A6%E6%8A%80%E8%A1%93%E6%96%87%E7%AB%A0%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84%E5%90%8C-vendor-%E7%B3%BB%E5%88%97%E7%9A%84%E9%96%8B%E5%A0%B4%E8%BC%AA%E6%9B%BF%E9%A9%97%E8%AD%89/" data-link-title="Vendor 深度技術文章方法論的演化紀錄：同 vendor 系列的開場輪替驗證" data-link-desc="vendor overview 飽和後要寫單一功能深度文章、需要選題與結構依據時回來。這套方法論的驗證來源與 cadence variant 在高風險場景（同 vendor sub-tool 系列）的實證。">6-section 模板&lt;/a>）跟 migration playbook（跨 vendor 遷移流程、走 &lt;a href="https://tarrragon.github.io/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">6-type 結構&lt;/a>）。「→ X」代表遷移到 X 的 playbook、「← X」代表從 X 遷入。&lt;/p></description><content:encoded><![CDATA[<p>部署平台 Vendor 清單的核心責任是把平台名稱放回 runtime contract、lifecycle contract、traffic contract、control plane 與 rollout governance 的判斷。每個服務頁先回答它承擔啟動、調度、入口、設定、基礎設施狀態或 service discovery 的哪一段，再討論操作成本與案例回寫。部署這塊能力的買 vs 建是一條深度光譜：自管 Kubernetes、用 managed K8s（EKS、GKE、AKS）、用 PaaS（Fly、Render、Railway），到完全 serverless — 越往右維運越少、客製與可攜性也越受限，取捨見 <a href="/blog/backend/00-service-selection/capability-buy-vs-build/" data-link-title="0.22 能力級買 vs 建：feature-as-a-service 與 BaaS bundle 選型" data-link-desc="在交付形態決定整個系統要不要自建之後、逐能力判斷該外包還是自建：辨識 managed 基礎設施、feature SaaS 與 BaaS bundle 三種外包深度、no-code 到 dev-tool 的服務光譜、買 vs 建判準與權重浮動、整合接縫與遷出代價">0.22 能力級買 vs 建</a>。</p>
<h2 id="讀法">讀法</h2>
<p>部署服務要從服務生命週期進入。讀者如果要處理 container 與 runtime，先回到 <a href="/blog/backend/05-deployment-platform/container-runtime/" data-link-title="5.1 container 與 runtime" data-link-desc="整理 image、resource limit 與啟動行為">5.1 container runtime</a>；如果要處理 rollout 與 probe，先回到 <a href="/blog/backend/05-deployment-platform/kubernetes-deployment/" data-link-title="5.2 Kubernetes 部署策略" data-link-desc="整理 deployment、probe 與 rolling update">5.2 Kubernetes deployment</a>；如果要處理入口與 drain，先回到 <a href="/blog/backend/05-deployment-platform/load-balancer-contract/" data-link-title="5.3 load balancer 合約" data-link-desc="整理 idle timeout、draining 與 health check">5.3 Load Balancer Contract</a>。</p>
<h2 id="教學順序同步">教學順序同步</h2>
<p>部署平台服務頁的教學順序是先建立 workload runtime，再進入 orchestration、traffic entry、infra state 與 discovery。這個順序對齊 checkout E4：讀者先理解服務如何啟動、接流量、drain 與 rollback，再比較 Kubernetes、systemd、Docker、load balancer、proxy、Terraform 與 Consul 分別承擔哪一層平台責任。</p>
<h2 id="t1-服務頁大綱">T1 服務頁大綱</h2>
<table>
  <thead>
      <tr>
          <th>服務</th>
          <th>類型</th>
          <th>頁面要回答的核心問題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/05-deployment-platform/vendors/kubernetes/" data-link-title="Kubernetes" data-link-desc="Container orchestration 主流、GKE / EKS / AKS / 自管">Kubernetes</a></td>
          <td>Orchestration</td>
          <td>pod lifecycle、probe、rolling update 與 resource limit 如何成為平台契約</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/05-deployment-platform/vendors/docker/" data-link-title="Docker" data-link-desc="Container runtime / image 標準">Docker</a></td>
          <td>Container runtime</td>
          <td>image、entrypoint、runtime config 與 local / prod parity 如何管理</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/05-deployment-platform/vendors/systemd/" data-link-title="systemd" data-link-desc="Linux init system、VM / 單機 service lifecycle">systemd</a></td>
          <td>Process supervisor</td>
          <td>unit、restart policy、signal 與 journal 如何支援單機服務</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/05-deployment-platform/vendors/nginx/" data-link-title="nginx" data-link-desc="HTTP server / reverse proxy / LB / ingress">nginx</a></td>
          <td>Reverse proxy / LB</td>
          <td>reverse proxy、timeout、buffering、TLS 與 ingress 如何取捨</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/05-deployment-platform/vendors/envoy/" data-link-title="Envoy" data-link-desc="Cloud-native service proxy、xDS dynamic config、Istio / Gateway 底層">Envoy</a></td>
          <td>Service proxy</td>
          <td>xDS、dynamic config、mesh data plane 與 traffic policy 如何治理</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/05-deployment-platform/vendors/aws-elb/" data-link-title="AWS ELB（ALB / NLB / CLB）" data-link-desc="AWS managed load balancer、ALB（L7）/ NLB（L4）/ CLB（legacy）">AWS ELB</a></td>
          <td>Managed LB</td>
          <td>ALB / NLB、health check、draining 與 target group 如何支援 AWS 入口</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/05-deployment-platform/vendors/terraform/" data-link-title="Terraform / OpenTofu" data-link-desc="Infrastructure as Code 主流工具">Terraform / OpenTofu</a></td>
          <td>IaC</td>
          <td>state、plan、provider、drift 與 review gate 如何管理 infra 變更</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/05-deployment-platform/vendors/traefik/" data-link-title="Traefik" data-link-desc="Cloud-native ingress / reverse proxy、auto-discovery">Traefik</a></td>
          <td>Ingress / proxy</td>
          <td>auto-discovery、dynamic routing 與 cloud-native ingress 如何取捨</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/05-deployment-platform/vendors/consul/" data-link-title="Consul" data-link-desc="Service registry / mesh / KV / DNS">Consul</a></td>
          <td>Registry / mesh</td>
          <td>service registry、DNS、health check、KV 與 mesh 邊界如何取捨</td>
      </tr>
  </tbody>
</table>
<h2 id="內容覆蓋進度">內容覆蓋進度</h2>
<p>每個 vendor 服務頁下會擴充兩類文章：deep article（vendor 自身的配置、故障、容量、走 <a href="/blog/posts/vendor-%E6%B7%B1%E5%BA%A6%E6%8A%80%E8%A1%93%E6%96%87%E7%AB%A0%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84%E5%90%8C-vendor-%E7%B3%BB%E5%88%97%E7%9A%84%E9%96%8B%E5%A0%B4%E8%BC%AA%E6%9B%BF%E9%A9%97%E8%AD%89/" data-link-title="Vendor 深度技術文章方法論的演化紀錄：同 vendor 系列的開場輪替驗證" data-link-desc="vendor overview 飽和後要寫單一功能深度文章、需要選題與結構依據時回來。這套方法論的驗證來源與 cadence variant 在高風險場景（同 vendor sub-tool 系列）的實證。">6-section 模板</a>）跟 migration playbook（跨 vendor 遷移流程、走 <a href="/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">6-type 結構</a>）。「→ X」代表遷移到 X 的 playbook、「← X」代表從 X 遷入。</p>
<table>
  <thead>
      <tr>
          <th>Vendor</th>
          <th>Deep article</th>
          <th>Migration playbook</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="kubernetes/">Kubernetes</a></td>
          <td><a href="kubernetes/graceful-shutdown/">graceful-shutdown</a></td>
          <td><a href="kubernetes/migrate-from-docker-swarm/">← Docker Swarm</a></td>
      </tr>
      <tr>
          <td><a href="terraform/">Terraform</a></td>
          <td>—</td>
          <td><a href="terraform/migrate-to-opentofu/">→ OpenTofu</a></td>
      </tr>
      <tr>
          <td><a href="consul/">Consul</a></td>
          <td>—</td>
          <td><a href="consul/migrate-from-etcd/">← etcd</a></td>
      </tr>
  </tbody>
</table>
<p>其他 T1 vendor（Docker / systemd / nginx / Envoy / AWS ELB / Traefik）尚未開始。對應的 backlog 議題見上方「T1 服務頁大綱」段每個服務頁要回答的核心問題、跟各 vendor <code>_index.md</code> 的「預計實作話題」段。</p>
<h2 id="服務頁撰寫欄位">服務頁撰寫欄位</h2>
<table>
  <thead>
      <tr>
          <th>欄位</th>
          <th>部署服務頁要保留的問題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>服務責任</td>
          <td>它承擔 runtime、orchestration、traffic entry、IaC、registry 還是 mesh</td>
      </tr>
      <tr>
          <td>適用壓力</td>
          <td>rollout frequency、instance count、long connection、multi-region、team ownership 哪個壓力最明顯</td>
      </tr>
      <tr>
          <td>替代邊界</td>
          <td>VM、container、Kubernetes、managed platform、service mesh、simple proxy 的機會成本</td>
      </tr>
      <tr>
          <td>操作成本</td>
          <td>upgrade、config drift、certificate、health check、drain、state、rollback</td>
      </tr>
      <tr>
          <td>Evidence</td>
          <td>deploy marker、per-version SLI、health check、drain completion、plan diff、registry freshness</td>
      </tr>
      <tr>
          <td>案例回寫</td>
          <td>Tradeshift、Condé Nast、Orbitera 與平台切換案例如何提供回退判準</td>
      </tr>
  </tbody>
</table>
<h2 id="服務頁標準章節">服務頁標準章節</h2>
<table>
  <thead>
      <tr>
          <th>章節</th>
          <th>部署服務頁要補的內容</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>服務定位</td>
          <td>它是 runtime、process supervisor、orchestrator、proxy、LB、IaC 還是 registry</td>
      </tr>
      <tr>
          <td>本章目標</td>
          <td>讀者能判斷 lifecycle、traffic、config、resource 與 rollback contract</td>
      </tr>
      <tr>
          <td>最短判讀路徑</td>
          <td>用「服務如何啟動、接流量、擴容、停止、回退」快速定位平台層</td>
      </tr>
      <tr>
          <td>日常操作與決策形狀</td>
          <td>image、unit、deployment、health check、drain、TLS、plan、registry</td>
      </tr>
      <tr>
          <td>核心取捨表</td>
          <td>systemd、Docker、Kubernetes、managed runtime、proxy、service mesh 的機會成本</td>
      </tr>
      <tr>
          <td>進階主題</td>
          <td>multi-cluster、service mesh、dynamic config、IaC drift、managed runtime</td>
      </tr>
      <tr>
          <td>排錯與失敗快速判讀</td>
          <td>readiness、liveness、drain timeout、target health、config drift、state lock</td>
      </tr>
      <tr>
          <td>何時改走其他服務</td>
          <td>單機服務回 systemd、多服務平台上 Kubernetes、簡單入口用 managed LB</td>
      </tr>
      <tr>
          <td>不在本頁內的主題</td>
          <td>完整 YAML / HCL 語法百科、雲端平台所有產品線、語言 framework deployment</td>
      </tr>
      <tr>
          <td>案例回寫與下一步路由</td>
          <td>回到 5.C migration cases、6 release gate、8 decision log</td>
      </tr>
  </tbody>
</table>
<h2 id="跨-vendor-議題對照">跨 vendor 議題對照</h2>
<p>本模組 9 個 vendor 跨 6 個 category（orchestrator / container / process / proxy / LB / IaC / registry）、不是同類產品的多個選項。對照表用「橫向工程議題」標明每個議題在哪些 vendor 是核心責任、哪些不適用。</p>
<table>
  <thead>
      <tr>
          <th>議題</th>
          <th>K8s</th>
          <th>Docker</th>
          <th>systemd</th>
          <th>nginx</th>
          <th>Envoy</th>
          <th>AWS ELB</th>
          <th>Terraform</th>
          <th>Traefik</th>
          <th>Consul</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>主責任</td>
          <td>orchestration</td>
          <td>container build/run</td>
          <td>process supervisor</td>
          <td>reverse proxy</td>
          <td>service proxy</td>
          <td>managed LB</td>
          <td>IaC state</td>
          <td>ingress proxy</td>
          <td>registry / mesh</td>
      </tr>
      <tr>
          <td>服務生命週期</td>
          <td>pod lifecycle</td>
          <td>container run</td>
          <td>service unit</td>
          <td>N/A</td>
          <td>N/A</td>
          <td>target health</td>
          <td>N/A</td>
          <td>N/A</td>
          <td>health check</td>
      </tr>
      <tr>
          <td>流量入口</td>
          <td>Service/Ingress</td>
          <td>port mapping</td>
          <td>listen socket</td>
          <td>HTTP server</td>
          <td>listener</td>
          <td>listener</td>
          <td>N/A</td>
          <td>entrypoint</td>
          <td>N/A</td>
      </tr>
      <tr>
          <td>配置模式</td>
          <td>declarative</td>
          <td>imperative</td>
          <td>declarative</td>
          <td>static config</td>
          <td>xDS dynamic</td>
          <td>API / IaC</td>
          <td>declarative</td>
          <td>dynamic provider</td>
          <td>KV + watch</td>
      </tr>
      <tr>
          <td>Service discovery</td>
          <td>K8s DNS</td>
          <td>N/A</td>
          <td>N/A</td>
          <td>manual upstream</td>
          <td>xDS EDS</td>
          <td>target group</td>
          <td>provider data</td>
          <td>provider 自動</td>
          <td>registry 原生</td>
      </tr>
      <tr>
          <td>Health check</td>
          <td>probe</td>
          <td>healthcheck</td>
          <td>restart policy</td>
          <td>upstream check</td>
          <td>active/passive</td>
          <td>health check</td>
          <td>N/A</td>
          <td>health check</td>
          <td>health check</td>
      </tr>
      <tr>
          <td>TLS / mTLS</td>
          <td>cert-manager</td>
          <td>N/A</td>
          <td>N/A</td>
          <td>ssl module</td>
          <td>filter chain</td>
          <td>ACM</td>
          <td>provider data</td>
          <td>ACME 自動</td>
          <td>Connect mTLS</td>
      </tr>
      <tr>
          <td>Multi-cluster</td>
          <td>federation</td>
          <td>N/A</td>
          <td>N/A</td>
          <td>manual</td>
          <td>mesh control plane</td>
          <td>cross-region</td>
          <td>provider chain</td>
          <td>per cluster</td>
          <td>DC federation</td>
      </tr>
      <tr>
          <td>授權模式</td>
          <td>Apache 2</td>
          <td>Apache 2 / Desktop license</td>
          <td>LGPL</td>
          <td>BSD-2 / Plus 商業</td>
          <td>Apache 2</td>
          <td>AWS managed</td>
          <td>BSL / OpenTofu MPL</td>
          <td>MIT / Hub 商業</td>
          <td>BSL</td>
      </tr>
      <tr>
          <td>主討論案例</td>
          <td>C1/C2/C3/C4/C8</td>
          <td>待補</td>
          <td>待補</td>
          <td>待補</td>
          <td>C5</td>
          <td>C9</td>
          <td>待補</td>
          <td>待補</td>
          <td>待補</td>
      </tr>
  </tbody>
</table>
<p>對照表的用途有三：</p>
<ul>
<li>寫某 vendor 頁時、檢查橫向議題該怎麼定位（不該強塞跟它無關的議題）</li>
<li>讀者理解「9 vendor 不是同類選一個、是不同 layer 各自一個」</li>
<li>評估部署 stack：選 orchestrator + container + proxy + LB + IaC + registry 各 1-2 個組合</li>
</ul>
<p>下面 5 段把對照表的關鍵橫向議題展開（不是每行都展開 — 部分行如「主責任」「授權模式」直接看表即可）。</p>
<h3 id="配置模式">配置模式</h3>
<p>配置模式跨 vendor 差異大、影響 dev workflow 跟 GitOps 整合度。<strong>K8s</strong> declarative（kubectl apply / YAML）；<strong>Terraform</strong> declarative（HCL）；<strong>systemd</strong> declarative（unit file）；<strong>Docker</strong> imperative（CLI）+ Compose declarative；<strong>nginx</strong> static config + reload；<strong>Envoy</strong> xDS dynamic（control plane push）；<strong>Traefik</strong> dynamic（provider 自動 sync）；<strong>AWS ELB</strong> API + IaC；<strong>Consul</strong> KV + watch。</p>
<p>選型判讀：要 GitOps → declarative（K8s + Terraform + systemd unit）；要 zero-reload → dynamic config（Envoy / Traefik）；要 manual control → imperative（Docker / 純 CLI）。</p>
<h3 id="service-discovery--health-check">Service discovery + Health check</h3>
<p>Service discovery 是 5 模組多個 vendor 共同關心的議題、但實作差異大。<strong>K8s</strong> 內建（Service + DNS + kube-proxy）；<strong>Consul</strong> registry first + DNS interface + health check 內建；<strong>Envoy</strong> EDS（xDS endpoint discovery）；<strong>Traefik</strong> provider 自動發現；<strong>nginx / AWS ELB</strong> 配置 upstream target；<strong>Docker / systemd</strong> N/A（單機 / 不負責 discovery）。</p>
<p>選型判讀：K8s-only → 內建；非 K8s 多平台 → Consul；K8s + service mesh → Istio + Envoy；單機 → nginx + manual config。</p>
<h3 id="multi-cluster--跨-dc">Multi-cluster / 跨 DC</h3>
<p>跨多 cluster / DC 拓樸差異大。<strong>K8s</strong> federation（v2 / Cluster API multi-cluster）；<strong>Consul</strong> 一級公民跨 DC（WAN federation）；<strong>Envoy + Istio</strong> multi-cluster mesh；<strong>Terraform</strong> 用 provider chain 管多 cloud / 多 cluster；<strong>AWS ELB</strong> cross-region replication；<strong>nginx / Traefik</strong> 一般 per cluster；<strong>systemd / Docker</strong> N/A。</p>
<p>選型判讀：跨 DC 為核心需求 → Consul / Istio；單一 cluster + cross-region LB → ELB / Global LB；多 cluster K8s → Cluster API + federation。</p>
<h3 id="tls--mtls">TLS / mTLS</h3>
<p>TLS / mTLS 在不同 vendor 由不同 layer 負責。<strong>K8s</strong> cert-manager（Let&rsquo;s Encrypt / 內部 CA）；<strong>AWS ELB</strong> ACM 自動憑證；<strong>Traefik</strong> ACME 自動 TLS；<strong>nginx</strong> ssl module + manual cert / cert-manager；<strong>Envoy</strong> filter chain（SDS 動態 cert）；<strong>Consul Connect</strong> mTLS 自動 sidecar；<strong>Terraform</strong> 不負責 TLS、提供 provider；<strong>Docker / systemd</strong> 不負責（交給 application 或上游 proxy）。</p>
<p>選型判讀：cluster 內 mTLS → cert-manager / Consul Connect；外部 TLS → ACME（Traefik / 自管 cert-manager）；managed → AWS ELB / Cloudflare。</p>
<h3 id="授權模式2023-2024-bsl-變動">授權模式（2023-2024 BSL 變動）</h3>
<p>2023-2024 多個 HashiCorp 產品改 BSL（Terraform / Vault / Consul / Boundary / Vagrant）— 影響採用決策。<strong>Terraform</strong> → OpenTofu fork（Linux Foundation、MPL 2.0）；<strong>Consul</strong> → 暫無大型 fork；<strong>Docker Desktop</strong> → 商業 license（員工 &gt; 250 / 收入 &gt; $10M）→ Podman Desktop 替代；<strong>nginx</strong> → F5 後 OSS 不滿 → Freenginx / angie fork；<strong>K8s / Envoy / Traefik</strong> → 仍 OSI 開源。</p>
<p>選型判讀：商業 SaaS 提供類似服務 → 避 BSL（用 OpenTofu / 自評）；企業內部使用 → BSL 多數無影響；公部門 / 嚴格合規 → 仍要 OSI 認可 license。</p>
<h2 id="撰寫批次">撰寫批次</h2>
<table>
  <thead>
      <tr>
          <th>批次</th>
          <th>服務頁</th>
          <th>撰寫目的</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>D1</td>
          <td>Docker / systemd</td>
          <td>建立 runtime、entrypoint、process supervisor 與單機服務 baseline</td>
      </tr>
      <tr>
          <td>D2</td>
          <td>Kubernetes</td>
          <td>建立 workload lifecycle、orchestration、probe 與 rollout contract</td>
      </tr>
      <tr>
          <td>D3</td>
          <td>nginx / AWS ELB / Envoy / Traefik</td>
          <td>建立 traffic entry、drain、timeout 與 proxy policy 對照</td>
      </tr>
      <tr>
          <td>D4</td>
          <td>Terraform / OpenTofu / Consul</td>
          <td>建立 infra state、service registry 與 control-plane boundary</td>
      </tr>
      <tr>
          <td>D5</td>
          <td>ECS / Fargate / Cloud Run / Nomad</td>
          <td>補 managed runtime、platform abstraction 與自管調度對照</td>
      </tr>
  </tbody>
</table>
<h2 id="後續候選">後續候選</h2>
<table>
  <thead>
      <tr>
          <th>類型</th>
          <th>候選服務</th>
          <th>寫作重點</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>GitOps / package</td>
          <td>Argo CD、Flux、Helm、Kustomize</td>
          <td>desired state、release review、config drift、environment promotion</td>
      </tr>
      <tr>
          <td>Ingress / Gateway</td>
          <td>ingress-nginx、Envoy Gateway、Gateway API、HAProxy</td>
          <td>routing contract、TLS、cross-namespace policy、drain</td>
      </tr>
      <tr>
          <td>Service mesh</td>
          <td>Istio、Linkerd、Cilium Service Mesh</td>
          <td>mTLS、traffic split、sidecar / ambient、control-plane cost</td>
      </tr>
      <tr>
          <td>Managed runtime</td>
          <td>ECS、Fargate、Cloud Run、Azure Container Apps、Fly.io</td>
          <td>managed scaling、deployment contract、platform limit</td>
      </tr>
      <tr>
          <td>Alternative orchestrator</td>
          <td>Nomad、OpenShift、Rancher</td>
          <td>operations model、multi-cluster governance、enterprise support</td>
      </tr>
      <tr>
          <td>IaC / PaaS</td>
          <td>Pulumi、Heroku、Railway、Vercel</td>
          <td>developer workflow、state ownership、backend suitability</td>
      </tr>
  </tbody>
</table>
<p>主流覆蓋檢查的重點是分開 runtime、orchestration、ingress / gateway、GitOps、IaC 與 mesh。Kubernetes 是 orchestration baseline；Argo CD / Flux / Helm / Kustomize 解 desired state delivery；ingress-nginx / Envoy Gateway / HAProxy 解 traffic entry；Istio / Linkerd / Cilium 解 service-to-service policy；ECS / Fargate / Cloud Run 解 managed runtime。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/05-deployment-platform/kubernetes-deployment/" data-link-title="5.2 Kubernetes 部署策略" data-link-desc="整理 deployment、probe 與 rolling update">5.2 Kubernetes deployment</a></li>
<li>上游：<a href="/blog/backend/05-deployment-platform/load-balancer-contract/" data-link-title="5.3 load balancer 合約" data-link-desc="整理 idle timeout、draining 與 health check">5.3 Load Balancer Contract</a></li>
<li>案例：<a href="/blog/backend/05-deployment-platform/cases/" data-link-title="模組五案例正文" data-link-desc="部署平台轉換案例入口。">5.C 部署平台案例正文</a></li>
<li>服務路徑：<a href="/blog/backend/05-deployment-platform/deployment-rollout-drain-rollback/" data-link-title="5.8 Deployment Rollout with Drain and Rollback（實作示範）" data-link-desc="以 checkout service 示範部署切換如何交付 canary evidence、drain signal、release gate 與 incident decision log。">5.8 Deployment Rollout with Drain and Rollback</a></li>
</ul>
]]></content:encoded></item><item><title>資料庫 Vendor 清單</title><link>https://tarrragon.github.io/blog/backend/01-database/vendors/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/01-database/vendors/</guid><description>&lt;p>資料庫 Vendor 清單的核心責任是把 database 服務名稱放回正式狀態、交易邊界、查詢模型、schema 演進、容量與資料治理的判斷。每個服務頁先說明它承擔的資料責任，再比較適用場景、容量邊界、替代服務、操作成本、案例對照與下一步路由。&lt;/p>
&lt;p>資料庫服務頁的共同讀法是先用 PostgreSQL / MySQL 建立 SQL baseline，再看 managed SQL、KV / document 與 global distributed SQL 如何改變團隊責任。&lt;/p>
&lt;p>資料庫 vendor 文章的撰寫規格見 &lt;a href="https://tarrragon.github.io/blog/backend/01-database/vendor-article-spec/" data-link-title="資料庫 Vendor 文章撰寫規格" data-link-desc="把 PostgreSQL 與 MySQL batch 的正文經驗整理成資料庫 vendor overview、deep article 與 migration playbook 的撰寫規格">資料庫 Vendor 文章撰寫規格&lt;/a>。該規格把 PostgreSQL / MySQL batch 的經驗整理成三個 surface：vendor overview 負責第一輪服務判斷，deep article 負責單一機制的操作與除錯，migration playbook 負責跨 vendor、跨 topology 或跨 operational model 的階段化變更。&lt;/p>
&lt;h2 id="教學順序同步">教學順序同步&lt;/h2>
&lt;p>資料庫服務頁的教學順序是先建立 SQL baseline，再處理 embedded / local、document / KV、managed SQL 與 global distributed SQL。這個順序對齊 checkout E1：讀者先理解正式狀態、transaction、schema migration 與 query boundary，再比較哪些服務把操作責任交給平台，哪些服務改變資料模型或一致性成本。&lt;/p>
&lt;h2 id="t1-服務頁大綱">T1 服務頁大綱&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>服務&lt;/th>
 &lt;th>類型&lt;/th>
 &lt;th>頁面要回答的核心問題&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/01-database/vendors/postgresql/" data-link-title="PostgreSQL" data-link-desc="多用途 OLTP 主流關聯式資料庫、MVCC、豐富 SQL 特性、是 Aurora / Cosmos DB / Spanner / CockroachDB / Aurora DSQL 的相容目標">PostgreSQL&lt;/a>&lt;/td>
 &lt;td>SQL baseline&lt;/td>
 &lt;td>transaction、schema、query、extension 與操作成熟度如何成為比較基準&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/01-database/vendors/mysql/" data-link-title="MySQL" data-link-desc="高併發網路服務常用關聯式資料庫、Vitess / PlanetScale 分片生態、GitHub / Shopify / Facebook 規模驗證">MySQL&lt;/a>&lt;/td>
 &lt;td>SQL baseline&lt;/td>
 &lt;td>高併發 OLTP、replication、online schema change 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">sharding&lt;/a> 生態如何取捨&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/01-database/vendors/sqlite/" data-link-title="SQLite" data-link-desc="embedded、單檔案、test / CLI / edge 場景的標準選擇、近年因 Cloudflare D1 / Turso 等服務復興">SQLite&lt;/a>&lt;/td>
 &lt;td>Embedded SQL&lt;/td>
 &lt;td>單機正式狀態、測試資料、edge / local DB 與低操作成本如何成立&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/01-database/vendors/mongodb/" data-link-title="MongoDB" data-link-desc="Document database 代表、Atlas managed、跨雲可用、許多大規模平台從 MongoDB 起家">MongoDB&lt;/a>&lt;/td>
 &lt;td>Document database&lt;/td>
 &lt;td>document shape、index、schema flexibility 與 transaction 邊界如何治理&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/01-database/vendors/dynamodb/" data-link-title="DynamoDB" data-link-desc="AWS managed key-value、partition-based scaling、9000 萬 RPS sustained 實戰證據">DynamoDB&lt;/a>&lt;/td>
 &lt;td>Managed KV / document&lt;/td>
 &lt;td>partition key、access pattern、容量計費與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/hot-partition/" data-link-title="Hot Partition" data-link-desc="說明分散式 KV / OLTP 中、單一 partition 流量遠超其他的容量問題">hot partition&lt;/a> 如何設計&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/01-database/vendors/aurora/" data-link-title="AWS Aurora" data-link-desc="AWS managed PostgreSQL / MySQL、storage / compute 分離、&amp;#43;75% 效能改善的 production 證據">Aurora&lt;/a>&lt;/td>
 &lt;td>Managed SQL&lt;/td>
 &lt;td>storage / compute 分離、failover、replica 與 AWS operation model 如何轉移責任&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/01-database/vendors/spanner/" data-link-title="Google Cloud Spanner" data-link-desc="全球分散式 strong-consistency OLTP、TrueTime API、線性擴展到 10 億 req/sec">Spanner&lt;/a>&lt;/td>
 &lt;td>Global SQL&lt;/td>
 &lt;td>TrueTime、strong consistency、multi-region latency 與成本如何取捨&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/01-database/vendors/cosmosdb/" data-link-title="Azure Cosmos DB" data-link-desc="全球分散式 multi-model DB、5 個 consistency levels、Microsoft 自家 dogfood 證據">Cosmos DB&lt;/a>&lt;/td>
 &lt;td>Global multi-model&lt;/td>
 &lt;td>consistency level、API model、partition 與 Azure 約束如何影響架構&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/01-database/vendors/cockroachdb/" data-link-title="CockroachDB" data-link-desc="分散式 SQL、PostgreSQL 相容、跨區強一致、Spanner 的開源 / 跨雲替代">CockroachDB&lt;/a>&lt;/td>
 &lt;td>Distributed SQL&lt;/td>
 &lt;td>SQL 相容、range lease、multi-region 與自管 / managed 邊界如何判斷&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="內容覆蓋進度">內容覆蓋進度&lt;/h2>
&lt;p>每個 vendor 服務頁下會擴充兩類文章：deep article（vendor 自身的配置、故障、容量、走 &lt;a href="https://tarrragon.github.io/blog/posts/vendor-%E6%B7%B1%E5%BA%A6%E6%8A%80%E8%A1%93%E6%96%87%E7%AB%A0%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84%E5%90%8C-vendor-%E7%B3%BB%E5%88%97%E7%9A%84%E9%96%8B%E5%A0%B4%E8%BC%AA%E6%9B%BF%E9%A9%97%E8%AD%89/" data-link-title="Vendor 深度技術文章方法論的演化紀錄：同 vendor 系列的開場輪替驗證" data-link-desc="vendor overview 飽和後要寫單一功能深度文章、需要選題與結構依據時回來。這套方法論的驗證來源與 cadence variant 在高風險場景（同 vendor sub-tool 系列）的實證。">6-section 模板&lt;/a>）跟 migration playbook（跨 vendor 遷移流程、走 &lt;a href="https://tarrragon.github.io/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">6-type 結構&lt;/a>）。「→ X」代表遷移到 X 的 playbook、其他形式代表 same-vendor 的 topology / version / config 變動。&lt;/p></description><content:encoded><![CDATA[<p>資料庫 Vendor 清單的核心責任是把 database 服務名稱放回正式狀態、交易邊界、查詢模型、schema 演進、容量與資料治理的判斷。每個服務頁先說明它承擔的資料責任，再比較適用場景、容量邊界、替代服務、操作成本、案例對照與下一步路由。</p>
<p>資料庫服務頁的共同讀法是先用 PostgreSQL / MySQL 建立 SQL baseline，再看 managed SQL、KV / document 與 global distributed SQL 如何改變團隊責任。</p>
<p>資料庫 vendor 文章的撰寫規格見 <a href="/blog/backend/01-database/vendor-article-spec/" data-link-title="資料庫 Vendor 文章撰寫規格" data-link-desc="把 PostgreSQL 與 MySQL batch 的正文經驗整理成資料庫 vendor overview、deep article 與 migration playbook 的撰寫規格">資料庫 Vendor 文章撰寫規格</a>。該規格把 PostgreSQL / MySQL batch 的經驗整理成三個 surface：vendor overview 負責第一輪服務判斷，deep article 負責單一機制的操作與除錯，migration playbook 負責跨 vendor、跨 topology 或跨 operational model 的階段化變更。</p>
<h2 id="教學順序同步">教學順序同步</h2>
<p>資料庫服務頁的教學順序是先建立 SQL baseline，再處理 embedded / local、document / KV、managed SQL 與 global distributed SQL。這個順序對齊 checkout E1：讀者先理解正式狀態、transaction、schema migration 與 query boundary，再比較哪些服務把操作責任交給平台，哪些服務改變資料模型或一致性成本。</p>
<h2 id="t1-服務頁大綱">T1 服務頁大綱</h2>
<table>
  <thead>
      <tr>
          <th>服務</th>
          <th>類型</th>
          <th>頁面要回答的核心問題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/01-database/vendors/postgresql/" data-link-title="PostgreSQL" data-link-desc="多用途 OLTP 主流關聯式資料庫、MVCC、豐富 SQL 特性、是 Aurora / Cosmos DB / Spanner / CockroachDB / Aurora DSQL 的相容目標">PostgreSQL</a></td>
          <td>SQL baseline</td>
          <td>transaction、schema、query、extension 與操作成熟度如何成為比較基準</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/01-database/vendors/mysql/" data-link-title="MySQL" data-link-desc="高併發網路服務常用關聯式資料庫、Vitess / PlanetScale 分片生態、GitHub / Shopify / Facebook 規模驗證">MySQL</a></td>
          <td>SQL baseline</td>
          <td>高併發 OLTP、replication、online schema change 與 <a href="/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">sharding</a> 生態如何取捨</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/01-database/vendors/sqlite/" data-link-title="SQLite" data-link-desc="embedded、單檔案、test / CLI / edge 場景的標準選擇、近年因 Cloudflare D1 / Turso 等服務復興">SQLite</a></td>
          <td>Embedded SQL</td>
          <td>單機正式狀態、測試資料、edge / local DB 與低操作成本如何成立</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/01-database/vendors/mongodb/" data-link-title="MongoDB" data-link-desc="Document database 代表、Atlas managed、跨雲可用、許多大規模平台從 MongoDB 起家">MongoDB</a></td>
          <td>Document database</td>
          <td>document shape、index、schema flexibility 與 transaction 邊界如何治理</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/01-database/vendors/dynamodb/" data-link-title="DynamoDB" data-link-desc="AWS managed key-value、partition-based scaling、9000 萬 RPS sustained 實戰證據">DynamoDB</a></td>
          <td>Managed KV / document</td>
          <td>partition key、access pattern、容量計費與 <a href="/blog/backend/knowledge-cards/hot-partition/" data-link-title="Hot Partition" data-link-desc="說明分散式 KV / OLTP 中、單一 partition 流量遠超其他的容量問題">hot partition</a> 如何設計</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/01-database/vendors/aurora/" data-link-title="AWS Aurora" data-link-desc="AWS managed PostgreSQL / MySQL、storage / compute 分離、&#43;75% 效能改善的 production 證據">Aurora</a></td>
          <td>Managed SQL</td>
          <td>storage / compute 分離、failover、replica 與 AWS operation model 如何轉移責任</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/01-database/vendors/spanner/" data-link-title="Google Cloud Spanner" data-link-desc="全球分散式 strong-consistency OLTP、TrueTime API、線性擴展到 10 億 req/sec">Spanner</a></td>
          <td>Global SQL</td>
          <td>TrueTime、strong consistency、multi-region latency 與成本如何取捨</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/01-database/vendors/cosmosdb/" data-link-title="Azure Cosmos DB" data-link-desc="全球分散式 multi-model DB、5 個 consistency levels、Microsoft 自家 dogfood 證據">Cosmos DB</a></td>
          <td>Global multi-model</td>
          <td>consistency level、API model、partition 與 Azure 約束如何影響架構</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/01-database/vendors/cockroachdb/" data-link-title="CockroachDB" data-link-desc="分散式 SQL、PostgreSQL 相容、跨區強一致、Spanner 的開源 / 跨雲替代">CockroachDB</a></td>
          <td>Distributed SQL</td>
          <td>SQL 相容、range lease、multi-region 與自管 / managed 邊界如何判斷</td>
      </tr>
  </tbody>
</table>
<h2 id="內容覆蓋進度">內容覆蓋進度</h2>
<p>每個 vendor 服務頁下會擴充兩類文章：deep article（vendor 自身的配置、故障、容量、走 <a href="/blog/posts/vendor-%E6%B7%B1%E5%BA%A6%E6%8A%80%E8%A1%93%E6%96%87%E7%AB%A0%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84%E5%90%8C-vendor-%E7%B3%BB%E5%88%97%E7%9A%84%E9%96%8B%E5%A0%B4%E8%BC%AA%E6%9B%BF%E9%A9%97%E8%AD%89/" data-link-title="Vendor 深度技術文章方法論的演化紀錄：同 vendor 系列的開場輪替驗證" data-link-desc="vendor overview 飽和後要寫單一功能深度文章、需要選題與結構依據時回來。這套方法論的驗證來源與 cadence variant 在高風險場景（同 vendor sub-tool 系列）的實證。">6-section 模板</a>）跟 migration playbook（跨 vendor 遷移流程、走 <a href="/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">6-type 結構</a>）。「→ X」代表遷移到 X 的 playbook、其他形式代表 same-vendor 的 topology / version / config 變動。</p>
<table>
  <thead>
      <tr>
          <th>Vendor</th>
          <th>Deep article</th>
          <th>Migration playbook</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="postgresql/">PostgreSQL</a></td>
          <td><a href="postgresql/autovacuum-tuning/">autovacuum-tuning</a> / <a href="postgresql/connection-scaling/">connection-scaling</a> / <a href="postgresql/connection-pooler-comparison/">connection-pooler-comparison</a> / <a href="postgresql/pgbouncer-config/">pgbouncer-config</a> / <a href="postgresql/declarative-partitioning/">declarative-partitioning</a> / <a href="postgresql/pg-partman-advanced/">pg-partman-advanced</a> / <a href="postgresql/logical-replication-debezium/">logical-replication-debezium</a> / <a href="postgresql/logical-decoding-plugins/">logical-decoding-plugins</a> / <a href="postgresql/replication-topology/">replication-topology</a> / <a href="postgresql/replication-slot-management/">replication-slot-management</a> / <a href="postgresql/patroni-ha/">patroni-ha</a> / <a href="postgresql/pitr-wal-archiving/">pitr-wal-archiving</a> / <a href="postgresql/cross-region-dr/">cross-region-dr</a> / <a href="postgresql/online-schema-change/">online-schema-change</a> / <a href="postgresql/query-optimization/">query-optimization</a> / <a href="postgresql/index-selection/">index-selection</a> / <a href="postgresql/mvcc-lock-model/">mvcc-lock-model</a> / <a href="postgresql/citus-distributed/">citus-distributed</a> / <a href="postgresql/bdr-multi-master/">bdr-multi-master</a> / <a href="postgresql/sql-features-baseline/">sql-features-baseline</a> / <a href="postgresql/jsonb-deep-dive/">jsonb-deep-dive</a> / <a href="postgresql/extension-ecosystem/">extension-ecosystem</a> / <a href="postgresql/specialized-pg-variants/">specialized-pg-variants</a> / <a href="postgresql/timescaledb-deep-dive/">timescaledb-deep-dive</a> / <a href="postgresql/pgvector-deep-dive/">pgvector-deep-dive</a> / <a href="postgresql/postgis-deep-dive/">postgis-deep-dive</a> / <a href="postgresql/full-text-search/">full-text-search</a> / <a href="postgresql/security-rls-audit-logging/">security-rls-audit-logging</a> / <a href="postgresql/managed-pg-comparison/">managed-pg-comparison</a> / <a href="postgresql/aurora-io-optimized-cost/">aurora-io-optimized-cost</a> / <a href="postgresql/developer-dba-responsibility-split/">developer-dba-responsibility-split</a></td>
          <td><a href="postgresql/major-version-upgrade/">major-version-upgrade</a> / <a href="postgresql/migrate-to-aurora/">→ Aurora</a> / <a href="postgresql/migrate-to-aurora-dsql/">→ Aurora DSQL</a> / <a href="postgresql/migrate-to-cockroachdb/">→ CockroachDB</a> / <a href="postgresql/migrate-to-yugabytedb-tidb/">→ YugabyteDB / TiDB</a> / <a href="postgresql/multi-region-gdpr-rollout/">multi-region-gdpr-rollout</a> / <a href="postgresql/partition-redesign/">partition-redesign</a></td>
      </tr>
      <tr>
          <td><a href="mysql/">MySQL</a></td>
          <td><a href="mysql/replication-topology/">replication-topology</a> / <a href="mysql/multi-source-replication/">multi-source-replication</a> / <a href="mysql/group-replication/">group-replication</a> / <a href="mysql/orchestrator-failover/">orchestrator-failover</a> / <a href="mysql/online-schema-change-tools/">online-schema-change-tools</a> / <a href="mysql/proxysql-config/">proxysql-config</a> / <a href="mysql/innodb-tuning/">innodb-tuning</a> / <a href="mysql/cross-buffer-memory-contention/">cross-buffer-memory-contention</a> / <a href="mysql/metadata-lock-deep-dive/">metadata-lock-deep-dive</a> / <a href="mysql/lock-contention/">lock-contention</a> / <a href="mysql/binlog-cdc/">binlog-cdc</a> / <a href="mysql/pitr-backup/">pitr-backup</a> / <a href="mysql/vitess-sharding/">vitess-sharding</a> / <a href="mysql/partitioning/">partitioning</a> / <a href="mysql/query-optimization/">query-optimization</a> / <a href="mysql/modern-sql-features/">modern-sql-features</a> / <a href="mysql/document-store-x-protocol/">document-store-x-protocol</a> / <a href="mysql/heatwave-olap-addon/">heatwave-olap-addon</a> / <a href="mysql/encryption-tls-key-management/">encryption-tls-key-management</a> / <a href="mysql/audit-log-siem/">audit-log-siem</a></td>
          <td><a href="mysql/major-version-upgrade/">major-version-upgrade</a> / <a href="mysql/migrate-to-postgresql/">→ PostgreSQL</a> / <a href="mysql/migrate-to-aurora/">→ Aurora</a> / <a href="mysql/migrate-to-planetscale/">→ PlanetScale</a> / <a href="mysql/migrate-vitess-to-planetscale/">Vitess → PlanetScale</a></td>
      </tr>
      <tr>
          <td><a href="sqlite/">SQLite</a></td>
          <td><a href="sqlite/file-lifecycle-backup-boundary/">file-lifecycle-backup-boundary</a> / <a href="sqlite/wal-concurrency-locking/">wal-concurrency-locking</a> / <a href="sqlite/pragma-tuning-performance/">pragma-tuning-performance</a> / <a href="sqlite/schema-migration-versioning/">schema-migration-versioning</a> / <a href="sqlite/sql-dialect-index-limits/">sql-dialect-index-limits</a> / <a href="sqlite/observability-runbook/">observability-runbook</a> / <a href="sqlite/test-fixture-best-practice/">test-fixture-best-practice</a> / <a href="sqlite/mobile-desktop-embedded-store/">mobile-desktop-embedded-store</a> / <a href="sqlite/local-first-sync-boundary/">local-first-sync-boundary</a> / <a href="sqlite/litestream-litefs-replication/">litestream-litefs-replication</a> / <a href="sqlite/d1-turso-libsql-comparison/">d1-turso-libsql-comparison</a></td>
          <td><a href="sqlite/migrate-from-postgresql-simplification/">migrate-from-postgresql-simplification</a> / <a href="sqlite/migrate-to-postgresql/">→ PostgreSQL</a> / <a href="sqlite/migrate-to-d1-turso/">→ D1 / Turso</a></td>
      </tr>
      <tr>
          <td><a href="mongodb/">MongoDB</a></td>
          <td><a href="mongodb/schema-design-pattern/">schema-design-pattern</a> (SSoT Frame 1 MongoDB 適用度) / <a href="mongodb/shard-key-selection/">shard-key-selection</a> / <a href="mongodb/replica-set-read-preference/">replica-set-read-preference</a> / <a href="mongodb/aggregation-pipeline-optimization/">aggregation-pipeline-optimization</a> / <a href="mongodb/change-streams-kafka/">change-streams-kafka</a> / <a href="mongodb/connection-management-and-cache-layer/">connection-management-and-cache-layer</a></td>
          <td><a href="mongodb/migrate-to-atlas/">→ Atlas</a> / <a href="mongodb/shard-expansion-multi-dc/">shard-expansion-multi-dc</a></td>
      </tr>
      <tr>
          <td><a href="dynamodb/">DynamoDB</a></td>
          <td><a href="dynamodb/single-table-design-pattern/">single-table-design-pattern</a> (SSoT Frame 1 DynamoDB 適用度) / <a href="dynamodb/partition-key-antipatterns/">partition-key-antipatterns</a> / <a href="dynamodb/gsi-lsi-design/">gsi-lsi-design</a> / <a href="dynamodb/on-demand-vs-provisioned/">on-demand-vs-provisioned</a> (SSoT Frame 8 event-driven scaling) / <a href="dynamodb/global-tables-conflict/">global-tables-conflict</a> / <a href="dynamodb/consistency-model-optimization/">consistency-model-optimization</a> / <a href="dynamodb/transactions-conditional-writes/">transactions-conditional-writes</a> / <a href="dynamodb/dax-caching-strategy/">dax-caching-strategy</a> / <a href="dynamodb/streams-lambda-event-driven/">streams-lambda-event-driven</a> / <a href="dynamodb/ttl-data-lifecycle/">ttl-data-lifecycle</a></td>
          <td><a href="dynamodb/migrate-rds-mongodb-to-dynamodb/">migrate-rds-mongodb-to-dynamodb</a> (Type E paradigm shift)</td>
      </tr>
      <tr>
          <td><a href="aurora/">Aurora</a></td>
          <td><a href="aurora/storage-architecture/">storage-architecture</a> / <a href="aurora/cross-az-failover-rto/">cross-az-failover-rto</a> / <a href="aurora/read-replica-scaling/">read-replica-scaling</a> (SSoT Aurora fleet 治理 + Frame 8 共寫) / <a href="aurora/global-database-multi-region/">global-database-multi-region</a> / <a href="aurora/migrate-from-self-managed-pg-mysql/">migrate-from-self-managed-pg-mysql</a> / <a href="aurora/serverless-v2-scaling/">serverless-v2-scaling</a> / <a href="aurora/multi-cluster-business-split/">multi-cluster-business-split</a> / <a href="aurora/rds-proxy-connection-pooling/">rds-proxy-connection-pooling</a> / <a href="aurora/aurora-vs-dsql-tradeoff/">aurora-vs-dsql-tradeoff</a></td>
          <td>—</td>
      </tr>
      <tr>
          <td><a href="spanner/">Spanner</a></td>
          <td><a href="spanner/truetime-api-depth/">truetime-api-depth</a> / <a href="spanner/consistency-models-comparison/">consistency-models-comparison</a> / <a href="spanner/schema-migration-interleaved-tables/">schema-migration-interleaved-tables</a> / <a href="spanner/migrate-from-cloud-sql-pg/">migrate-from-cloud-sql-pg</a> / <a href="spanner/change-streams-cdc/">change-streams-cdc</a> / <a href="spanner/postgresql-dialect/">postgresql-dialect</a> / <a href="spanner/spanner-graph/">spanner-graph</a> / <a href="spanner/bigquery-federation/">bigquery-federation</a></td>
          <td>—</td>
      </tr>
      <tr>
          <td><a href="cosmosdb/">Cosmos DB</a></td>
          <td><a href="cosmosdb/consistency-levels-engineering/">consistency-levels-engineering</a> / <a href="cosmosdb/partition-key-design/">partition-key-design</a> / <a href="cosmosdb/ru-cost-model-sizing/">ru-cost-model-sizing</a> / <a href="cosmosdb/mongodb-api-vs-sql-api/">mongodb-api-vs-sql-api</a> (SSoT Document 三型遷移 + Cosmos Frame 1) / <a href="cosmosdb/multi-region-write-conflict/">multi-region-write-conflict</a> (SSoT Strong + multi-region 互斥) / <a href="cosmosdb/change-feed-cdc/">change-feed-cdc</a> / <a href="cosmosdb/stored-procedure-trigger/">stored-procedure-trigger</a> / <a href="cosmosdb/cosmos-for-postgresql/">cosmos-for-postgresql</a> / <a href="cosmosdb/synapse-link-federation/">synapse-link-federation</a></td>
          <td><a href="cosmosdb/migrate-from-mongodb-cassandra/">migrate-from-mongodb-cassandra</a> (Type B drop-in / Type E paradigm)</td>
      </tr>
      <tr>
          <td><a href="cockroachdb/">CockroachDB</a></td>
          <td><a href="cockroachdb/hlc-raft-consensus/">hlc-raft-consensus</a> / <a href="cockroachdb/survival-goals/">survival-goals</a> / <a href="cockroachdb/transaction-retry-pattern/">transaction-retry-pattern</a> / <a href="cockroachdb/locality-aware-schema/">locality-aware-schema</a> / <a href="cockroachdb/aurora-dsql-spanner-decision-tree/">aurora-dsql-spanner-decision-tree</a> (SSoT DB4 entry + cluster boundary 顆粒) / <a href="cockroachdb/multi-region-table-config/">multi-region-table-config</a> / <a href="cockroachdb/cloud-serverless/">cloud-serverless</a></td>
          <td>—</td>
      </tr>
  </tbody>
</table>
<p>DB1（PostgreSQL / MySQL）/ DB2（SQLite）/ DB3（MongoDB / DynamoDB）/ DB4（Aurora / Spanner / Cosmos DB / CockroachDB）四批 vendor 的 deep article 都已鋪滿。DB3 跟 DB4 batch 共新增 31 篇 deep article + 1 篇 DB3 entry article（<a href="db3-vendor-selection/">db3-vendor-selection</a>）+ 1 篇 DB4 entry article（<a href="cockroachdb/aurora-dsql-spanner-decision-tree/">cockroachdb/aurora-dsql-spanner-decision-tree</a>）。PostgreSQL 與 MySQL 也保留 hands-on 子目錄，集中放可重現的 lab；hands-on 與覆蓋表互補、不重複列在這張表。SQLite 的 <a href="sqlite/teaching-structure/">teaching-structure</a> 是該服務章節群的大綱、不視為 deep article。後續批次 backlog 見下方各 vendor _index.md 的「後續擴充（仍待補）」段。</p>
<p>DB5 batch（BaaS 資料層）新增 <a href="firestore/">Firestore</a> overview（serverless document、client 直連 + Security Rules、查詢邊界、realtime / offline）+ <a href="firestore/migrate-to-relational/">→ 自建 relational</a> 遷移 playbook（Type E paradigm shift、存取模型反轉）+ 4 篇 deep article：<a href="firestore/security-rules-authz-modeling/">Security Rules 授權建模</a>、<a href="firestore/distributed-counter-high-frequency-write/">distributed counter 高頻寫入</a>、<a href="firestore/denormalization-fanout-consistency/">document 反正規化與一致性</a>、<a href="firestore/realtime-listener-fanout-cost/">realtime listener 扇出與成本</a>。這批的定位是把 BaaS（<a href="/blog/backend/knowledge-cards/baas/" data-link-title="BaaS（Backend as a Service）" data-link-desc="說明把認證、資料庫、檔案儲存、推播打包成現成模組、由前端 SDK 直連的後端交付形態">Firebase</a> / Firestore）的資料層面放回 vendor 視角：要不要採用 BaaS 這種交付形態本身是 <a href="/blog/backend/00-service-selection/delivery-mode-selection/" data-link-title="0.21 交付形態選型：從全託管到自建的光譜與邊界" data-link-desc="在進入資料庫、快取與部署選型之前、先判斷服務該用託管平台（Wix / Shopify / Google Sites）、辦公生態自動化（Apps Script）、BaaS（Firebase）、半託管 CMS（WordPress）還是自建、並為日後遷往自建保留可遷出路徑">0.21</a> / <a href="/blog/backend/00-service-selection/capability-buy-vs-build/" data-link-title="0.22 能力級買 vs 建：feature-as-a-service 與 BaaS bundle 選型" data-link-desc="在交付形態決定整個系統要不要自建之後、逐能力判斷該外包還是自建：辨識 managed 基礎設施、feature SaaS 與 BaaS bundle 三種外包深度、no-code 到 dev-tool 的服務光譜、買 vs 建判準與權重浮動、整合接縫與遷出代價">0.22</a> 的選型層決策、本模組只負責「Firestore 作為 document store 承擔什麼狀態責任、撞牆後如何遷往自建」。deep article 章節群讀法見 <a href="firestore/#deep-article-%e7%ab%a0%e7%af%80%e7%be%a4">Firestore overview 的 Deep article 章節群段</a>；<a href="firestore/hands-on/">hands-on 章節群</a> 提供 3 個 Firebase Emulator lab（emulator quickstart、Security Rules 測試、distributed counter）。Supabase 的資料層不另開 vendor 頁 — 它的 Postgres 面寫在 <a href="postgresql/managed-pg-comparison/">managed-pg-comparison</a> 的比較表一行、選型層錨點在 <a href="/blog/backend/00-service-selection/capability-buy-vs-build/" data-link-title="0.22 能力級買 vs 建：feature-as-a-service 與 BaaS bundle 選型" data-link-desc="在交付形態決定整個系統要不要自建之後、逐能力判斷該外包還是自建：辨識 managed 基礎設施、feature SaaS 與 BaaS bundle 三種外包深度、no-code 到 dev-tool 的服務光譜、買 vs 建判準與權重浮動、整合接縫與遷出代價">0.22</a>（見該章「跨能力 bundle 的特殊判讀」段）、SSoT 不重複。</p>
<h2 id="cross-vendor-ssot-主寫位置">Cross-vendor SSoT 主寫位置</h2>
<p>跨 vendor 共寫 frame 在多篇 deep article 之間 cross-link、但每個 frame 都有 <em>單一 SSoT 主寫位置</em>、其他 article 只 cross-link 不重複展開。讀者從 entry article 或覆蓋表進來時、可以直接跳對應 SSoT 看完整推導：</p>
<ul>
<li><strong>Aurora fleet 治理（business sharding / microservice / 合規 driver）</strong>：<a href="aurora/read-replica-scaling/">aurora/read-replica-scaling</a> — DraftKings 200 cluster fleet、何時拆 cluster vs 加 replica 的 6 條判讀順序</li>
<li><strong>CockroachDB cluster boundary 顆粒（per-app cluster vs 邏輯一個 cluster）</strong>：<a href="cockroachdb/aurora-dsql-spanner-decision-tree/">cockroachdb/aurora-dsql-spanner-decision-tree</a> — 已選 CockroachDB 後的拓樸決策、跟 vendor 選擇分流</li>
<li><strong>Strong consistency + multi-region write 互斥（CAP 硬約束）</strong>：<a href="cosmosdb/multi-region-write-conflict/">cosmosdb/multi-region-write-conflict</a> — 跨 region active-active write 三家機制對比 + Cosmos DB Strong / multi-region 互斥根因</li>
<li><strong>Document model 三型遷移（保留 / 換託管 / 換 vendor 保留 model）</strong>：<a href="cosmosdb/mongodb-api-vs-sql-api/">cosmosdb/mongodb-api-vs-sql-api</a> — wire compat ≠ 100% 行為相同、dual-write per query pattern 驗證</li>
<li><strong>Frame 1 vendor 適用度判讀 — MongoDB</strong>：<a href="mongodb/schema-design-pattern/">mongodb/schema-design-pattern</a> — document workload 適配軸 + aggregate root 邊界</li>
<li><strong>Frame 1 vendor 適用度判讀 — DynamoDB</strong>：<a href="dynamodb/single-table-design-pattern/">dynamodb/single-table-design-pattern</a> — KV 4 軸前置判讀 + access pattern 穩定度</li>
<li><strong>Frame 1 vendor 適用度判讀 — Cosmos DB</strong>：<a href="cosmosdb/mongodb-api-vs-sql-api/">cosmosdb/mongodb-api-vs-sql-api</a> — Cosmos DB 跟 Document migration 同 SSoT、API model 四層 framing</li>
<li><strong>Frame 8 event-driven scaling 5 模式（surge / burst / sustained / scheduled / predictive）</strong>：<a href="dynamodb/on-demand-vs-provisioned/">dynamodb/on-demand-vs-provisioned</a> + <a href="aurora/read-replica-scaling/">aurora/read-replica-scaling</a> 共寫 — Tixcraft 6750x spike / Capcom predictive / DraftKings scheduled 三 case 對應</li>
<li><strong>Partition / shard key 可逆性跨 vendor 對照</strong>：<a href="db3-vendor-selection/">db3-vendor-selection</a> 三 vendor 對比 10 軸 + 軸的延伸子段「Partition / shard key 可逆性」 — MongoDB（4.4+ 可改）/ DynamoDB（backfill 可改）/ Cosmos DB（不可改）三家不在同一光譜、決定 selection 階段 access pattern audit 嚴格度。3 篇 deep article（mongodb/shard-key-selection、dynamodb/partition-key-antipatterns、cosmosdb/partition-key-design）各自展開本 vendor 內部設計、不重複跨 vendor 對照</li>
</ul>
<p>DB3 / DB4 entry article（<a href="db3-vendor-selection/">db3-vendor-selection</a> + <a href="cockroachdb/aurora-dsql-spanner-decision-tree/">cockroachdb/aurora-dsql-spanner-decision-tree</a>）承擔 <em>跨 vendor 選型 driver path</em> SSoT、上列 SSoT 是 <em>單一 frame 跨 vendor 共寫</em> 主寫位置、兩層 SSoT 不重疊。</p>
<h2 id="cross-vendor-entry-point">Cross-vendor entry point</h2>
<p>跨 vendor 選型不該直接讀單一 vendor overview — 先用 entry article 判斷 driver path、再進個別 vendor 深度：</p>
<ul>
<li><strong>DB3 入口</strong>（document / KV / multi-model 三家對比）：<a href="db3-vendor-selection/">db3-vendor-selection</a> — workload shape × access pattern × consistency 三軸前置判讀、migration path 三型、federated DB 視角、三 vendor 對比 10 軸</li>
<li><strong>DB4 入口</strong>（distributed SQL 三家對比）：<a href="cockroachdb/aurora-dsql-spanner-decision-tree/">cockroachdb/aurora-dsql-spanner-decision-tree</a> — 撞牆訊號分型（DoorDash 單主寫入 / Netflix Cassandra 缺口 / Hard Rock 合規驅動）+ 七問題決策樹（跨雲 / 雲商生態 / 風險預算 / PG 相容 / 管理負擔 / team size / vendor sizing barrier）</li>
</ul>
<p>兩個 entry 都用 case-driven driver 視角切入、不只是「特性對照表」— 讀者帶具體的 production 訊號（撞牆 case / 資料形狀變化 / 合規邊界）進來、entry 才會指向正確的 vendor。</p>
<h2 id="服務頁教學功能">服務頁教學功能</h2>
<p>資料庫服務頁的共同檢查軸是教學功能，而非固定章節順序。PostgreSQL、SQLite、MongoDB、DynamoDB 與 Spanner 的服務對象不同，頁面可以用不同標題展開，但都要讓讀者學會正式狀態、資料形狀、交易需求、查詢邊界、容量與操作責任的判斷。</p>
<table>
  <thead>
      <tr>
          <th>教學功能</th>
          <th>資料庫服務頁要交付的內容</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>服務定位</td>
          <td>它是正式狀態、embedded store、managed SQL、KV/document 還是 distributed SQL</td>
      </tr>
      <tr>
          <td>學習目標</td>
          <td>讀者能判斷資料形狀、交易需求、查詢邊界、容量與操作責任</td>
      </tr>
      <tr>
          <td>最短判讀路徑</td>
          <td>用 transaction、ad-hoc query、local state 或 global consistency 快速定位</td>
      </tr>
      <tr>
          <td>日常操作與決策形狀</td>
          <td>schema migration、backup、restore、replica、index、connection、quota</td>
      </tr>
      <tr>
          <td>核心取捨</td>
          <td>SQL baseline、managed SQL、KV/document、<a href="/blog/backend/knowledge-cards/distributed-sql/" data-link-title="Distributed SQL" data-link-desc="把 SQL 與交易語意延伸到多節點與多區域的資料庫形態">distributed SQL</a> 的機會成本</td>
      </tr>
      <tr>
          <td>進階主題</td>
          <td><a href="/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">sharding</a>、multi-region、online migration、CDC、global consistency</td>
      </tr>
      <tr>
          <td>失敗快速判讀</td>
          <td>connection exhaustion、slow query、lock、<a href="/blog/backend/knowledge-cards/replication-lag/" data-link-title="Replication Lag" data-link-desc="說明資料副本落後正式來源多久，以及它如何影響讀取正確性">replication lag</a>、<a href="/blog/backend/knowledge-cards/hot-partition/" data-link-title="Hot Partition" data-link-desc="說明分散式 KV / OLTP 中、單一 partition 流量遠超其他的容量問題">hot partition</a></td>
      </tr>
      <tr>
          <td>替代服務路由</td>
          <td>query 變複雜時回 SQL、replay 需求轉 event log、全文搜尋轉 search</td>
      </tr>
      <tr>
          <td>Scope boundary</td>
          <td>ORM 語法、語言 driver 細節、完整 DBA 手冊</td>
      </tr>
      <tr>
          <td>案例回寫與下一步路由</td>
          <td>回到 01 主章、09 capacity case、08 incident decision log</td>
      </tr>
  </tbody>
</table>
<h2 id="後續擴充">後續擴充</h2>
<table>
  <thead>
      <tr>
          <th>層級</th>
          <th>候選服務</th>
          <th>補充理由</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>T2</td>
          <td>Oracle Database、Microsoft SQL Server、MariaDB</td>
          <td>enterprise / commercial SQL 與 MySQL 相鄰生態</td>
      </tr>
      <tr>
          <td>T2</td>
          <td>PlanetScale / Vitess、TiDB、YugabyteDB、Neon、Supabase、Azure SQL Hyperscale</td>
          <td><a href="/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">sharding</a>、<a href="/blog/backend/knowledge-cards/distributed-sql/" data-link-title="Distributed SQL" data-link-desc="把 SQL 與交易語意延伸到多節點與多區域的資料庫形態">distributed SQL</a>、serverless Postgres、managed SQL</td>
      </tr>
      <tr>
          <td>T2</td>
          <td>Apache Cassandra、ScyllaDB</td>
          <td>wide-column、high-write（mobile / serverless document 已由 <a href="firestore/">Firestore</a> 覆蓋）</td>
      </tr>
      <tr>
          <td>T2</td>
          <td>OpenSearch / Elasticsearch</td>
          <td>search engine 與 log / document search 邊界</td>
      </tr>
      <tr>
          <td>T3</td>
          <td>ClickHouse、BigQuery、Snowflake</td>
          <td>OLAP / analytics，先作相鄰路由</td>
      </tr>
      <tr>
          <td>T3</td>
          <td>CouchDB、Couchbase</td>
          <td>sync / document database 的特殊場景</td>
      </tr>
  </tbody>
</table>
<p>主流覆蓋檢查的重點是區分 OLTP、search 與 analytics。Oracle、SQL Server、MariaDB 補 enterprise SQL；Cassandra / ScyllaDB 補 wide-column；OpenSearch / Elasticsearch 補 search；ClickHouse、BigQuery、Snowflake 先保留 analytics 路由，避免資料庫服務頁承擔整個數倉教材。</p>
<h2 id="撰寫批次">撰寫批次</h2>
<table>
  <thead>
      <tr>
          <th>批次</th>
          <th>服務頁</th>
          <th>撰寫目的</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>DB1</td>
          <td>PostgreSQL / MySQL</td>
          <td>建立 SQL baseline、transaction、schema evolution 與 connection 判準</td>
      </tr>
      <tr>
          <td>DB2</td>
          <td>SQLite</td>
          <td>建立 embedded / local formal state 與低操作成本邊界</td>
      </tr>
      <tr>
          <td>DB3</td>
          <td>MongoDB / DynamoDB</td>
          <td>建立 document / KV、access pattern、partition 與資料形狀判準</td>
      </tr>
      <tr>
          <td>DB4</td>
          <td>Aurora / Spanner / Cosmos DB / CockroachDB</td>
          <td>建立 managed / global SQL、多 region、consistency 與 vendor 約束</td>
      </tr>
      <tr>
          <td>DB5</td>
          <td>Firestore</td>
          <td>建立 BaaS 資料層視角：client 直連 document store 與撞牆後遷往自建</td>
      </tr>
  </tbody>
</table>
<h2 id="db3--db4-batch-完成紀錄">DB3 / DB4 batch 完成紀錄</h2>
<p>DB3 / DB4 batch（MongoDB / DynamoDB / Cosmos DB / Aurora / Spanner / CockroachDB 共 6 vendor、31 篇新 deep article + 2 篇 cross-vendor entry article）已完成。完成順序如下：</p>
<ul>
<li><strong>DB3</strong>：MongoDB（schema design / shard key / read preference / aggregation / change streams / connection management 6 篇）+ DynamoDB（single-table / partition key 反模式 / GSI-LSI / capacity mode / global tables 5 篇）+ Cosmos DB（consistency / partition key / RU 成本 / MongoDB API / multi-region 5 篇）+ DB3 entry article（document / KV / multi-model 三方選型）</li>
<li><strong>DB4</strong>：Aurora（storage / failover / replica scaling / global database / migration 5 篇）+ Spanner（TrueTime / consistency models / schema migration / Cloud SQL migration 4 篇）+ CockroachDB（HLC-Raft / survival goals / retry pattern / locality / DB4 decision tree 5 篇、含 DB4 entry article）</li>
</ul>
<p>各 vendor 後續 backlog（Atlas 遷移、PITR restore drill、Serverless 等）見各 vendor _index.md「後續擴充（仍待補）」段。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/01-database/schema-design/" data-link-title="1.2 Schema Design 與資料建模" data-link-desc="整理 table、index、key、partition、denormalization 與命名規則">1.2 schema design 與資料建模</a></li>
<li>上游：<a href="/blog/backend/01-database/transaction-boundary/" data-link-title="1.3 Transaction 與一致性邊界" data-link-desc="交易邊界、isolation level、retry 策略、distributed transaction（2PC、Saga）與跨 region 強一致取捨">1.3 transaction 與一致性邊界</a></li>
<li>服務路徑：<a href="/blog/backend/01-database/schema-migration-rollout-evidence/" data-link-title="1.7 Schema Migration Rollout 證據（Schema Migration Rollout Evidence）實作示範" data-link-desc="以訂單付款狀態欄位演進示範 schema migration 如何產出 evidence、release gate 與 incident decision log。">1.7 Schema Migration Rollout 證據</a></li>
</ul>
]]></content:encoded></item><item><title>可靠性 Vendor 清單</title><link>https://tarrragon.github.io/blog/backend/06-reliability/vendors/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/06-reliability/vendors/</guid><description>&lt;p>可靠性 Vendor 清單的核心責任是把工具名稱放回 verification loop、release gate、fault injection、SLO governance 與 evidence handoff 的判斷。每個服務頁先回答它承擔哪一種可靠性驗證責任，再討論整合成本、風險控制、artifact 與案例回寫。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/cases/" data-link-title="可靠性服務案例庫" data-link-desc="按服務組織的 SRE 實踐案例庫，累積架構脈絡與工程文化">cases/&lt;/a> 是不同維度。Cases 是教學案例來源，vendors 是把驗證流程落地的工具入口。&lt;/p>
&lt;h2 id="讀法">讀法&lt;/h2>
&lt;p>可靠性工具要從驗證流程進入。讀者如果要處理 release gate，先回到 &lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/release-gate/" data-link-title="6.8 Release Gate 與變更節奏" data-link-desc="把驗證、migration、相容性納入放行判準">6.8 Release Gate&lt;/a>；如果要處理 load test 與 regression，先回到 &lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/performance-regression-gate/" data-link-title="6.13 Performance Regression Gate" data-link-desc="把效能 baseline 從一次性壓測變成持續對齊的 release gate，涵蓋 baseline 設定、判讀方法、variance 控制與退化定位">6.13 Performance Regression Gate&lt;/a>；如果要處理 chaos，先回到 &lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/experiment-safety-boundary/" data-link-title="6.20 Experiment Safety Boundary" data-link-desc="定義 chaos、load test、DR drill 的 [blast radius](/backend/knowledge-cards/blast-radius/)、停止條件與權限約束">6.20 Experiment Safety Boundary&lt;/a>。&lt;/p>
&lt;h2 id="教學順序同步">教學順序同步&lt;/h2>
&lt;p>可靠性工具頁的教學順序是先建立 CI / release gate，再進入 load test、chaos / fault injection 與 SLO governance。這個順序對齊 checkout E5：讀者先理解變更如何被放行與停止，再比較哪些工具產生 regression evidence、experiment evidence 與 error budget evidence。&lt;/p>
&lt;h2 id="t1-服務頁大綱">T1 服務頁大綱&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>服務&lt;/th>
 &lt;th>類型&lt;/th>
 &lt;th>頁面要回答的核心問題&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/vendors/github-actions/" data-link-title="GitHub Actions" data-link-desc="GitHub 原生 CI/CD、PR check、deploy gate">GitHub Actions&lt;/a>&lt;/td>
 &lt;td>CI/CD&lt;/td>
 &lt;td>workflow、environment、artifact 與 approval gate 如何支援 release evidence&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/vendors/circleci/" data-link-title="CircleCI" data-link-desc="CI/CD 平台、強 cache 與 parallelism">CircleCI&lt;/a>&lt;/td>
 &lt;td>CI/CD&lt;/td>
 &lt;td>pipeline、orb、parallelism 與 context 權限如何取捨&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/vendors/k6/" data-link-title="k6" data-link-desc="現代 load test、JS scripting、Grafana Labs">k6&lt;/a>&lt;/td>
 &lt;td>Load test&lt;/td>
 &lt;td>scenario、threshold 與 CI gate 如何支援可靠性驗證&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/vendors/gatling/" data-link-title="Gatling" data-link-desc="JVM-based load test、Scala / Java / Kotlin DSL、強型別 scenario、HAR-driven recording">Gatling&lt;/a>&lt;/td>
 &lt;td>Load test&lt;/td>
 &lt;td>JVM simulation、injection profile 與 report 如何支援 regression gate&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/vendors/jmeter/" data-link-title="Apache JMeter" data-link-desc="老牌 load test 工具、GUI &amp;#43; plugins">JMeter&lt;/a>&lt;/td>
 &lt;td>Load test&lt;/td>
 &lt;td>GUI plan、protocol sampler 與既有測試資產如何治理&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/vendors/locust/" data-link-title="Locust" data-link-desc="Python-based load test、distributed、易擴展">Locust&lt;/a>&lt;/td>
 &lt;td>Load test&lt;/td>
 &lt;td>Python user behavior 與 distributed worker 如何支援自訂 workload&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/vendors/chaos-mesh/" data-link-title="Chaos Mesh" data-link-desc="Kubernetes-native chaos engineering（CNCF incubating）">Chaos Mesh&lt;/a>&lt;/td>
 &lt;td>Chaos engineering&lt;/td>
 &lt;td>Kubernetes-native fault injection 與 experiment scope 如何控制&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/vendors/litmuschaos/" data-link-title="LitmusChaos" data-link-desc="Kubernetes chaos engineering 平台（CNCF graduated）">LitmusChaos&lt;/a>&lt;/td>
 &lt;td>Chaos engineering&lt;/td>
 &lt;td>chaos workflow、hub 與 Kubernetes 實驗治理如何取捨&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/vendors/gremlin/" data-link-title="Gremlin" data-link-desc="商業 chaos engineering 平台、跨平台與 GameDay">Gremlin&lt;/a>&lt;/td>
 &lt;td>Chaos platform&lt;/td>
 &lt;td>商業 chaos 平台、blast radius guardrail 與審計如何支援成熟團隊&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/vendors/toxiproxy/" data-link-title="Toxiproxy" data-link-desc="TCP-level fault injection proxy（Shopify 開源）">Toxiproxy&lt;/a>&lt;/td>
 &lt;td>Fault injection&lt;/td>
 &lt;td>TCP fault、local integration test 與 dependency failure 如何模擬&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/vendors/nobl9/" data-link-title="Nobl9" data-link-desc="SLO platform、跨 data source、企業 SLO 治理">Nobl9&lt;/a>&lt;/td>
 &lt;td>SLO platform&lt;/td>
 &lt;td>SLO、error budget、alerting 與 governance 如何整合&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/vendors/sloth/" data-link-title="Sloth" data-link-desc="OSS SLO generator for Prometheus">Sloth&lt;/a>&lt;/td>
 &lt;td>SLO generator&lt;/td>
 &lt;td>OpenSLO / Prometheus rule 生成如何降低 SLO 維護成本&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="內容覆蓋進度">內容覆蓋進度&lt;/h2>
&lt;p>每個 vendor 服務頁下會擴充兩類文章：deep article（vendor 自身的配置、故障、容量、走 &lt;a href="https://tarrragon.github.io/blog/posts/vendor-%E6%B7%B1%E5%BA%A6%E6%8A%80%E8%A1%93%E6%96%87%E7%AB%A0%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84%E5%90%8C-vendor-%E7%B3%BB%E5%88%97%E7%9A%84%E9%96%8B%E5%A0%B4%E8%BC%AA%E6%9B%BF%E9%A9%97%E8%AD%89/" data-link-title="Vendor 深度技術文章方法論的演化紀錄：同 vendor 系列的開場輪替驗證" data-link-desc="vendor overview 飽和後要寫單一功能深度文章、需要選題與結構依據時回來。這套方法論的驗證來源與 cadence variant 在高風險場景（同 vendor sub-tool 系列）的實證。">6-section 模板&lt;/a>）跟 migration playbook（跨 vendor 遷移流程、走 &lt;a href="https://tarrragon.github.io/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">6-type 結構&lt;/a>）。「← X」代表從 X 遷入。&lt;/p></description><content:encoded><![CDATA[<p>可靠性 Vendor 清單的核心責任是把工具名稱放回 verification loop、release gate、fault injection、SLO governance 與 evidence handoff 的判斷。每個服務頁先回答它承擔哪一種可靠性驗證責任，再討論整合成本、風險控制、artifact 與案例回寫。</p>
<p>跟 <a href="/blog/backend/06-reliability/cases/" data-link-title="可靠性服務案例庫" data-link-desc="按服務組織的 SRE 實踐案例庫，累積架構脈絡與工程文化">cases/</a> 是不同維度。Cases 是教學案例來源，vendors 是把驗證流程落地的工具入口。</p>
<h2 id="讀法">讀法</h2>
<p>可靠性工具要從驗證流程進入。讀者如果要處理 release gate，先回到 <a href="/blog/backend/06-reliability/release-gate/" data-link-title="6.8 Release Gate 與變更節奏" data-link-desc="把驗證、migration、相容性納入放行判準">6.8 Release Gate</a>；如果要處理 load test 與 regression，先回到 <a href="/blog/backend/06-reliability/performance-regression-gate/" data-link-title="6.13 Performance Regression Gate" data-link-desc="把效能 baseline 從一次性壓測變成持續對齊的 release gate，涵蓋 baseline 設定、判讀方法、variance 控制與退化定位">6.13 Performance Regression Gate</a>；如果要處理 chaos，先回到 <a href="/blog/backend/06-reliability/experiment-safety-boundary/" data-link-title="6.20 Experiment Safety Boundary" data-link-desc="定義 chaos、load test、DR drill 的 [blast radius](/backend/knowledge-cards/blast-radius/)、停止條件與權限約束">6.20 Experiment Safety Boundary</a>。</p>
<h2 id="教學順序同步">教學順序同步</h2>
<p>可靠性工具頁的教學順序是先建立 CI / release gate，再進入 load test、chaos / fault injection 與 SLO governance。這個順序對齊 checkout E5：讀者先理解變更如何被放行與停止，再比較哪些工具產生 regression evidence、experiment evidence 與 error budget evidence。</p>
<h2 id="t1-服務頁大綱">T1 服務頁大綱</h2>
<table>
  <thead>
      <tr>
          <th>服務</th>
          <th>類型</th>
          <th>頁面要回答的核心問題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/06-reliability/vendors/github-actions/" data-link-title="GitHub Actions" data-link-desc="GitHub 原生 CI/CD、PR check、deploy gate">GitHub Actions</a></td>
          <td>CI/CD</td>
          <td>workflow、environment、artifact 與 approval gate 如何支援 release evidence</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/06-reliability/vendors/circleci/" data-link-title="CircleCI" data-link-desc="CI/CD 平台、強 cache 與 parallelism">CircleCI</a></td>
          <td>CI/CD</td>
          <td>pipeline、orb、parallelism 與 context 權限如何取捨</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/06-reliability/vendors/k6/" data-link-title="k6" data-link-desc="現代 load test、JS scripting、Grafana Labs">k6</a></td>
          <td>Load test</td>
          <td>scenario、threshold 與 CI gate 如何支援可靠性驗證</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/06-reliability/vendors/gatling/" data-link-title="Gatling" data-link-desc="JVM-based load test、Scala / Java / Kotlin DSL、強型別 scenario、HAR-driven recording">Gatling</a></td>
          <td>Load test</td>
          <td>JVM simulation、injection profile 與 report 如何支援 regression gate</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/06-reliability/vendors/jmeter/" data-link-title="Apache JMeter" data-link-desc="老牌 load test 工具、GUI &#43; plugins">JMeter</a></td>
          <td>Load test</td>
          <td>GUI plan、protocol sampler 與既有測試資產如何治理</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/06-reliability/vendors/locust/" data-link-title="Locust" data-link-desc="Python-based load test、distributed、易擴展">Locust</a></td>
          <td>Load test</td>
          <td>Python user behavior 與 distributed worker 如何支援自訂 workload</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/06-reliability/vendors/chaos-mesh/" data-link-title="Chaos Mesh" data-link-desc="Kubernetes-native chaos engineering（CNCF incubating）">Chaos Mesh</a></td>
          <td>Chaos engineering</td>
          <td>Kubernetes-native fault injection 與 experiment scope 如何控制</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/06-reliability/vendors/litmuschaos/" data-link-title="LitmusChaos" data-link-desc="Kubernetes chaos engineering 平台（CNCF graduated）">LitmusChaos</a></td>
          <td>Chaos engineering</td>
          <td>chaos workflow、hub 與 Kubernetes 實驗治理如何取捨</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/06-reliability/vendors/gremlin/" data-link-title="Gremlin" data-link-desc="商業 chaos engineering 平台、跨平台與 GameDay">Gremlin</a></td>
          <td>Chaos platform</td>
          <td>商業 chaos 平台、blast radius guardrail 與審計如何支援成熟團隊</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/06-reliability/vendors/toxiproxy/" data-link-title="Toxiproxy" data-link-desc="TCP-level fault injection proxy（Shopify 開源）">Toxiproxy</a></td>
          <td>Fault injection</td>
          <td>TCP fault、local integration test 與 dependency failure 如何模擬</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/06-reliability/vendors/nobl9/" data-link-title="Nobl9" data-link-desc="SLO platform、跨 data source、企業 SLO 治理">Nobl9</a></td>
          <td>SLO platform</td>
          <td>SLO、error budget、alerting 與 governance 如何整合</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/06-reliability/vendors/sloth/" data-link-title="Sloth" data-link-desc="OSS SLO generator for Prometheus">Sloth</a></td>
          <td>SLO generator</td>
          <td>OpenSLO / Prometheus rule 生成如何降低 SLO 維護成本</td>
      </tr>
  </tbody>
</table>
<h2 id="內容覆蓋進度">內容覆蓋進度</h2>
<p>每個 vendor 服務頁下會擴充兩類文章：deep article（vendor 自身的配置、故障、容量、走 <a href="/blog/posts/vendor-%E6%B7%B1%E5%BA%A6%E6%8A%80%E8%A1%93%E6%96%87%E7%AB%A0%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84%E5%90%8C-vendor-%E7%B3%BB%E5%88%97%E7%9A%84%E9%96%8B%E5%A0%B4%E8%BC%AA%E6%9B%BF%E9%A9%97%E8%AD%89/" data-link-title="Vendor 深度技術文章方法論的演化紀錄：同 vendor 系列的開場輪替驗證" data-link-desc="vendor overview 飽和後要寫單一功能深度文章、需要選題與結構依據時回來。這套方法論的驗證來源與 cadence variant 在高風險場景（同 vendor sub-tool 系列）的實證。">6-section 模板</a>）跟 migration playbook（跨 vendor 遷移流程、走 <a href="/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">6-type 結構</a>）。「← X」代表從 X 遷入。</p>
<table>
  <thead>
      <tr>
          <th>Vendor</th>
          <th>Deep article</th>
          <th>Migration playbook</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="github-actions/">GitHub Actions</a></td>
          <td><a href="github-actions/environment-protection-and-oidc-cloud-auth/">Environment Protection + OIDC</a></td>
          <td><a href="github-actions/migrate-from-jenkins/">← Jenkins</a></td>
      </tr>
      <tr>
          <td><a href="k6/">k6</a></td>
          <td><a href="k6/threshold-ci-gate-and-scenario-design/">Threshold CI Gate + Scenario</a></td>
          <td>—</td>
      </tr>
      <tr>
          <td><a href="chaos-mesh/">Chaos Mesh</a></td>
          <td><a href="chaos-mesh/workflow-experiment-scope-and-steady-state-probe/">Workflow + Scope + Steady State Probe</a></td>
          <td>—</td>
      </tr>
      <tr>
          <td><a href="sloth/">Sloth</a></td>
          <td><a href="sloth/slo-yaml-and-multi-burn-rate-alert-generation/">SLO YAML + Multi-burn-rate Alert</a></td>
          <td>—</td>
      </tr>
  </tbody>
</table>
<p>其他 T1 vendor（CircleCI / Gatling / JMeter / Locust / LitmusChaos / Gremlin / Toxiproxy / Nobl9）的 deep article 尚未開始。對應的 backlog 議題見上方「T1 服務頁大綱」段每個服務頁要回答的核心問題、跟各 vendor <code>_index.md</code> 的「預計實作話題」段。</p>
<h2 id="服務頁撰寫欄位">服務頁撰寫欄位</h2>
<table>
  <thead>
      <tr>
          <th>欄位</th>
          <th>可靠性服務頁要保留的問題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>服務責任</td>
          <td>它承擔 CI gate、load test、chaos、fault injection 還是 SLO governance</td>
      </tr>
      <tr>
          <td>適用壓力</td>
          <td>release frequency、failure mode、experiment safety、SLO maturity 哪個壓力最明顯</td>
      </tr>
      <tr>
          <td>替代邊界</td>
          <td>CI 平台、09 壓測工具、chaos 平台、SLO tool 的機會成本</td>
      </tr>
      <tr>
          <td>操作成本</td>
          <td>runner、secret、artifact、test data、blast radius、experiment approval</td>
      </tr>
      <tr>
          <td>Evidence</td>
          <td>workflow run、test report、experiment result、SLO burn、gate decision</td>
      </tr>
      <tr>
          <td>案例回寫</td>
          <td>Google SRE、Netflix chaos、release gate 與 replay 案例如何提供判準</td>
      </tr>
  </tbody>
</table>
<h2 id="服務頁標準章節">服務頁標準章節</h2>
<table>
  <thead>
      <tr>
          <th>章節</th>
          <th>可靠性工具頁要補的內容</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>工具定位</td>
          <td>它是 CI gate、load test、chaos platform、fault injection 還是 SLO governance</td>
      </tr>
      <tr>
          <td>本章目標</td>
          <td>讀者能判斷該工具能產生哪種 verification evidence 與 gate decision</td>
      </tr>
      <tr>
          <td>最短判讀路徑</td>
          <td>用「要擋 release、驗證負載、注入失敗、追 SLO」快速定位工具類型</td>
      </tr>
      <tr>
          <td>日常操作與決策形狀</td>
          <td>workflow、runner、secret、artifact、approval、experiment scope、SLO rule</td>
      </tr>
      <tr>
          <td>核心取捨表</td>
          <td>CI 平台、09 壓測工具、chaos 平台、SLO 平台的機會成本</td>
      </tr>
      <tr>
          <td>進階主題</td>
          <td>self-hosted runner、blast radius guardrail、error budget policy、audit</td>
      </tr>
      <tr>
          <td>排錯與失敗快速判讀</td>
          <td>flaky job、missing artifact、unsafe experiment、false SLO alert、runner bottleneck</td>
      </tr>
      <tr>
          <td>何時改走其他服務</td>
          <td>容量模型回 09、觀測資料回 04、事故協作回 08、部署控制回 05</td>
      </tr>
      <tr>
          <td>不在本頁內的主題</td>
          <td>完整 pipeline cookbook、每個 test framework、所有 chaos experiment 範本</td>
      </tr>
      <tr>
          <td>案例回寫與下一步路由</td>
          <td>回到 06 cases、6.8 release gate、6.20 experiment safety boundary</td>
      </tr>
  </tbody>
</table>
<h2 id="跨-vendor-議題對照">跨 vendor 議題對照</h2>
<p>本模組 12 個 vendor 跨 4 個 sub-category（CI/CD / load test / chaos / SLO）、不是同類選一。對照表用「橫向 reliability gate 議題」標明每個議題在哪個 sub-category 落地。</p>
<table>
  <thead>
      <tr>
          <th>議題</th>
          <th>GH Actions</th>
          <th>CircleCI</th>
          <th>k6</th>
          <th>Gatling</th>
          <th>JMeter</th>
          <th>Locust</th>
          <th>Chaos Mesh</th>
          <th>Litmus</th>
          <th>Gremlin</th>
          <th>Toxiproxy</th>
          <th>Nobl9</th>
          <th>Sloth</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>主責任</td>
          <td>CI gate</td>
          <td>CI gate</td>
          <td>Load test</td>
          <td>Load test</td>
          <td>Load test</td>
          <td>Load test</td>
          <td>K8s chaos</td>
          <td>K8s chaos</td>
          <td>跨平台 chaos</td>
          <td>TCP fault</td>
          <td>SLO governance</td>
          <td>SLO generator</td>
      </tr>
      <tr>
          <td>整合 CI gate</td>
          <td>原生</td>
          <td>原生</td>
          <td>threshold</td>
          <td>assertion</td>
          <td>non-GUI mode</td>
          <td>headless</td>
          <td>workflow</td>
          <td>workflow</td>
          <td>scenario</td>
          <td>client SDK</td>
          <td>error budget</td>
          <td>rule gen</td>
      </tr>
      <tr>
          <td>配置模式</td>
          <td>YAML</td>
          <td>YAML</td>
          <td>JS</td>
          <td>Scala / Java</td>
          <td>XML GUI</td>
          <td>Python</td>
          <td>CRD</td>
          <td>CRD</td>
          <td>UI / API</td>
          <td>API</td>
          <td>YAML / UI</td>
          <td>YAML</td>
      </tr>
      <tr>
          <td>環境支援</td>
          <td>GitHub-hosted</td>
          <td>cross-VCS</td>
          <td>OSS / Cloud</td>
          <td>OSS / Enterprise</td>
          <td>OSS</td>
          <td>OSS</td>
          <td>K8s only</td>
          <td>K8s only</td>
          <td>跨平台</td>
          <td>TCP layer</td>
          <td>multi-source</td>
          <td>Prometheus</td>
      </tr>
      <tr>
          <td>進階產出</td>
          <td>matrix / OIDC</td>
          <td>parallelism</td>
          <td>extension</td>
          <td>feeder</td>
          <td>plugins</td>
          <td>distributed</td>
          <td>scope control</td>
          <td>ChaosHub</td>
          <td>GameDay</td>
          <td>toxic types</td>
          <td>composite SLO</td>
          <td>multi-burn</td>
      </tr>
      <tr>
          <td>商業 / 開源</td>
          <td>商業 + SaaS</td>
          <td>商業 + SaaS</td>
          <td>OSS + Cloud</td>
          <td>OSS + Enterprise</td>
          <td>OSS</td>
          <td>OSS</td>
          <td>OSS</td>
          <td>OSS + 商業</td>
          <td>商業 SaaS</td>
          <td>OSS</td>
          <td>商業 SaaS</td>
          <td>OSS</td>
      </tr>
      <tr>
          <td>主討論案例</td>
          <td>待補</td>
          <td>待補</td>
          <td>待補</td>
          <td>待補</td>
          <td>待補</td>
          <td>待補</td>
          <td>Netflix/Google</td>
          <td>待補</td>
          <td>待補</td>
          <td>Shopify</td>
          <td>Google SRE</td>
          <td>待補</td>
      </tr>
  </tbody>
</table>
<p>對照表的用途有三：</p>
<ul>
<li>寫某 vendor 頁時、看相同 sub-category 對手如何處理同一議題</li>
<li>讀者組 reliability stack：CI gate + load test + chaos + SLO 各選 1</li>
<li>評估 OSS vs 商業 trade-off</li>
</ul>
<p>下面 4 段把對照表的 sub-category 展開、不是每行都展開。</p>
<h3 id="ci-gategithub-actions--circleci">CI gate（GitHub Actions / CircleCI）</h3>
<p>CI gate 是 release 前最後一道驗證、決定哪些工件可發。<strong>GitHub Actions</strong> 跟 GitHub 深度整合（PR check / environment protection / OIDC cloud auth）、marketplace action 生態最廣；<strong>CircleCI</strong> 強進階 cache + parallelism + macOS / GPU resource class、cross-VCS（GitHub / Bitbucket / GitLab）。</p>
<p>選型判讀：GitHub-hosted + 普通用 → GitHub Actions；極致 build speed / macOS / 跨 VCS → CircleCI；複雜 DAG → Tekton / Argo。</p>
<h3 id="load-testk6--gatling--jmeter--locust">Load test（k6 / Gatling / JMeter / Locust）</h3>
<p>Load test 提供 performance regression evidence。差異主要在語言生態：<strong>k6</strong> JS / CLI-first / Grafana 生態；<strong>Gatling</strong> Scala / Java / 強型別 / 複雜 scenario；<strong>JMeter</strong> GUI / 老牌 / 多 protocol；<strong>Locust</strong> Python / 自訂邏輯極彈性。</p>
<p>選型判讀：CI-first JS → k6；JVM 生態 → Gatling；既有 .jmx 資產 → JMeter；Python 團隊 / 複雜邏輯 → Locust。詳見 <a href="/blog/backend/09-performance-capacity/" data-link-title="模組九：效能工程與容量規劃" data-link-desc="把『目前配置能撐多少、要加多少機器』變成可量化、可驗證、可改進的工程流程">9 performance capacity 模組</a> 的 capacity planning 角度。</p>
<h3 id="chaos-engineeringchaos-mesh--litmuschaos--gremlin--toxiproxy">Chaos engineering（Chaos Mesh / LitmusChaos / Gremlin / Toxiproxy）</h3>
<p>Chaos 工具按 scope 跟運維模式分四類：<strong>Chaos Mesh</strong> K8s-native CRD-driven 多 fault types；<strong>LitmusChaos</strong> K8s + ChaosHub experiment 庫；<strong>Gremlin</strong> 商業 SaaS / 跨平台 / GameDay；<strong>Toxiproxy</strong> TCP-level / integration test 用。</p>
<p>選型判讀：K8s production + OSS → Chaos Mesh / Litmus；跨平台 + 商業 → Gremlin；CI integration test → Toxiproxy。對應 <a href="/blog/backend/06-reliability/experiment-safety-boundary/" data-link-title="6.20 Experiment Safety Boundary" data-link-desc="定義 chaos、load test、DR drill 的 [blast radius](/backend/knowledge-cards/blast-radius/)、停止條件與權限約束">6.20 Experiment Safety Boundary</a> 的 blast radius 設計。</p>
<h3 id="slo-governancenobl9--sloth">SLO governance（Nobl9 / Sloth）</h3>
<p>SLO 工具按 source 跟運維模式分兩類：<strong>Nobl9</strong> 商業 SaaS / multi-source / OpenSLO 主導 / 企業 governance；<strong>Sloth</strong> OSS / Prometheus-only / 產生 Prometheus rules。</p>
<p>選型判讀：multi-source / SaaS / governance → Nobl9；Prometheus-only / OSS → Sloth / Pyrra；vendor 內建夠 → Datadog SLO / Grafana SLO / Honeycomb SLO。對應 <a href="/blog/backend/knowledge-cards/burn-rate/" data-link-title="Burn Rate" data-link-desc="說明 error budget 消耗速度如何支援告警與事故分級">knowledge cards burn-rate</a>。</p>
<h2 id="撰寫批次">撰寫批次</h2>
<table>
  <thead>
      <tr>
          <th>批次</th>
          <th>服務頁</th>
          <th>撰寫目的</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>R1</td>
          <td>GitHub Actions / CircleCI</td>
          <td>建立 CI gate、artifact 與 approval baseline</td>
      </tr>
      <tr>
          <td>R2</td>
          <td>k6 / Gatling / JMeter / Locust</td>
          <td>建立 release gate 視角的 load test 與 regression evidence</td>
      </tr>
      <tr>
          <td>R3</td>
          <td>Chaos Mesh / LitmusChaos / Gremlin / Toxiproxy</td>
          <td>建立 fault injection 與 experiment safety 對照</td>
      </tr>
      <tr>
          <td>R4</td>
          <td>Nobl9 / Sloth</td>
          <td>建立 SLO governance、error budget 與 rule generation 判準</td>
      </tr>
  </tbody>
</table>
<h2 id="後續候選">後續候選</h2>
<table>
  <thead>
      <tr>
          <th>類型</th>
          <th>候選服務</th>
          <th>寫作重點</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>CI/CD</td>
          <td>GitLab CI、Jenkins、Buildkite、Tekton、Harness、Azure Pipelines</td>
          <td>self-hosted runner、enterprise workflow、pipeline governance</td>
      </tr>
      <tr>
          <td>Load / browser gate</td>
          <td>Artillery、Grafana k6 Cloud、BlazeMeter、Playwright、Cypress</td>
          <td>managed runner、browser flow、release gate、cost</td>
      </tr>
      <tr>
          <td>Chaos / fault</td>
          <td>AWS Fault Injection Service、Azure Chaos Studio、Pumba</td>
          <td>cloud-native fault、container fault、blast radius</td>
      </tr>
      <tr>
          <td>SLO</td>
          <td>Pyrra、OpenSLO、Keptn</td>
          <td>Prometheus-native SLO、portable SLO spec、quality gate</td>
      </tr>
      <tr>
          <td>Policy / audit</td>
          <td>Steampipe、Conftest</td>
          <td>compliance query、control evidence、change review</td>
      </tr>
  </tbody>
</table>
<p>主流覆蓋檢查的重點是分開 CI gate、performance gate、chaos gate、SLO gate 與 policy gate。CI 工具負責 release artifact 與 approval；load / browser 工具負責 regression evidence；chaos 工具負責 failure mode evidence；SLO 工具負責 error budget governance；policy 工具負責控制證據。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/06-reliability/release-gate/" data-link-title="6.8 Release Gate 與變更節奏" data-link-desc="把驗證、migration、相容性納入放行判準">6.8 Release Gate</a></li>
<li>上游：<a href="/blog/backend/06-reliability/experiment-safety-boundary/" data-link-title="6.20 Experiment Safety Boundary" data-link-desc="定義 chaos、load test、DR drill 的 [blast radius](/backend/knowledge-cards/blast-radius/)、停止條件與權限約束">6.20 Experiment Safety Boundary</a></li>
<li>服務路徑：<a href="/blog/backend/06-reliability/provider-dependency-release-gate/" data-link-title="6.25 Provider Dependency Release Gate 實作示範" data-link-desc="以 payment provider 變更示範 release gate 如何結合 evidence、stop condition 與 rollback window。">6.25 Provider Dependency Release Gate 實作示範</a></li>
<li>平行：<a href="/blog/backend/09-performance-capacity/vendors/" data-link-title="效能與容量工具清單" data-link-desc="整理效能工程、容量規劃、壓測、production replay 與 profiling 工具的服務責任與選型路由">09 效能與容量工具清單</a></li>
</ul>
]]></content:encoded></item><item><title>事故處理 Vendor 清單</title><link>https://tarrragon.github.io/blog/backend/08-incident-response/vendors/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/08-incident-response/vendors/</guid><description>&lt;p>事故處理 Vendor 清單的核心責任是把工具名稱放回 alert routing、incident command、stakeholder communication、status page、postmortem 與 learning loop 的判斷。每個服務頁先回答它承擔事故流程的哪一段，再討論輪值成本、協作模型、稽核證據與案例回寫。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/cases/" data-link-title="事故處理服務案例庫" data-link-desc="按服務組織的公開事故案例庫，累積架構脈絡與 longitudinal pattern">cases/&lt;/a> 是不同維度。Cases 是公開事故案例來源，vendors 是把事故流程落地的工具入口。&lt;/p>
&lt;h2 id="讀法">讀法&lt;/h2>
&lt;p>事故工具要從協作節點進入。讀者如果要處理告警與輪值，先回到 &lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/drills-and-oncall-readiness/" data-link-title="8.6 演練與值班能力建設" data-link-desc="用演練與值班訓練提升事故反應品質">Drills and On-call Readiness&lt;/a>；如果要處理決策紀錄，先回到 &lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/incident-decision-log/" data-link-title="8.19 Incident Decision Log" data-link-desc="把事中假設、決策、證據、回退條件與責任人留下可復盤紀錄">8.19 Incident Decision Log&lt;/a>；如果要處理復盤與回寫，先回到 &lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/incident-evidence-write-back/" data-link-title="8.22 Incident Evidence Write-back" data-link-desc="把事故證據、決策與復盤結論回寫到 observability、reliability 與 runbook">8.22 Incident Evidence Write-back&lt;/a>。&lt;/p>
&lt;h2 id="教學順序同步">教學順序同步&lt;/h2>
&lt;p>事故工具頁的教學順序是先建立 paging，再進入 incident command、status page 與 learning loop。這個順序對齊 checkout E4 與 E6：讀者先理解告警如何找到 owner，再比較事故指揮、對外更新、復盤學習與 action item 如何回寫到 release gate、資安控制與服務路徑。&lt;/p>
&lt;h2 id="t1-服務頁大綱">T1 服務頁大綱&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>服務&lt;/th>
 &lt;th>類型&lt;/th>
 &lt;th>頁面要回答的核心問題&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/vendors/pagerduty/" data-link-title="PagerDuty" data-link-desc="On-call / alerting 主流 SaaS、IR 平台演化">PagerDuty&lt;/a>&lt;/td>
 &lt;td>On-call platform&lt;/td>
 &lt;td>escalation、service ownership、runbook 與 incident object 如何支援輪值&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/vendors/opsgenie/" data-link-title="Opsgenie" data-link-desc="Atlassian on-call、跟 Jira / Statuspage 套件整合、JSM Premium migration 議題">Opsgenie&lt;/a>&lt;/td>
 &lt;td>On-call platform&lt;/td>
 &lt;td>Atlassian workflow、routing rule 與 team schedule 如何取捨&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/vendors/grafana-oncall/" data-link-title="Grafana OnCall" data-link-desc="OSS-friendly on-call 平台、Grafana Labs 維護、Apache 2.0、Grafana IRM bundle 把 OnCall &amp;#43; Incident 收進一個 alert-to-resolve 流程">Grafana OnCall&lt;/a>&lt;/td>
 &lt;td>OSS / Grafana on-call&lt;/td>
 &lt;td>alert grouping、Grafana integration 與自管成本如何取捨&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/vendors/incident-io/" data-link-title="incident.io" data-link-desc="Slack-native IR 平台、整合 paging / response / retro">incident.io&lt;/a>&lt;/td>
 &lt;td>IR platform&lt;/td>
 &lt;td>Slack-native command、timeline、action 與 post-incident workflow 如何支援協作&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/vendors/firehydrant/" data-link-title="FireHydrant" data-link-desc="IR &amp;#43; retrospective 平台、Slack / Teams 整合、service catalog &amp;#43; runbook automation 為核心">FireHydrant&lt;/a>&lt;/td>
 &lt;td>IR platform&lt;/td>
 &lt;td>service catalog、runbook、retrospective 與 automation 如何整合&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/vendors/rootly/" data-link-title="Rootly" data-link-desc="IR 自動化平台、no-code workflow &amp;#43; AI investigation、Slack-native &amp;#43; 200&amp;#43; integration">Rootly&lt;/a>&lt;/td>
 &lt;td>IR automation&lt;/td>
 &lt;td>Slack workflow、status update、task automation 與 Jira / Linear handoff 如何取捨&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/vendors/atlassian-statuspage/" data-link-title="Atlassian Statuspage" data-link-desc="公開狀態頁 SaaS、Atlassian 出品、enterprise polish &amp;#43; Atlassian 生態整合、subscriber notification &amp;#43; component dependency 是核心責任">Atlassian Statuspage&lt;/a>&lt;/td>
 &lt;td>Status page&lt;/td>
 &lt;td>component、subscriber、incident update 與 stakeholder communication 如何管理&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/vendors/instatus/" data-link-title="Instatus" data-link-desc="輕量 status page SaaS、現代 UI、價格敏感替代">Instatus&lt;/a>&lt;/td>
 &lt;td>Status page&lt;/td>
 &lt;td>輕量 status page、custom domain 與低操作成本如何取捨&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/vendors/jeli/" data-link-title="Jeli" data-link-desc="Post-incident learning 平台、2023 被 PagerDuty 收購、強調 interview-driven narrative 而非 timeline-only retro">Jeli&lt;/a>&lt;/td>
 &lt;td>Learning platform&lt;/td>
 &lt;td>postmortem、interview、timeline 與 learning review 如何支援組織學習&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="內容覆蓋進度">內容覆蓋進度&lt;/h2>
&lt;p>每個 vendor 服務頁下會擴充兩類文章：deep article（vendor 自身的配置、故障、容量、走 &lt;a href="https://tarrragon.github.io/blog/posts/vendor-%E6%B7%B1%E5%BA%A6%E6%8A%80%E8%A1%93%E6%96%87%E7%AB%A0%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84%E5%90%8C-vendor-%E7%B3%BB%E5%88%97%E7%9A%84%E9%96%8B%E5%A0%B4%E8%BC%AA%E6%9B%BF%E9%A9%97%E8%AD%89/" data-link-title="Vendor 深度技術文章方法論的演化紀錄：同 vendor 系列的開場輪替驗證" data-link-desc="vendor overview 飽和後要寫單一功能深度文章、需要選題與結構依據時回來。這套方法論的驗證來源與 cadence variant 在高風險場景（同 vendor sub-tool 系列）的實證。">6-section 模板&lt;/a>）跟 migration playbook（跨 vendor 遷移流程、走 &lt;a href="https://tarrragon.github.io/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">6-type 結構&lt;/a>）。「→ X」代表遷移到 X 的 playbook、「← X」代表從 X 遷入。&lt;/p></description><content:encoded><![CDATA[<p>事故處理 Vendor 清單的核心責任是把工具名稱放回 alert routing、incident command、stakeholder communication、status page、postmortem 與 learning loop 的判斷。每個服務頁先回答它承擔事故流程的哪一段，再討論輪值成本、協作模型、稽核證據與案例回寫。</p>
<p>跟 <a href="/blog/backend/08-incident-response/cases/" data-link-title="事故處理服務案例庫" data-link-desc="按服務組織的公開事故案例庫，累積架構脈絡與 longitudinal pattern">cases/</a> 是不同維度。Cases 是公開事故案例來源，vendors 是把事故流程落地的工具入口。</p>
<h2 id="讀法">讀法</h2>
<p>事故工具要從協作節點進入。讀者如果要處理告警與輪值，先回到 <a href="/blog/backend/08-incident-response/drills-and-oncall-readiness/" data-link-title="8.6 演練與值班能力建設" data-link-desc="用演練與值班訓練提升事故反應品質">Drills and On-call Readiness</a>；如果要處理決策紀錄，先回到 <a href="/blog/backend/08-incident-response/incident-decision-log/" data-link-title="8.19 Incident Decision Log" data-link-desc="把事中假設、決策、證據、回退條件與責任人留下可復盤紀錄">8.19 Incident Decision Log</a>；如果要處理復盤與回寫，先回到 <a href="/blog/backend/08-incident-response/incident-evidence-write-back/" data-link-title="8.22 Incident Evidence Write-back" data-link-desc="把事故證據、決策與復盤結論回寫到 observability、reliability 與 runbook">8.22 Incident Evidence Write-back</a>。</p>
<h2 id="教學順序同步">教學順序同步</h2>
<p>事故工具頁的教學順序是先建立 paging，再進入 incident command、status page 與 learning loop。這個順序對齊 checkout E4 與 E6：讀者先理解告警如何找到 owner，再比較事故指揮、對外更新、復盤學習與 action item 如何回寫到 release gate、資安控制與服務路徑。</p>
<h2 id="t1-服務頁大綱">T1 服務頁大綱</h2>
<table>
  <thead>
      <tr>
          <th>服務</th>
          <th>類型</th>
          <th>頁面要回答的核心問題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/08-incident-response/vendors/pagerduty/" data-link-title="PagerDuty" data-link-desc="On-call / alerting 主流 SaaS、IR 平台演化">PagerDuty</a></td>
          <td>On-call platform</td>
          <td>escalation、service ownership、runbook 與 incident object 如何支援輪值</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/08-incident-response/vendors/opsgenie/" data-link-title="Opsgenie" data-link-desc="Atlassian on-call、跟 Jira / Statuspage 套件整合、JSM Premium migration 議題">Opsgenie</a></td>
          <td>On-call platform</td>
          <td>Atlassian workflow、routing rule 與 team schedule 如何取捨</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/08-incident-response/vendors/grafana-oncall/" data-link-title="Grafana OnCall" data-link-desc="OSS-friendly on-call 平台、Grafana Labs 維護、Apache 2.0、Grafana IRM bundle 把 OnCall &#43; Incident 收進一個 alert-to-resolve 流程">Grafana OnCall</a></td>
          <td>OSS / Grafana on-call</td>
          <td>alert grouping、Grafana integration 與自管成本如何取捨</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/08-incident-response/vendors/incident-io/" data-link-title="incident.io" data-link-desc="Slack-native IR 平台、整合 paging / response / retro">incident.io</a></td>
          <td>IR platform</td>
          <td>Slack-native command、timeline、action 與 post-incident workflow 如何支援協作</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/08-incident-response/vendors/firehydrant/" data-link-title="FireHydrant" data-link-desc="IR &#43; retrospective 平台、Slack / Teams 整合、service catalog &#43; runbook automation 為核心">FireHydrant</a></td>
          <td>IR platform</td>
          <td>service catalog、runbook、retrospective 與 automation 如何整合</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/08-incident-response/vendors/rootly/" data-link-title="Rootly" data-link-desc="IR 自動化平台、no-code workflow &#43; AI investigation、Slack-native &#43; 200&#43; integration">Rootly</a></td>
          <td>IR automation</td>
          <td>Slack workflow、status update、task automation 與 Jira / Linear handoff 如何取捨</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/08-incident-response/vendors/atlassian-statuspage/" data-link-title="Atlassian Statuspage" data-link-desc="公開狀態頁 SaaS、Atlassian 出品、enterprise polish &#43; Atlassian 生態整合、subscriber notification &#43; component dependency 是核心責任">Atlassian Statuspage</a></td>
          <td>Status page</td>
          <td>component、subscriber、incident update 與 stakeholder communication 如何管理</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/08-incident-response/vendors/instatus/" data-link-title="Instatus" data-link-desc="輕量 status page SaaS、現代 UI、價格敏感替代">Instatus</a></td>
          <td>Status page</td>
          <td>輕量 status page、custom domain 與低操作成本如何取捨</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/08-incident-response/vendors/jeli/" data-link-title="Jeli" data-link-desc="Post-incident learning 平台、2023 被 PagerDuty 收購、強調 interview-driven narrative 而非 timeline-only retro">Jeli</a></td>
          <td>Learning platform</td>
          <td>postmortem、interview、timeline 與 learning review 如何支援組織學習</td>
      </tr>
  </tbody>
</table>
<h2 id="內容覆蓋進度">內容覆蓋進度</h2>
<p>每個 vendor 服務頁下會擴充兩類文章：deep article（vendor 自身的配置、故障、容量、走 <a href="/blog/posts/vendor-%E6%B7%B1%E5%BA%A6%E6%8A%80%E8%A1%93%E6%96%87%E7%AB%A0%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84%E5%90%8C-vendor-%E7%B3%BB%E5%88%97%E7%9A%84%E9%96%8B%E5%A0%B4%E8%BC%AA%E6%9B%BF%E9%A9%97%E8%AD%89/" data-link-title="Vendor 深度技術文章方法論的演化紀錄：同 vendor 系列的開場輪替驗證" data-link-desc="vendor overview 飽和後要寫單一功能深度文章、需要選題與結構依據時回來。這套方法論的驗證來源與 cadence variant 在高風險場景（同 vendor sub-tool 系列）的實證。">6-section 模板</a>）跟 migration playbook（跨 vendor 遷移流程、走 <a href="/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">6-type 結構</a>）。「→ X」代表遷移到 X 的 playbook、「← X」代表從 X 遷入。</p>
<table>
  <thead>
      <tr>
          <th>Vendor</th>
          <th>Deep article</th>
          <th>Migration playbook</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="pagerduty/">PagerDuty</a></td>
          <td>—</td>
          <td><a href="pagerduty/migrate-to-incident-io/">→ incident.io (Type E)</a></td>
      </tr>
      <tr>
          <td><a href="opsgenie/">Opsgenie</a></td>
          <td>—</td>
          <td><a href="opsgenie/migrate-from-pagerduty/">← PagerDuty (Type A)</a></td>
      </tr>
      <tr>
          <td><a href="atlassian-statuspage/">Atlassian Statuspage</a></td>
          <td>—</td>
          <td><a href="atlassian-statuspage/migrate-to-instatus/">→ Instatus (Type B)</a></td>
      </tr>
  </tbody>
</table>
<p>其他 T1 vendor（Grafana OnCall / incident.io / FireHydrant / Rootly / Instatus / Jeli）尚未開始。對應的 backlog 議題見上方「T1 服務頁大綱」段每個服務頁要回答的核心問題、跟各 vendor <code>_index.md</code> 的「預計實作話題」段。</p>
<h2 id="服務頁撰寫欄位">服務頁撰寫欄位</h2>
<table>
  <thead>
      <tr>
          <th>欄位</th>
          <th>事故處理服務頁要保留的問題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>服務責任</td>
          <td>它承擔 on-call、IR coordination、status communication、postmortem 還是 learning loop</td>
      </tr>
      <tr>
          <td>適用壓力</td>
          <td>alert volume、team count、customer communication、compliance、learning maturity 哪個壓力最明顯</td>
      </tr>
      <tr>
          <td>替代邊界</td>
          <td>on-call SaaS、Slack workflow、自建流程、status page、learning platform 的機會成本</td>
      </tr>
      <tr>
          <td>操作成本</td>
          <td>rota hygiene、service catalog、integration、timeline quality、stakeholder update</td>
      </tr>
      <tr>
          <td>Evidence</td>
          <td>alert route、ack time、incident timeline、decision log、status update、action item</td>
      </tr>
      <tr>
          <td>案例回寫</td>
          <td>AWS、Cloudflare、GitHub、Atlassian 等事故案例如何提供流程判準</td>
      </tr>
  </tbody>
</table>
<h2 id="服務頁標準章節">服務頁標準章節</h2>
<table>
  <thead>
      <tr>
          <th>章節</th>
          <th>事故處理工具頁要補的內容</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>工具定位</td>
          <td>它是 on-call、IR coordination、status communication、postmortem 還是 learning platform</td>
      </tr>
      <tr>
          <td>本章目標</td>
          <td>讀者能判斷該工具改善哪個事故協作節點與哪種 evidence handoff</td>
      </tr>
      <tr>
          <td>最短判讀路徑</td>
          <td>用「告警找人、事故指揮、對外更新、復盤學習」快速定位工具類型</td>
      </tr>
      <tr>
          <td>日常操作與決策形狀</td>
          <td>service catalog、rota、escalation、timeline、status update、action item</td>
      </tr>
      <tr>
          <td>核心取捨表</td>
          <td>On-call SaaS、Slack-native IR、自建流程、status page、learning platform 的機會成本</td>
      </tr>
      <tr>
          <td>進階主題</td>
          <td>multi-team escalation、compliance report、customer communication、learning review</td>
      </tr>
      <tr>
          <td>排錯與失敗快速判讀</td>
          <td>alert storm、missed ack、unclear commander、stale status page、action item drift</td>
      </tr>
      <tr>
          <td>何時改走其他服務</td>
          <td>信號品質回 04、release gate 回 06、平台回退回 05、資安事件回 07</td>
      </tr>
      <tr>
          <td>不在本頁內的主題</td>
          <td>完整組織設計、HR 輪值政策、法律公告模板、每個聊天平台 automation</td>
      </tr>
      <tr>
          <td>案例回寫與下一步路由</td>
          <td>回到 08 cases、8.19 decision log、8.22 evidence write-back</td>
      </tr>
  </tbody>
</table>
<h2 id="跨-vendor-議題對照">跨 vendor 議題對照</h2>
<p>本模組 9 個 vendor 跨 4 個 sub-category（on-call paging / IR coordination / status page / learning）、覆蓋 incident 全流程。對照表用「橫向 incident 流程節點」標明每個議題在哪個 sub-category 落地。</p>
<table>
  <thead>
      <tr>
          <th>議題</th>
          <th>PagerDuty</th>
          <th>Opsgenie</th>
          <th>Grafana OnCall</th>
          <th>incident.io</th>
          <th>FireHydrant</th>
          <th>Rootly</th>
          <th>Statuspage</th>
          <th>Instatus</th>
          <th>Jeli</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>主責任</td>
          <td>On-call SaaS</td>
          <td>Atlassian on-call</td>
          <td>OSS on-call</td>
          <td>IR coordination</td>
          <td>IR coordination</td>
          <td>IR coordination</td>
          <td>Status page</td>
          <td>Status page</td>
          <td>Learning / postmortem</td>
      </tr>
      <tr>
          <td>Paging</td>
          <td>核心</td>
          <td>核心</td>
          <td>核心</td>
          <td>後加</td>
          <td>後加</td>
          <td>後加</td>
          <td>N/A</td>
          <td>N/A</td>
          <td>N/A</td>
      </tr>
      <tr>
          <td>IR coordination</td>
          <td>Response Play</td>
          <td>中等</td>
          <td>弱</td>
          <td>核心 (Slack)</td>
          <td>核心 (Teams)</td>
          <td>核心 (no-code)</td>
          <td>N/A</td>
          <td>N/A</td>
          <td>N/A</td>
      </tr>
      <tr>
          <td>Status page</td>
          <td>整合外部</td>
          <td>整合 Statuspage</td>
          <td>整合外部</td>
          <td>整合外部</td>
          <td>內建</td>
          <td>整合外部</td>
          <td>核心</td>
          <td>核心</td>
          <td>N/A</td>
      </tr>
      <tr>
          <td>Retrospective</td>
          <td>Jeli (整合)</td>
          <td>Confluence</td>
          <td>弱</td>
          <td>template</td>
          <td>facilitator</td>
          <td>AI</td>
          <td>N/A</td>
          <td>N/A</td>
          <td>核心 (narrative)</td>
      </tr>
      <tr>
          <td>配置模式</td>
          <td>UI + Terraform</td>
          <td>UI</td>
          <td>UI / Helm</td>
          <td>Slack + UI</td>
          <td>Slack/Teams + UI</td>
          <td>No-code UI</td>
          <td>UI + API</td>
          <td>UI + API</td>
          <td>UI</td>
      </tr>
      <tr>
          <td>整合 IR 工具</td>
          <td>支援</td>
          <td>支援</td>
          <td>中等</td>
          <td>支援</td>
          <td>支援</td>
          <td>200+ 整合</td>
          <td>IR push</td>
          <td>IR push</td>
          <td>PagerDuty 整合</td>
      </tr>
      <tr>
          <td>商業 / 開源</td>
          <td>商業 SaaS</td>
          <td>商業 SaaS</td>
          <td>OSS / Cloud</td>
          <td>商業 SaaS</td>
          <td>商業 SaaS</td>
          <td>商業 SaaS</td>
          <td>商業 SaaS</td>
          <td>商業 SaaS</td>
          <td>商業（PD 旗下）</td>
      </tr>
      <tr>
          <td>平台支援</td>
          <td>iOS / Android / Web</td>
          <td>iOS / Android / Web</td>
          <td>Web</td>
          <td>Slack first</td>
          <td>Slack + Teams</td>
          <td>Slack + Teams</td>
          <td>Web</td>
          <td>Web</td>
          <td>Web</td>
      </tr>
  </tbody>
</table>
<p>對照表的用途有三：</p>
<ul>
<li>寫某 vendor 頁時、看相同 sub-category 對手如何處理同議題</li>
<li>讀者組 IR stack：paging + IR coordination + status page + learning 各選 1</li>
<li>評估 best-of-breed vs all-in-one 取捨</li>
</ul>
<p>下面 4 段把對照表的 sub-category 展開。</p>
<h3 id="pagingpagerduty--opsgenie--grafana-oncall">Paging（PagerDuty / Opsgenie / Grafana OnCall）</h3>
<p>Paging 是 alert 找對人的入口。<strong>PagerDuty</strong> 業界標準、完整 IR 平台演化、Jeli 收購補 learning；<strong>Opsgenie</strong> Atlassian 生態最強、跟 JSM / Statuspage / Confluence 一站式；<strong>Grafana OnCall</strong> OSS / 預算敏感替代、跟 Grafana 觀測生態整合。</p>
<p>選型判讀：成熟 + 跨生態 → PagerDuty；Atlassian 用戶 → Opsgenie；OSS / Grafana 用戶 → Grafana OnCall。</p>
<h3 id="ir-coordinationincidentio--firehydrant--rootly">IR coordination（incident.io / FireHydrant / Rootly）</h3>
<p>IR coordination 是事故當下的協作平台、把 incident lifecycle 自動化。<strong>incident.io</strong> Slack-first、UX 最簡潔；<strong>FireHydrant</strong> 雙平台（Slack + Teams）、內建 status page + retrospective facilitator；<strong>Rootly</strong> no-code workflow + AI 輔助、200+ integration。</p>
<p>選型判讀：Slack-only + 簡潔 → incident.io；Microsoft Teams + 完整 retro → FireHydrant；no-code 客製 + AI → Rootly。三者都有 paging 模組、可不另外用 PagerDuty。</p>
<h3 id="status-pageatlassian-statuspage--instatus">Status page（Atlassian Statuspage / Instatus）</h3>
<p>Status page 是對外溝通入口、是法律 / SLA / 客戶信任的 evidence。<strong>Statuspage</strong> 事實標準、enterprise SLA、跟 Opsgenie / PagerDuty / IR 平台廣泛整合；<strong>Instatus</strong> 輕量 / 價格親民 / 現代 UI / startup 友善。</p>
<p>選型判讀：enterprise / 既有 Atlassian 投資 → Statuspage；budget / startup → Instatus；OSS 自管 → Cachet（不在本表）；IR 平台內建夠 → FireHydrant 內建 status page。</p>
<h3 id="learningjeli">Learning（Jeli）</h3>
<p>Learning 是事故後的組織學習、不是 retro template、是 longitudinal pattern analysis。<strong>Jeli</strong>（2023 PagerDuty 收購）narrative-based investigation + cross-incident pattern detection、源自 Honeycomb Production Excellence 文化。Jeli 跟 IR 平台的 retrospective 模組 complement、不取代 — IR retro 是單事故、Jeli 是跨事故學習。</p>
<p>選型判讀：深度 learning + multi-incident pattern → Jeli（PagerDuty 用戶）；單事故 retro template → IR 平台內建即可；組織學習 / 文化變革 → Jeli + 對應流程。</p>
<h2 id="撰寫批次">撰寫批次</h2>
<table>
  <thead>
      <tr>
          <th>批次</th>
          <th>服務頁</th>
          <th>撰寫目的</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>I1</td>
          <td>PagerDuty / Opsgenie / Grafana OnCall</td>
          <td>建立 alert routing、escalation 與輪值 baseline</td>
      </tr>
      <tr>
          <td>I2</td>
          <td>incident.io / FireHydrant / Rootly</td>
          <td>建立 incident command、timeline 與 automation 對照</td>
      </tr>
      <tr>
          <td>I3</td>
          <td>Atlassian Statuspage / Instatus</td>
          <td>建立外部溝通、component status 與 stakeholder update 判準</td>
      </tr>
      <tr>
          <td>I4</td>
          <td>Jeli / Blameless / 自建流程</td>
          <td>建立 postmortem、learning review 與 action tracking 對照</td>
      </tr>
  </tbody>
</table>
<h2 id="後續候選">後續候選</h2>
<table>
  <thead>
      <tr>
          <th>類型</th>
          <th>候選服務</th>
          <th>寫作重點</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>On-call</td>
          <td>Squadcast、xMatters、Splunk On-Call、Better Stack</td>
          <td>escalation policy、enterprise workflow、handoff</td>
      </tr>
      <tr>
          <td>ITSM / service desk</td>
          <td>ServiceNow、Jira Service Management</td>
          <td>ticket lifecycle、change / incident linkage、enterprise workflow</td>
      </tr>
      <tr>
          <td>Status page</td>
          <td>status.io、Cachet、Better Stack Status</td>
          <td>hosted vs self-hosted、subscriber communication</td>
      </tr>
      <tr>
          <td>Learning</td>
          <td>Blameless、Howie</td>
          <td>postmortem workflow、learning capture、action follow-up</td>
      </tr>
      <tr>
          <td>Collaboration</td>
          <td>Slack workflow、Microsoft Teams workflow、GitHub Issues</td>
          <td>低成本流程、缺口、handoff evidence</td>
      </tr>
  </tbody>
</table>
<p>主流覆蓋檢查的重點是分開 paging、incident command、ITSM、status communication 與 learning。PagerDuty / Opsgenie / Grafana OnCall 解 paging；incident.io / FireHydrant / Rootly 解 command workflow；ServiceNow / Jira Service Management 解 enterprise ticket lifecycle；Statuspage / Instatus / Cachet 解對外溝通；Jeli / Blameless 解 learning loop。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/08-incident-response/drills-and-oncall-readiness/" data-link-title="8.6 演練與值班能力建設" data-link-desc="用演練與值班訓練提升事故反應品質">Drills and On-call Readiness</a></li>
<li>上游：<a href="/blog/backend/08-incident-response/incident-decision-log/" data-link-title="8.19 Incident Decision Log" data-link-desc="把事中假設、決策、證據、回退條件與責任人留下可復盤紀錄">8.19 Incident Decision Log</a></li>
<li>上游：<a href="/blog/backend/08-incident-response/incident-evidence-write-back/" data-link-title="8.22 Incident Evidence Write-back" data-link-desc="把事故證據、決策與復盤結論回寫到 observability、reliability 與 runbook">8.22 Incident Evidence Write-back</a></li>
<li>服務路徑：<a href="/blog/backend/08-incident-response/control-plane-decision-log-write-back/" data-link-title="8.23 Control Plane Decision Log and Write-back 實作示範" data-link-desc="以 rule/config rollout 事故示範 decision log 與 write-back 如何形成可回放閉環。">8.23 Control Plane Decision Log and Write-back 實作示範</a></li>
</ul>
]]></content:encoded></item><item><title>Sibling Vendor Cross-Link 雙向性 Audit：寫 Vendor Batch 結束必跑</title><link>https://tarrragon.github.io/blog/report/sibling-vendor-cross-link-bidirectionality-audit/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/sibling-vendor-cross-link-bidirectionality-audit/</guid><description>&lt;h2 id="核心sibling-vendor-batch-容易單向-cross-link">核心：Sibling vendor batch 容易單向 cross-link&lt;/h2>
&lt;p>當寫 sibling vendor batch（A 跟 B 是同類角色的 vendor）、cross-link 容易單向：&lt;/p>
&lt;ul>
&lt;li>A 是後寫 batch、提 B 多次（「跟 PG sibling 對比」「PG 的 X 行為跟 MySQL 不同」）&lt;/li>
&lt;li>B 是先寫 batch、預設沒提 A（寫的時候 A 還不存在）&lt;/li>
&lt;li>結果：A → B 有 9 條 link、B → A 有 0 條 link&lt;/li>
&lt;/ul>
&lt;p>讀者從 B 進入、看不到 A 的存在；只有從 A 進入才知道兩者並列。&lt;/p>
&lt;p>問題不在 &lt;em>單向 link 本身錯&lt;/em>、在 &lt;em>vendor batch 結束沒跑 bidirectional audit&lt;/em>、就以為「cross-link 已建立」。&lt;/p>
&lt;h2 id="casemysql--postgresql-cross-link-asymmetry">Case：MySQL ↔ PostgreSQL cross-link asymmetry&lt;/h2>
&lt;p>4-reviewer audit（Reviewer B）finding：&lt;/p>
&lt;ul>
&lt;li>MySQL 18 篇對 PG sibling 的 cross-link：9 條（vs PostgreSQL 對比段 / 連到 PG vendor page / 連到 PG sibling article）&lt;/li>
&lt;li>PG 11 篇對 MySQL 的 cross-link：0 條&lt;/li>
&lt;/ul>
&lt;p>讀者站 PG &lt;code>pgbouncer-config&lt;/code> 不會跳到 MySQL &lt;code>proxysql-config&lt;/code>；站 MySQL &lt;code>proxysql-config&lt;/code> 直接看到「跟 PG pgBouncer 對比」段。Navigation asymmetric。&lt;/p>
&lt;h2 id="機制為什麼會單向">機制：為什麼會單向&lt;/h2>
&lt;h3 id="1-寫第二個-batch-時-reference-第一個-batch-是自然行為">1. 寫第二個 batch 時 reference 第一個 batch 是自然行為&lt;/h3>
&lt;p>寫 MySQL &lt;code>replication-topology&lt;/code> 時、PG &lt;code>patroni-ha&lt;/code> 已存在、自然連去做對比。寫 PG &lt;code>patroni-ha&lt;/code> 時、MySQL &lt;code>replication-topology&lt;/code> 還不存在、不可能 link。&lt;/p>
&lt;p>這是 &lt;em>sequential 寫作的時間性結構性&lt;/em>、不是疏忽。&lt;/p>
&lt;h3 id="2-bidirectional-link-audit-不在預設寫作流程">2. Bidirectional link audit 不在預設寫作流程&lt;/h3>
&lt;p>寫完 batch B 後、預設 audit：&lt;/p>
&lt;ul>
&lt;li>lint / cards&lt;/li>
&lt;li>emoji / 裸 URL&lt;/li>
&lt;li>跨檔一致性&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>沒有&lt;/strong> &lt;em>向上回補 sibling A 的 cross-link&lt;/em> 這一步。&lt;/p>
&lt;h3 id="3-sibling-a-寫好後不會自動-trigger-a-的更新">3. Sibling A 寫好後、不會自動 trigger A 的更新&lt;/h3>
&lt;p>寫 vendor batch B 完成時、A 的內容不變、沒人 trigger「現在 sibling B 存在了、A 應該加 cross-link 回 B」。&lt;/p>
&lt;h2 id="修法bidirectional-cross-link-audit">修法：Bidirectional cross-link audit&lt;/h2>
&lt;h3 id="audit-步驟">Audit 步驟&lt;/h3>
&lt;p>寫完 vendor batch B（B 跟 sibling A 存在對應）後、跑：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 1. Count A → B link&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">rg -c &lt;span class="s2">&amp;#34;\]\(/path/to/B/&amp;#34;&lt;/span> content/path/to/A/*.md
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="c1"># 2. Count B → A link&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">rg -c &lt;span class="s2">&amp;#34;\]\(/path/to/A/&amp;#34;&lt;/span> content/path/to/B/*.md
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">&lt;span class="c1"># 3. 對比&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl">&lt;span class="c1"># 若 A→B 顯著少於 B→A、補 A 端 cross-link&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="補-a-端-cross-link-的位置">補 A 端 cross-link 的位置&lt;/h3>
&lt;p>每個 A article 應該在：&lt;/p></description><content:encoded><![CDATA[<h2 id="核心sibling-vendor-batch-容易單向-cross-link">核心：Sibling vendor batch 容易單向 cross-link</h2>
<p>當寫 sibling vendor batch（A 跟 B 是同類角色的 vendor）、cross-link 容易單向：</p>
<ul>
<li>A 是後寫 batch、提 B 多次（「跟 PG sibling 對比」「PG 的 X 行為跟 MySQL 不同」）</li>
<li>B 是先寫 batch、預設沒提 A（寫的時候 A 還不存在）</li>
<li>結果：A → B 有 9 條 link、B → A 有 0 條 link</li>
</ul>
<p>讀者從 B 進入、看不到 A 的存在；只有從 A 進入才知道兩者並列。</p>
<p>問題不在 <em>單向 link 本身錯</em>、在 <em>vendor batch 結束沒跑 bidirectional audit</em>、就以為「cross-link 已建立」。</p>
<h2 id="casemysql--postgresql-cross-link-asymmetry">Case：MySQL ↔ PostgreSQL cross-link asymmetry</h2>
<p>4-reviewer audit（Reviewer B）finding：</p>
<ul>
<li>MySQL 18 篇對 PG sibling 的 cross-link：9 條（vs PostgreSQL 對比段 / 連到 PG vendor page / 連到 PG sibling article）</li>
<li>PG 11 篇對 MySQL 的 cross-link：0 條</li>
</ul>
<p>讀者站 PG <code>pgbouncer-config</code> 不會跳到 MySQL <code>proxysql-config</code>；站 MySQL <code>proxysql-config</code> 直接看到「跟 PG pgBouncer 對比」段。Navigation asymmetric。</p>
<h2 id="機制為什麼會單向">機制：為什麼會單向</h2>
<h3 id="1-寫第二個-batch-時-reference-第一個-batch-是自然行為">1. 寫第二個 batch 時 reference 第一個 batch 是自然行為</h3>
<p>寫 MySQL <code>replication-topology</code> 時、PG <code>patroni-ha</code> 已存在、自然連去做對比。寫 PG <code>patroni-ha</code> 時、MySQL <code>replication-topology</code> 還不存在、不可能 link。</p>
<p>這是 <em>sequential 寫作的時間性結構性</em>、不是疏忽。</p>
<h3 id="2-bidirectional-link-audit-不在預設寫作流程">2. Bidirectional link audit 不在預設寫作流程</h3>
<p>寫完 batch B 後、預設 audit：</p>
<ul>
<li>lint / cards</li>
<li>emoji / 裸 URL</li>
<li>跨檔一致性</li>
</ul>
<p><strong>沒有</strong> <em>向上回補 sibling A 的 cross-link</em> 這一步。</p>
<h3 id="3-sibling-a-寫好後不會自動-trigger-a-的更新">3. Sibling A 寫好後、不會自動 trigger A 的更新</h3>
<p>寫 vendor batch B 完成時、A 的內容不變、沒人 trigger「現在 sibling B 存在了、A 應該加 cross-link 回 B」。</p>
<h2 id="修法bidirectional-cross-link-audit">修法：Bidirectional cross-link audit</h2>
<h3 id="audit-步驟">Audit 步驟</h3>
<p>寫完 vendor batch B（B 跟 sibling A 存在對應）後、跑：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 1. Count A → B link</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">rg -c <span class="s2">&#34;\]\(/path/to/B/&#34;</span> content/path/to/A/*.md
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 2. Count B → A link</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">rg -c <span class="s2">&#34;\]\(/path/to/A/&#34;</span> content/path/to/B/*.md
</span></span><span class="line"><span class="ln">6</span><span class="cl">
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="c1"># 3. 對比</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="c1"># 若 A→B 顯著少於 B→A、補 A 端 cross-link</span></span></span></code></pre></div><h3 id="補-a-端-cross-link-的位置">補 A 端 cross-link 的位置</h3>
<p>每個 A article 應該在：</p>
<ol>
<li><strong>「相關連結」段</strong> — 列對應 sibling B article</li>
<li><strong>「跟其他 vendor 的取捨」段</strong>（若有） — 提到 sibling B 的對應</li>
<li><strong>「下一步路由」 / 「替代路徑」段</strong> — 列 B 作為 alternative</li>
</ol>
<h3 id="audit-cadence">Audit cadence</h3>
<ul>
<li>每個 sibling vendor batch 寫完、跑一次 bidirectional audit</li>
<li>不只寫完 <em>第二個</em> batch、寫完 <em>第三 / 第四個</em> 也跑（A↔B↔C 三方對稱）</li>
<li>vendors/_index 內容覆蓋進度表加 <code>link_density</code> 欄、揭露 asymmetry</li>
</ul>
<h2 id="跟既有原則的關係">跟既有原則的關係</h2>
<ul>
<li><a href="../sibling-coverage-asymmetry-blindspot-in-priority/">Sibling Coverage Asymmetry Blindspot in Priority</a>：本卡是 cross-link asymmetry、那卡是 coverage asymmetry、同型但不同 axis</li>
<li><a href="../cards-as-living-system-iteration/">Cards as Living System Iteration</a>：cross-link 維護是 living system 部分、不是 one-shot</li>
</ul>
<h2 id="反向驗證">反向驗證</h2>
<p>不該誤用：</p>
<ul>
<li><em>Sibling vendor</em> 限同類角色（PG / MySQL 都 SQL baseline）、不是任意兩個 vendor。MySQL 沒必要 link Spanner（不同類）</li>
<li>雙向不等於 <em>對稱數量</em> — A 18 篇可能有 9 條 link、B 11 篇有 6 條 link 是合理（不是 9 對 9）</li>
<li>Migration playbook 結構性單向（A → B 是遷移、不是 B → A）— 對 migration playbook 是 <em>單向結構</em>、不適用本 audit</li>
</ul>
]]></content:encoded></item><item><title>Vendor Feature 時間敏感性：Claim Verification 必跑、寫作日期必標</title><link>https://tarrragon.github.io/blog/report/vendor-feature-time-sensitivity-claim-verification/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/vendor-feature-time-sensitivity-claim-verification/</guid><description>&lt;h2 id="核心vendor-feature-limitation-claim-有時間敏感性">核心：Vendor feature limitation claim 有時間敏感性&lt;/h2>
&lt;p>寫 vendor article 時、常見以下 claim 形態：&lt;/p>
&lt;ul>
&lt;li>「Vendor X 不支援 Y」&lt;/li>
&lt;li>「Vendor X 最多 Z」&lt;/li>
&lt;li>「Vendor X 預設 W」&lt;/li>
&lt;/ul>
&lt;p>這些 claim 在寫作那刻是真的、但 vendor 持續演進。寫作後 &lt;em>N 個月&lt;/em> — 6 個月、12 個月、24 個月 — claim 可能反轉、整段 audit 邏輯 invalidates。&lt;/p>
&lt;p>問題不只是 &lt;em>claim 過時&lt;/em>、是 &lt;em>基於 claim 的整段流程被推翻&lt;/em>。Migration playbook Phase 1 audit 如果以「Vendor 不支援 X」為前提、X 後來變支援、Phase 1 整段重寫。&lt;/p>
&lt;h2 id="caseplanetscale-fk-claim-反轉">Case：PlanetScale FK claim 反轉&lt;/h2>
&lt;p>寫 migrate-to-planetscale.md 跟 migrate-vitess-to-planetscale.md 時：&lt;/p>
&lt;ul>
&lt;li>Claim：「PlanetScale 不支援 Foreign Key（Vitess 限制）」&lt;/li>
&lt;li>基於此 claim：Phase 1 audit 整段「FK audit + 全 drop FK + application enforcement 改寫」&lt;/li>
&lt;li>Phase 1 是 weeks-months 工作量、第一個 phase&lt;/li>
&lt;/ul>
&lt;p>實際狀態（4-reviewer C audit catch）：&lt;/p>
&lt;ul>
&lt;li>Vitess 18（2023 末）加 FK 支援&lt;/li>
&lt;li>PlanetScale 2024 起在合適 plan 內可啟用 FK&lt;/li>
&lt;li>「不支援」是 2022 年的事實、寫作時已過時&lt;/li>
&lt;/ul>
&lt;p>修法：整段 Phase 1 audit 從「FK audit + drop」改寫成「FK 行為驗證 + cross-shard cascade 處理」。&lt;/p>
&lt;p>這不是 &lt;em>微調文字&lt;/em>、是 &lt;em>整段 framing 重做&lt;/em>。&lt;/p>
&lt;h2 id="機制為什麼會發生">機制：為什麼會發生&lt;/h2>
&lt;h3 id="1-llm-training-cutoff-vs-vendor-changelog-速度差">1. LLM training cutoff vs vendor changelog 速度差&lt;/h3>
&lt;p>LLM training data 有 cutoff date（通常滯後 12-18 個月）。Vendor major feature release 在 cutoff 後、LLM 不知道。&lt;/p>
&lt;p>寫 vendor article 時、LLM 預設用 &lt;em>training 內的 latest fact&lt;/em> — 那個 fact 可能已過時。&lt;/p>
&lt;h3 id="2-llm-預設不標-claim-的時間性">2. LLM 預設不標 claim 的時間性&lt;/h3>
&lt;p>LLM 寫「PlanetScale 不支援 FK」、不會自動標「&lt;em>as of 2022&lt;/em>」、讀者看到 &lt;em>永久性 claim&lt;/em>。&lt;/p>
&lt;p>LLM 不會主動 verify「我寫的這個 claim 是 N 個月內仍 valid 的嗎」、除非寫作流程強制 verify step。&lt;/p>
&lt;h3 id="3-基於-claim-的整段流程是結構性-anchor">3. 基於 claim 的整段流程是「結構性 anchor」&lt;/h3>
&lt;p>Migration playbook 的 Phase 1 是 &lt;em>結構錨點&lt;/em> — 後續 Phase 2-4 都 reference Phase 1 結果。Phase 1 基於過時 claim 時、修法不只是 claim、是 &lt;em>整個 anchor 重做&lt;/em>。&lt;/p></description><content:encoded><![CDATA[<h2 id="核心vendor-feature-limitation-claim-有時間敏感性">核心：Vendor feature limitation claim 有時間敏感性</h2>
<p>寫 vendor article 時、常見以下 claim 形態：</p>
<ul>
<li>「Vendor X 不支援 Y」</li>
<li>「Vendor X 最多 Z」</li>
<li>「Vendor X 預設 W」</li>
</ul>
<p>這些 claim 在寫作那刻是真的、但 vendor 持續演進。寫作後 <em>N 個月</em> — 6 個月、12 個月、24 個月 — claim 可能反轉、整段 audit 邏輯 invalidates。</p>
<p>問題不只是 <em>claim 過時</em>、是 <em>基於 claim 的整段流程被推翻</em>。Migration playbook Phase 1 audit 如果以「Vendor 不支援 X」為前提、X 後來變支援、Phase 1 整段重寫。</p>
<h2 id="caseplanetscale-fk-claim-反轉">Case：PlanetScale FK claim 反轉</h2>
<p>寫 migrate-to-planetscale.md 跟 migrate-vitess-to-planetscale.md 時：</p>
<ul>
<li>Claim：「PlanetScale 不支援 Foreign Key（Vitess 限制）」</li>
<li>基於此 claim：Phase 1 audit 整段「FK audit + 全 drop FK + application enforcement 改寫」</li>
<li>Phase 1 是 weeks-months 工作量、第一個 phase</li>
</ul>
<p>實際狀態（4-reviewer C audit catch）：</p>
<ul>
<li>Vitess 18（2023 末）加 FK 支援</li>
<li>PlanetScale 2024 起在合適 plan 內可啟用 FK</li>
<li>「不支援」是 2022 年的事實、寫作時已過時</li>
</ul>
<p>修法：整段 Phase 1 audit 從「FK audit + drop」改寫成「FK 行為驗證 + cross-shard cascade 處理」。</p>
<p>這不是 <em>微調文字</em>、是 <em>整段 framing 重做</em>。</p>
<h2 id="機制為什麼會發生">機制：為什麼會發生</h2>
<h3 id="1-llm-training-cutoff-vs-vendor-changelog-速度差">1. LLM training cutoff vs vendor changelog 速度差</h3>
<p>LLM training data 有 cutoff date（通常滯後 12-18 個月）。Vendor major feature release 在 cutoff 後、LLM 不知道。</p>
<p>寫 vendor article 時、LLM 預設用 <em>training 內的 latest fact</em> — 那個 fact 可能已過時。</p>
<h3 id="2-llm-預設不標-claim-的時間性">2. LLM 預設不標 claim 的時間性</h3>
<p>LLM 寫「PlanetScale 不支援 FK」、不會自動標「<em>as of 2022</em>」、讀者看到 <em>永久性 claim</em>。</p>
<p>LLM 不會主動 verify「我寫的這個 claim 是 N 個月內仍 valid 的嗎」、除非寫作流程強制 verify step。</p>
<h3 id="3-基於-claim-的整段流程是結構性-anchor">3. 基於 claim 的整段流程是「結構性 anchor」</h3>
<p>Migration playbook 的 Phase 1 是 <em>結構錨點</em> — 後續 Phase 2-4 都 reference Phase 1 結果。Phase 1 基於過時 claim 時、修法不只是 claim、是 <em>整個 anchor 重做</em>。</p>
<p>這比修 isolated fact 工作量大 10x — 是「invalidates premise」、不是「fix typo」。</p>
<h3 id="4-vendor-article-多用-永久性語氣-而非-時間性語氣">4. Vendor article 多用 <em>永久性語氣</em> 而非 <em>時間性語氣</em></h3>
<p>寫作習慣寫「PlanetScale 不支援 FK」（永久性）、不寫「PlanetScale 截至 2022 末不支援 FK」（時間性）。</p>
<p>讀者讀到的是 <em>當前永久狀態</em>、寫作者其實只能保證 <em>寫作那刻</em>。</p>
<h2 id="修法">修法</h2>
<h3 id="1-每篇-vendor-article-標-last-verified-date">1. 每篇 vendor article 標 <code>Last verified</code> date</h3>
<p>frontmatter 或開頭加：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="ln">1</span><span class="cl"><span class="nt">last_verified</span><span class="p">:</span><span class="w"> </span><span class="ld">2026-05-19</span><span class="w">
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="w"></span><span class="nt">verified_against</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="w">  </span>- <span class="l">PlanetScale docs（2026-05 access）</span><span class="w">
</span></span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="w">  </span>- <span class="l">Vitess 18.0 release notes</span></span></span></code></pre></div><p>讓讀者看到 <em>寫作時 verify 的 source / date</em>、不假設永久性。</p>
<h3 id="2-feature-limitation-claim-加時間註">2. Feature limitation claim 加時間註</h3>
<p>寫「Vendor X 不支援 Y」時、加 <em>as of N</em>：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">PlanetScale 截至 2024 末有限支援 FK（Vitess 18+、需明確啟用）</span></span></code></pre></div><p>而非：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">PlanetScale 不支援 FK</span></span></code></pre></div><h3 id="3-claim-反轉--整段-audit-重寫不是-patch">3. Claim 反轉 → 整段 audit 重寫、不是 patch</h3>
<p>當 verify 發現 claim 已反轉（如 PlanetScale FK 從不支援變支援）、不要 <em>只改 claim 字句</em>。回頭看 <em>基於該 claim 的流程段落</em> —</p>
<ul>
<li>Migration Phase 1 audit</li>
<li>「何時不要遷」反向 recommendation</li>
<li>「跟 sibling vendor 對比」表</li>
</ul>
<p>每段都要 <em>重看是否還成立</em>、不成立的整段重寫。</p>
<h3 id="4-vendor-article-寫作前先-verify-主要-claim">4. Vendor article 寫作前先 verify 主要 claim</h3>
<p>寫作流程加 <em>verify checkpoint</em>：</p>
<ul>
<li>列出該 article 的「Vendor X 不支援 Y / 最多 Z / 預設 W」claim</li>
<li>對每個 claim、查 vendor official docs（最新 docs）/ recent release note（過去 12 個月）</li>
<li>不確定的標 <em>uncertain</em>、不要 confidence-fake</li>
</ul>
<h3 id="5-reviewer-c-必查-vendor-feature-time-sensitive-claim">5. Reviewer C 必查 vendor feature time-sensitive claim</h3>
<p>跑 4-reviewer audit 時、Reviewer C（技術準確性）必須：</p>
<ul>
<li>對每個 <em>feature limitation claim</em>、verify 是否仍 current</li>
<li>對每個 <em>vendor CLI command</em>、verify 是否真實存在（hallucinated CLI 是 sibling 問題）</li>
<li>對每個 <em>vendor default value</em>、verify 是否最新</li>
</ul>
<h2 id="hallucination-鄰近議題">Hallucination 鄰近議題</h2>
<p>LLM 寫 vendor CLI command 容易 hallucinate（例如 <code>pscale database promote-shadow</code>、<code>vtctldclient PartitionTablet</code>）— 命令不存在、是 LLM 編造。</p>
<p>跟本卡時間敏感性 <em>不完全相同</em> —</p>
<ul>
<li>時間敏感性：<em>claim 寫作時 valid、現在過時</em></li>
<li>Hallucination：<em>claim 寫作時也 invalid、是編造</em></li>
</ul>
<p>兩者修法部分重疊：</p>
<ul>
<li>寫前 verify（claim + CLI）</li>
<li>Reviewer C audit</li>
<li>不確定標 uncertain</li>
</ul>
<p>但 hallucination 是 <em>更基本的 verify failure</em>、本卡聚焦時間敏感性。</p>
<h2 id="跟既有原則的關係">跟既有原則的關係</h2>
<ul>
<li><a href="../sibling-coverage-asymmetry-blindspot-in-priority/">Sibling Coverage Asymmetry Blindspot in Priority</a>：本卡是 <em>claim 時間敏感性</em>、那卡是 <em>coverage 對稱性</em>、不同 axis</li>
<li><a href="../data-topology-as-audit-dimension/">Data Topology as Audit Dimension</a>：本卡是 <em>寫作 audit 應加時間維度</em>、那卡是 <em>content audit 應加 topology 維度</em></li>
</ul>
<h2 id="反向驗證">反向驗證</h2>
<p>不該誤用本卡：</p>
<ul>
<li><em>穩定 fact</em>（SQL syntax / RFC standard / industry-wide convention）不必標時間性、只有 <em>vendor-specific evolving feature</em> 才需要</li>
<li>不是每個 claim 都要 verify — 「MySQL replication 用 binlog」是穩定 fact、不必加 <em>as of N</em></li>
<li>過度標 <em>as of N</em> 會讓 article 變 verbose、只對 <em>limitation claim</em> 跟 <em>vendor-specific behavior</em> 套用</li>
</ul>
<h2 id="觸發再評估">觸發再評估</h2>
<p>未來累積到以下情境、本卡應 review：</p>
<ul>
<li>連續 2 個 batch 都踩 hallucinated CLI（trigger 升級到強制 <em>寫前 CLI verify</em>）</li>
<li>Feature claim 反轉 invalidates 整段流程的 case 超過 3 次（trigger 把 vendor article 改成 <em>每 N 個月 re-verify</em> 紀律）</li>
<li>LLM training cutoff 跟 vendor changelog 速度差變更大（trigger 升級 verify cadence）</li>
</ul>
]]></content:encoded></item><item><title>資料庫 Vendor 文章撰寫規格</title><link>https://tarrragon.github.io/blog/backend/01-database/vendor-article-spec/</link><pubDate>Wed, 20 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/01-database/vendor-article-spec/</guid><description>&lt;p>資料庫 Vendor 文章撰寫規格的核心責任是把服務頁、深度文章與遷移 playbook 的分工固定下來。PostgreSQL 與 MySQL 已經提供 SQL baseline 的完整樣本；後續撰寫 SQLite、MongoDB、DynamoDB、Aurora、Spanner、Cosmos DB 與 CockroachDB 時，應沿用同一組教學功能檢查，但保留每個服務自己的資料形狀、操作責任與失敗語言。&lt;/p>
&lt;p>這份規格承接 &lt;a href="https://tarrragon.github.io/blog/posts/vendor-%E6%B7%B1%E5%BA%A6%E6%8A%80%E8%A1%93%E6%96%87%E7%AB%A0%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84%E5%90%8C-vendor-%E7%B3%BB%E5%88%97%E7%9A%84%E9%96%8B%E5%A0%B4%E8%BC%AA%E6%9B%BF%E9%A9%97%E8%AD%89/" data-link-title="Vendor 深度技術文章方法論的演化紀錄：同 vendor 系列的開場輪替驗證" data-link-desc="vendor overview 飽和後要寫單一功能深度文章、需要選題與結構依據時回來。這套方法論的驗證來源與 cadence variant 在高風險場景（同 vendor sub-tool 系列）的實證。">Vendor 深度技術文章寫作方法論&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">Migration Playbook 寫作方法論&lt;/a>。本文只處理資料庫模組的落地規格：哪些內容留在 vendor overview，哪些議題升級成 deep article，哪些變更需要 migration playbook。&lt;/p>
&lt;h2 id="判讀錨點">判讀錨點&lt;/h2>
&lt;p>資料庫 vendor 文章的錨點是正式狀態如何被保存、查詢、複製、演進與修復。產品功能、版本差異與雲端價格都只是材料；正文要把材料轉成讀者可操作的判準，讓讀者能判斷資料模型、交易需求、查詢邊界、容量壓力、操作責任與替代路由。&lt;/p>
&lt;p>PostgreSQL 與 MySQL 的 batch 顯示三個穩定事實。第一，SQL baseline 已經足以支撐其他服務頁開寫；第二，深度文章需要「何時不用」與真實案例 anchor 防止過度工程化；第三，跨 vendor 或 topology 變更需要獨立 playbook，不適合塞回 overview。&lt;/p>
&lt;h2 id="vendor-overview-規格">Vendor Overview 規格&lt;/h2>
&lt;p>Vendor overview 的責任是教讀者完成第一輪服務判斷。這一層回答服務承擔什麼資料責任、適合什麼壓力、日常有哪些操作決策、失效時先看哪些訊號，以及何時改走相鄰服務。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>規格面&lt;/th>
 &lt;th>必答問題&lt;/th>
 &lt;th>交付形態&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>服務定位&lt;/td>
 &lt;td>這個服務承擔 SQL、embedded、document、KV 或 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/distributed-sql/" data-link-title="Distributed SQL" data-link-desc="把 SQL 與交易語意延伸到多節點與多區域的資料庫形態">distributed SQL&lt;/a> 哪一種責任&lt;/td>
 &lt;td>開場段、教學路線、最短判讀路徑&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>資料形狀&lt;/td>
 &lt;td>資料是 row、document、key-value、time-series、geo 還是 global record&lt;/td>
 &lt;td>適用場景、schema / index / partition 說明&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>一致性與交易&lt;/td>
 &lt;td>transaction、replica、multi-region 與 stale read 如何取捨&lt;/td>
 &lt;td>適用場景、不適用場景、跟其他 vendor 的取捨&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>操作責任&lt;/td>
 &lt;td>誰負責 backup、failover、upgrade、capacity、security 與 audit&lt;/td>
 &lt;td>容量規劃要點、常見陷阱、下一步路由&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>替代邊界&lt;/td>
 &lt;td>什麼條件下改走 SQL、document、KV、managed SQL 或 distributed SQL&lt;/td>
 &lt;td>同類對比、相鄰章節路由、下游 deep article&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>案例與限制&lt;/td>
 &lt;td>哪些案例能提供壓力訊號，哪些 claim 需要時間敏感標記&lt;/td>
 &lt;td>案例對照、已知 limitation、後續擴充候選&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>服務定位段要先把產品名稱放回資料庫分類語言。SQLite 的定位是 embedded formal state 與低操作成本；MongoDB 的定位是 document shape 與 schema governance；DynamoDB 的定位是 managed KV / document access pattern；Aurora 的定位是 managed SQL operation transfer；Spanner、Cosmos DB 與 CockroachDB 的定位是 global 或 distributed consistency。&lt;/p>
&lt;p>資料形狀段要讓讀者知道服務為哪種查詢與寫入模式付成本。Row model 適合交易與 ad-hoc query；document model 適合聚合資料與 schema flexibility；KV model 適合固定 access pattern；&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/distributed-sql/" data-link-title="Distributed SQL" data-link-desc="把 SQL 與交易語意延伸到多節點與多區域的資料庫形態">distributed SQL&lt;/a> 適合跨 region 一致性，但會把 latency、transaction retry 與成本模型帶進設計。&lt;/p></description><content:encoded><![CDATA[<p>資料庫 Vendor 文章撰寫規格的核心責任是把服務頁、深度文章與遷移 playbook 的分工固定下來。PostgreSQL 與 MySQL 已經提供 SQL baseline 的完整樣本；後續撰寫 SQLite、MongoDB、DynamoDB、Aurora、Spanner、Cosmos DB 與 CockroachDB 時，應沿用同一組教學功能檢查，但保留每個服務自己的資料形狀、操作責任與失敗語言。</p>
<p>這份規格承接 <a href="/blog/posts/vendor-%E6%B7%B1%E5%BA%A6%E6%8A%80%E8%A1%93%E6%96%87%E7%AB%A0%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84%E5%90%8C-vendor-%E7%B3%BB%E5%88%97%E7%9A%84%E9%96%8B%E5%A0%B4%E8%BC%AA%E6%9B%BF%E9%A9%97%E8%AD%89/" data-link-title="Vendor 深度技術文章方法論的演化紀錄：同 vendor 系列的開場輪替驗證" data-link-desc="vendor overview 飽和後要寫單一功能深度文章、需要選題與結構依據時回來。這套方法論的驗證來源與 cadence variant 在高風險場景（同 vendor sub-tool 系列）的實證。">Vendor 深度技術文章寫作方法論</a> 與 <a href="/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">Migration Playbook 寫作方法論</a>。本文只處理資料庫模組的落地規格：哪些內容留在 vendor overview，哪些議題升級成 deep article，哪些變更需要 migration playbook。</p>
<h2 id="判讀錨點">判讀錨點</h2>
<p>資料庫 vendor 文章的錨點是正式狀態如何被保存、查詢、複製、演進與修復。產品功能、版本差異與雲端價格都只是材料；正文要把材料轉成讀者可操作的判準，讓讀者能判斷資料模型、交易需求、查詢邊界、容量壓力、操作責任與替代路由。</p>
<p>PostgreSQL 與 MySQL 的 batch 顯示三個穩定事實。第一，SQL baseline 已經足以支撐其他服務頁開寫；第二，深度文章需要「何時不用」與真實案例 anchor 防止過度工程化；第三，跨 vendor 或 topology 變更需要獨立 playbook，不適合塞回 overview。</p>
<h2 id="vendor-overview-規格">Vendor Overview 規格</h2>
<p>Vendor overview 的責任是教讀者完成第一輪服務判斷。這一層回答服務承擔什麼資料責任、適合什麼壓力、日常有哪些操作決策、失效時先看哪些訊號，以及何時改走相鄰服務。</p>
<table>
  <thead>
      <tr>
          <th>規格面</th>
          <th>必答問題</th>
          <th>交付形態</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>服務定位</td>
          <td>這個服務承擔 SQL、embedded、document、KV 或 <a href="/blog/backend/knowledge-cards/distributed-sql/" data-link-title="Distributed SQL" data-link-desc="把 SQL 與交易語意延伸到多節點與多區域的資料庫形態">distributed SQL</a> 哪一種責任</td>
          <td>開場段、教學路線、最短判讀路徑</td>
      </tr>
      <tr>
          <td>資料形狀</td>
          <td>資料是 row、document、key-value、time-series、geo 還是 global record</td>
          <td>適用場景、schema / index / partition 說明</td>
      </tr>
      <tr>
          <td>一致性與交易</td>
          <td>transaction、replica、multi-region 與 stale read 如何取捨</td>
          <td>適用場景、不適用場景、跟其他 vendor 的取捨</td>
      </tr>
      <tr>
          <td>操作責任</td>
          <td>誰負責 backup、failover、upgrade、capacity、security 與 audit</td>
          <td>容量規劃要點、常見陷阱、下一步路由</td>
      </tr>
      <tr>
          <td>替代邊界</td>
          <td>什麼條件下改走 SQL、document、KV、managed SQL 或 distributed SQL</td>
          <td>同類對比、相鄰章節路由、下游 deep article</td>
      </tr>
      <tr>
          <td>案例與限制</td>
          <td>哪些案例能提供壓力訊號，哪些 claim 需要時間敏感標記</td>
          <td>案例對照、已知 limitation、後續擴充候選</td>
      </tr>
  </tbody>
</table>
<p>服務定位段要先把產品名稱放回資料庫分類語言。SQLite 的定位是 embedded formal state 與低操作成本；MongoDB 的定位是 document shape 與 schema governance；DynamoDB 的定位是 managed KV / document access pattern；Aurora 的定位是 managed SQL operation transfer；Spanner、Cosmos DB 與 CockroachDB 的定位是 global 或 distributed consistency。</p>
<p>資料形狀段要讓讀者知道服務為哪種查詢與寫入模式付成本。Row model 適合交易與 ad-hoc query；document model 適合聚合資料與 schema flexibility；KV model 適合固定 access pattern；<a href="/blog/backend/knowledge-cards/distributed-sql/" data-link-title="Distributed SQL" data-link-desc="把 SQL 與交易語意延伸到多節點與多區域的資料庫形態">distributed SQL</a> 適合跨 region 一致性，但會把 latency、transaction retry 與成本模型帶進設計。</p>
<p>一致性與交易段要接回 <a href="/blog/backend/knowledge-cards/transaction-boundary/" data-link-title="Transaction Boundary" data-link-desc="說明哪些資料變更應在同一個交易中一起成功或一起回復">transaction boundary</a>、<a href="/blog/backend/knowledge-cards/isolation-level/" data-link-title="Isolation Level" data-link-desc="說明資料庫交易隔離級別如何影響並發讀寫結果">isolation level</a>、<a href="/blog/backend/knowledge-cards/replication-lag/" data-link-title="Replication Lag" data-link-desc="說明資料副本落後正式來源多久，以及它如何影響讀取正確性">replication lag</a> 與 <a href="/blog/backend/knowledge-cards/stale-read/" data-link-title="Stale Read" data-link-desc="讀取到落後於最新寫入版本的舊資料">stale read</a>。讀者需要知道的是哪種資料變更必須一起成功、哪種讀取可以接受延遲，以及跨 region 寫入是否值得支付協調成本。</p>
<p>操作責任段要把 managed 與 self-managed 的責任轉移寫清楚。自管服務保留控制權，團隊承擔 patch、backup、failover、capacity 與事故演練；managed 服務降低操作負擔，但增加平台限制、費用模型、版本節奏與 vendor-specific behavior。</p>
<p>替代邊界段要保留機會成本。PostgreSQL 或 MySQL 可以承擔多數 OLTP baseline；當 query 固定且高峰連線壓力明顯，DynamoDB 類服務可能更划算；當 document shape 主導資料模型，MongoDB 或 Cosmos DB 有更自然的操作語意；當 global write 是核心需求，Spanner、CockroachDB 或 Aurora DSQL 才進入主要比較。</p>
<p>案例與限制段要分開處理 evidence 與 backlog。案例提供流量形狀、資料形狀、失敗代價或回退路徑；limitation 承認正文還缺哪些維度，例如 PostgreSQL 目前仍需補 Security / RLS / audit logging、cross-region DR 與 managed PG 變體對比，MySQL 仍需補 deep article 的 anti-recommendation 與真實 incident anchor。</p>
<h2 id="deep-article-規格">Deep Article 規格</h2>
<p>Deep article 的責任是把 vendor overview 點到的單一機制展開成可操作教材。這一層不重寫服務選型，而是教讀者設定、觀測、除錯、容量估算與整合某個具體機制，例如 connection pool、replication topology、online schema change、<a href="/blog/backend/knowledge-cards/change-data-capture/" data-link-title="Change Data Capture" data-link-desc="說明資料變更如何被捕捉並傳送到其他系統">CDC</a>、partitioning、lock contention 或 PITR。</p>
<table>
  <thead>
      <tr>
          <th>規格面</th>
          <th>必答問題</th>
          <th>交付形態</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>問題情境</td>
          <td>什麼 production 壓力會讓這個機制變成主題</td>
          <td>開場場景、痛點、失效訊號</td>
      </tr>
      <tr>
          <td>核心機制</td>
          <td>該 vendor 如何實作這個能力，跟通用概念差在哪</td>
          <td>lifecycle、模式對照、內部元件責任</td>
      </tr>
      <tr>
          <td>操作流程</td>
          <td>讀者要如何配置、驗證、調整與演練</td>
          <td>step-by-step、config、query、command、驗證條件</td>
      </tr>
      <tr>
          <td>失敗模式</td>
          <td>哪些踩雷最常把服務推向事故</td>
          <td>production case、徵兆、根因、修法</td>
      </tr>
      <tr>
          <td>容量與觀測</td>
          <td>什麼 metric、query、log 或 cost signal 能判斷健康狀態</td>
          <td>容量規劃、觀測 metric、alert / dashboard route</td>
      </tr>
      <tr>
          <td>邊界與整合</td>
          <td>什麼條件下要換 sub-tool、改架構或回到 overview</td>
          <td>何時用、何時不用、sibling 對比、下一步路由</td>
      </tr>
  </tbody>
</table>
<p>問題情境段要用具體壓力啟動，產品文件定義只作為補充材料。Connection pool 可以從連線風暴與 backend slot 說起；replication 可以從 lag 與 failover 說起；PITR 可以從 restore 能力與 RPO 說起；lock contention 可以從交易範圍與 deadlock 訊號說起。</p>
<p>核心機制段要保留 vendor-specific 語意。PostgreSQL 的 WAL / LSN / replication slot、MVCC / vacuum、process-per-connection model 與 extension lifecycle 都有自己的操作語意；MySQL 的 binlog / GTID、InnoDB clustered index、gap / next-key lock、ProxySQL query rule 與 Vitess VSchema 也要用自己的語言展開。</p>
<p>操作流程段要把設定與判準綁在一起。Config、SQL、CLI 或 dashboard query 只在能支撐判讀時出現；每個操作要回答「如何知道它生效」「失敗時看到什麼」「可以停在哪個 rollback boundary」。</p>
<p>失敗模式段是 deep article 的主要價值。PostgreSQL / MySQL 既有文章多數已具備「5 個 Production 踩雷」；後續服務要維持這個密度，並優先補真實案例 anchor，避免所有案例都停在合成數字或典型設定。</p>
<p>容量與觀測段要讓 deep article 接回 04 / 09。資料庫機制常見的訊號包括 connection usage、replication lag、lock wait、dead tuple、buffer hit ratio、slow query、binlog retention、WAL growth、partition pruning 與 restore duration；這些訊號要能回到 <a href="/blog/backend/04-observability/observability-evidence-package/" data-link-title="4.20 Observability Evidence Package" data-link-desc="把 log、metric、trace、audit 與資料品質限制包成可交接證據">4.20 Observability Evidence Package</a> 或 <a href="/blog/backend/09-performance-capacity/bottleneck-localization/" data-link-title="9.5 瓶頸定位流程" data-link-desc="從 app 到 DB / cache / broker / 第三方 quota 的逐層瓶頸定位">9.5 瓶頸定位流程</a>。</p>
<p>邊界與整合段要補「何時不用」。MySQL audit 已經指出 deep article 容易缺 anti-recommendation；後續每篇 deep article 至少要有一段說明什麼規模、團隊能力或 workload 下暫時維持簡單設計更划算。</p>
<h2 id="hands-on--artifact-規格">Hands-on / Artifact 規格</h2>
<p>Hands-on / artifact 章節的責任是把 deep article 的機制判讀轉成可演練操作。這一層對齊 LLM <code>hands-on/</code> 的教學功能：讀者能跑出一個 local / staging lab，取得 config、query output、metric snapshot、validation result 或 rollback note，而不只停在概念理解。</p>
<table>
  <thead>
      <tr>
          <th>規格面</th>
          <th>必答問題</th>
          <th>交付形態</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Lab scope</td>
          <td>這個操作在 local、staging、managed sandbox 哪裡跑</td>
          <td>Docker Compose、CLI、SQL script、preview environment</td>
      </tr>
      <tr>
          <td>Input</td>
          <td>需要哪些 schema、seed data、config、credential</td>
          <td>setup checklist、sample data、env var</td>
      </tr>
      <tr>
          <td>操作步驟</td>
          <td>讀者照順序做什麼</td>
          <td>command / SQL / dashboard step</td>
      </tr>
      <tr>
          <td>Evidence</td>
          <td>怎麼知道操作成功、退化或失敗</td>
          <td>query output、metric snapshot、log、screenshot note</td>
      </tr>
      <tr>
          <td>Cleanup</td>
          <td>操作後哪些資料、帳號、route、backup 要清理</td>
          <td>teardown、rollback、retention note</td>
      </tr>
      <tr>
          <td>下一步路由</td>
          <td>操作結果要回到哪篇 deep article 或 migration</td>
          <td>overview、deep article、release gate、incident log</td>
      </tr>
  </tbody>
</table>
<p>PostgreSQL、MySQL 與 SQLite 已建立 hands-on 入口：<a href="/blog/backend/01-database/vendors/postgresql/hands-on/" data-link-title="PostgreSQL Hands-on 操作路線" data-link-desc="PostgreSQL local lab、connection pool、PITR restore drill、schema migration evidence 與 HA failover 的操作型章節設計">PostgreSQL hands-on</a>、<a href="/blog/backend/01-database/vendors/mysql/hands-on/" data-link-title="MySQL Hands-on 操作路線" data-link-desc="MySQL local lab、ProxySQL routing、online schema change、replication failover、backup restore 與 Vitess sandbox 的操作型章節設計">MySQL hands-on</a> 與 <a href="/blog/backend/01-database/vendors/sqlite/hands-on/" data-link-title="SQLite Hands-on 操作路線" data-link-desc="SQLite local file lab、backup / restore drill、WAL busy reproduction、migration fixture、D1 / Turso preview 的操作型章節設計">SQLite hands-on</a>。後續其他 database vendor 也要先建立 hands-on 入口，再依服務責任決定是否補完整操作正文。</p>
<h2 id="migration-playbook-規格">Migration Playbook 規格</h2>
<p>Migration playbook 的責任是處理跨 vendor、跨 topology 或跨 operational model 的變更流程。這一層的主體是差異盤點、階段切換、雙軌驗證、cutover、rollback / fail-forward 與 cleanup；它應作為獨立流程教材，而非 deep article 的長版或 vendor overview 的補充段。</p>
<table>
  <thead>
      <tr>
          <th>規格面</th>
          <th>必答問題</th>
          <th>交付形態</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Driver</td>
          <td>為什麼要遷，壓力來自成本、容量、合規、operation 還是 paradigm</td>
          <td>開場 driver、no-go condition、替代方案</td>
      </tr>
      <tr>
          <td>Diff audit</td>
          <td>source / target 在 schema、operation、paradigm、component、application、topology 哪裡不同</td>
          <td>6 維 audit、主導差異、type 判定</td>
      </tr>
      <tr>
          <td>Phase plan</td>
          <td>哪些工作能分段，哪些工作必須 parallel run 或長期混合</td>
          <td>phase、stream、owner、驗證門檻</td>
      </tr>
      <tr>
          <td>Evidence</td>
          <td>每個階段用什麼資料證明可前進</td>
          <td>validation query、row count、lag、error budget、cost</td>
      </tr>
      <tr>
          <td>Cutover</td>
          <td>什麼條件下切流，切流期間誰決策</td>
          <td>cutover window、rollback condition、decision log route</td>
      </tr>
      <tr>
          <td>Cleanup</td>
          <td>哪些舊路徑能退役，哪些證據要保留</td>
          <td>contract removal、backup retention、incident write-back</td>
      </tr>
  </tbody>
</table>
<p>Driver 段要先排除「因為新服務比較好」這類空泛動機。有效 driver 通常是單機 primary 上限、connection limit、replication lag、backup / restore 責任、multi-region residency、vendor operation transfer、schema feature gap 或成本曲線。</p>
<p>Diff audit 段要先決定 playbook type。MySQL → PostgreSQL 主要是 schema / dialect 差；PostgreSQL → Aurora 主要是 operational redesign；PostgreSQL → CockroachDB 或 Aurora DSQL 主要是 paradigm shift；partition redesign 是 topology re-layout。type 決定結構，不用把所有 playbook 壓成同一套 phase。</p>
<p>Phase plan 段要把不可逆動作放晚。Schema audit、application compatibility、shadow read、dual-write、backfill、CDC catch-up、read-only cutover 與 cleanup 要分出驗證門檻；長期混合架構要明確標示哪些 workload 保留在 source。</p>
<p>Evidence 段要把資料庫遷移接回 observability 與 reliability。Playbook 應要求 row count、checksum、replication lag、error rate、query latency、data quality 與 owner；這些 evidence 是 release gate、incident decision log 與 rollback 判斷的共同材料。</p>
<p>Cutover 段要把決策權責寫清楚。資料庫切流失敗通常代價高，正文要標示切流窗口、暫停條件、回退條件、資料凍結策略與 decision owner，並連到 <a href="/blog/backend/knowledge-cards/rollback-window/" data-link-title="Rollback Window" data-link-desc="說明變更進入 production 後還能用哪種方式回退或改路線的時間與條件">rollback window</a> 或 <a href="/blog/backend/knowledge-cards/rollback-condition/" data-link-title="Rollback Condition" data-link-desc="說明決策執行後出現哪些訊號時要撤回、回退或改路線">rollback condition</a>。</p>
<p>Cleanup 段要防止雙軌永久殘留。舊 schema、舊 writer、舊 CDC connector、舊 backup、舊 dashboard 與舊 runbook 都需要退役判準；資料保留、稽核與 incident write-back 要在 cleanup 前確認。</p>
<h2 id="從-postgresql--mysql-回收的調整項">從 PostgreSQL / MySQL 回收的調整項</h2>
<p>PostgreSQL 與 MySQL 的正文已經足以讓其他服務頁開寫。下一輪調整應集中在橫向品質；SQL baseline 可維持現有正文作為後續服務頁的比較基準。</p>
<h3 id="postgresql">PostgreSQL</h3>
<p>PostgreSQL 的下一輪擴充重點是補安全、災難復原與 managed variant。<a href="/blog/backend/01-database/vendors/postgresql/security-rls-audit-logging/" data-link-title="PostgreSQL Security / RLS / Audit Logging" data-link-desc="PostgreSQL role、grant、Row Level Security、pgAudit、log policy、PII access evidence 與合規路由">Security / RLS / audit logging</a> 可以連到資料保護與稽核章節；<a href="/blog/backend/01-database/vendors/postgresql/cross-region-dr/" data-link-title="PostgreSQL Cross-region DR" data-link-desc="PostgreSQL 跨區災難復原、physical replica、logical replication、backup restore、RPO / RTO 與 failover runbook">cross-region DR</a> 可以連到 reliability 與 incident decision；<a href="/blog/backend/01-database/vendors/postgresql/managed-pg-comparison/" data-link-title="Managed PostgreSQL Comparison" data-link-desc="RDS PostgreSQL、Aurora PostgreSQL、Cloud SQL、Azure Database for PostgreSQL、Neon、Supabase、Crunchy Bridge 的責任邊界比較">Managed PG Comparison</a> 與 <a href="/blog/backend/01-database/vendors/postgresql/specialized-pg-variants/" data-link-title="Specialized PostgreSQL Variants" data-link-desc="pgvectorscale、Citus、TimescaleDB、PostGIS、AlloyDB、Cosmos DB for PostgreSQL、serverless PG 等 PostgreSQL 變體的選型邊界">Specialized PostgreSQL Variants</a> 承接 AlloyDB、Cloud SQL、Cosmos DB for PostgreSQL 與 pgvectorscale。</p>
<p>PostgreSQL 的既有 limitation 已經標示 PG-favoring narrative 與時間敏感 claim。後續補文時要保留對手 vendor 的強項，例如專業 vector DB 的 scale、專業 time-series DB 的 ingestion、distributed SQL 的 global consistency 與 managed 平台的 operation transfer。</p>
<h3 id="mysql">MySQL</h3>
<p>MySQL 的下一輪擴充重點是補 anti-recommendation 與真實 case anchor。多數 deep article 已經有 production 踩雷，但還要加上「何時暫時不用這個機制」的段落，讓讀者知道維持單 primary、簡單 replication、原生 partition 或標準 backup 何時更划算；security、audit、Document Store、multi-source replication、HeatWave、memory contention 與 metadata lock 已先建立 outline 路由。</p>
<p>MySQL 的案例段要把 GitHub、Shopify、Slack、YouTube / Vitess 這些業界來源升級成具體 anchor。案例不只列公司名稱，還要回收它提供的流量形狀、<a href="/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">database sharding</a> 策略、schema change 壓力、failover 責任或工具演化原因。</p>
<h2 id="後續服務撰寫順序">後續服務撰寫順序</h2>
<p>後續服務撰寫順序要從 SQL baseline 推進到資料模型與操作責任差異。每一篇先完成 vendor overview，再依 overview 暴露出的機制缺口決定 deep article 或 migration playbook。</p>
<table>
  <thead>
      <tr>
          <th>批次</th>
          <th>服務</th>
          <th>開寫重點</th>
          <th>升級條件</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>DB2</td>
          <td>SQLite</td>
          <td>embedded formal state、local data、testing DB、backup 邊界</td>
          <td>local-first sync、edge deployment 或 file corruption</td>
      </tr>
      <tr>
          <td>DB3</td>
          <td>MongoDB / DynamoDB</td>
          <td>document shape、access pattern、partition key、capacity mode</td>
          <td>shard expansion、Atlas migration、<a href="/blog/backend/knowledge-cards/hot-partition/" data-link-title="Hot Partition" data-link-desc="說明分散式 KV / OLTP 中、單一 partition 流量遠超其他的容量問題">hot partition</a></td>
      </tr>
      <tr>
          <td>DB4</td>
          <td>Aurora</td>
          <td>managed SQL、storage / compute 分離、failover、cost model</td>
          <td>PostgreSQL / MySQL 遷移、I/O-Optimized cost</td>
      </tr>
      <tr>
          <td>DB5</td>
          <td>Spanner / Cosmos DB</td>
          <td>global consistency、multi-region latency、consistency level</td>
          <td>regional rollout、API model migration</td>
      </tr>
      <tr>
          <td>DB6</td>
          <td>CockroachDB</td>
          <td>distributed SQL、transaction retry、range lease、compatibility</td>
          <td>PostgreSQL migration、multi-region topology</td>
      </tr>
  </tbody>
</table>
<p>SQLite 的重點是讓讀者知道單機正式狀態何時成立。它不應被寫成小型 PostgreSQL，而要處理 file lifecycle、embedded process boundary、backup、concurrency、migration 與測試資料責任。</p>
<p>MongoDB / DynamoDB 的重點是把資料形狀放在 SQL baseline 之後。MongoDB 應教 document shape、index、schema governance 與 transaction boundary；DynamoDB 應教 access pattern、partition key、capacity mode、<a href="/blog/backend/knowledge-cards/hot-partition/" data-link-title="Hot Partition" data-link-desc="說明分散式 KV / OLTP 中、單一 partition 流量遠超其他的容量問題">hot partition</a> 與 connection-free scaling。</p>
<p>Aurora 的重點是 operation transfer。它把 PostgreSQL / MySQL 相容介面放進 AWS-managed operational model；storage / compute 分離、cluster endpoint、replica、backup、failover、cost model 與 AWS 限制都會改變團隊責任。</p>
<p>Spanner / Cosmos DB 的重點是 global data responsibility。Spanner 應教 TrueTime、strong consistency、multi-region latency 與 cost；Cosmos DB 應教 consistency level、API model、partition、RU 與 Azure 約束。</p>
<p>CockroachDB 的重點是 distributed SQL 對 application contract 的影響。SQL 相容降低導入門檻，但 transaction retry、range lease、hot range、schema feature gap 與 multi-region topology 會改變 application 與 SRE 的責任。</p>
<h2 id="llm-depth-下一輪擴章-backlog">LLM-depth 下一輪擴章 Backlog</h2>
<p>LLM-depth 下一輪的責任是把每個資料庫服務從 T1 overview 推進到可教學的章節群。Overview 只回答第一輪服務判斷；deep article 回答穩定運作與排錯；migration playbook 回答跨 vendor、跨 topology 或跨 operational model 變更。</p>
<table>
  <thead>
      <tr>
          <th>服務</th>
          <th>目前狀態</th>
          <th>下一篇 deep article</th>
          <th>升級 playbook 候選</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>SQLite</td>
          <td>T1 overview 已完成</td>
          <td><a href="/blog/backend/01-database/vendors/sqlite/teaching-structure/" data-link-title="SQLite Teaching Structure" data-link-desc="SQLite 服務章節群的大綱：從 embedded formal state、WAL、backup、test fixture、local-first、edge SQLite 到遷移路由">teaching structure</a> + <a href="/blog/backend/01-database/vendors/sqlite/file-lifecycle-backup-boundary/" data-link-title="SQLite file lifecycle 與 backup boundary" data-link-desc="把 SQLite 單檔案正式狀態拆成 WAL、backup API、restore drill、corruption recovery 與操作責任邊界">file lifecycle / backup boundary</a></td>
          <td><a href="/blog/backend/01-database/vendors/sqlite/migrate-to-postgresql/" data-link-title="SQLite to PostgreSQL Migration" data-link-desc="SQLite 升級到 PostgreSQL 的 driver、schema diff、data copy、dual run、cutover、rollback 與 cleanup">SQLite → PostgreSQL</a>、<a href="/blog/backend/01-database/vendors/sqlite/migrate-to-d1-turso/" data-link-title="SQLite to D1 / Turso Migration" data-link-desc="SQLite 轉向 Cloudflare D1、Turso / libSQL 的 edge driver、compatibility audit、data movement 與 rollback">SQLite → D1 / Turso</a></td>
      </tr>
      <tr>
          <td>MongoDB</td>
          <td>T1 overview 已完成</td>
          <td>document shape governance、index / shard key</td>
          <td>self-managed → Atlas、document model → relational split</td>
      </tr>
      <tr>
          <td>DynamoDB</td>
          <td>T1 overview 已完成</td>
          <td>partition key / hot partition、capacity mode</td>
          <td>DynamoDB → SQL / search / analytics split</td>
      </tr>
      <tr>
          <td>Aurora</td>
          <td>T1 overview 已完成</td>
          <td>failover / endpoint routing、I/O cost model</td>
          <td>PostgreSQL / MySQL → Aurora、Aurora → distributed SQL</td>
      </tr>
      <tr>
          <td>Spanner</td>
          <td>T1 overview 已完成</td>
          <td>TrueTime / transaction latency、multi-region topology</td>
          <td>regional SQL → Spanner</td>
      </tr>
      <tr>
          <td>Cosmos DB</td>
          <td>T1 overview 已完成</td>
          <td>consistency level / RU budgeting、partitioning</td>
          <td>API model migration、Cosmos DB → specialized store</td>
      </tr>
      <tr>
          <td>CockroachDB</td>
          <td>T1 overview 已完成</td>
          <td>transaction retry、range split / leaseholder</td>
          <td>PostgreSQL → CockroachDB、single-region → multi-region</td>
      </tr>
  </tbody>
</table>
<p>Backlog 的排序以學習梯度為準。SQLite 先處理單檔案正式狀態，補足「低操作成本如何 production 化」；MongoDB / DynamoDB 再處理資料形狀與 access pattern；Aurora 接 SQL operation transfer；Spanner、Cosmos DB 與 CockroachDB 最後處理 distributed consistency 與 multi-region topology。</p>
<h2 id="規格檢查清單">規格檢查清單</h2>
<p>資料庫 vendor 文章完成前要跑一次規格檢查。檢查通過代表本次內容可作為後續服務的基準；未通過時，先修正文再開下一篇。</p>
<ul>
<li>Vendor overview 已說清楚服務責任、資料形狀、一致性、操作責任、替代邊界、案例與 limitation。</li>
<li>Deep article 已包含問題情境、核心機制、操作流程、失敗模式、容量與觀測、邊界與整合。</li>
<li>Migration playbook 已完成 driver、diff audit、phase plan、evidence、cutover 與 cleanup。</li>
<li>表格後有情境化說明，沒有讓表格取代判讀。</li>
<li>案例提供壓力、失敗代價或回退條件，不只列公司名稱。</li>
<li>「何時不用」或 no-go condition 已出現在 deep article / migration playbook。</li>
<li>Time-sensitive vendor claim 有日期語境或指向官方文件。</li>
<li>下一步路由能接回主章、knowledge card、04 / 06 / 08 / 09 或 sibling vendor。</li>
</ul>
]]></content:encoded></item><item><title>Atlassian Statuspage → Instatus：status page 成本下降、但 compatibility audit 不能跳</title><link>https://tarrragon.github.io/blog/backend/08-incident-response/vendors/atlassian-statuspage/migrate-to-instatus/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/08-incident-response/vendors/atlassian-statuspage/migrate-to-instatus/</guid><description>&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>項目&lt;/th>
 &lt;th>Atlassian Statuspage（Business / Enterprise）&lt;/th>
 &lt;th>Instatus（Pro / Business）&lt;/th>
 &lt;th>差距判讀&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>月費&lt;/td>
 &lt;td>Business 約 $399/mo、Enterprise 約 $1,499/mo 起&lt;/td>
 &lt;td>Pro 約 $20/mo、Business 約 $300/mo&lt;/td>
 &lt;td>savings 取決於 target tier&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Custom domain + SSL&lt;/td>
 &lt;td>內建&lt;/td>
 &lt;td>Free tier 起就含&lt;/td>
 &lt;td>持平&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Subscriber 上限&lt;/td>
 &lt;td>依 tier 提升&lt;/td>
 &lt;td>Pro 約 5,000 subscriber、Business 約 25,000 subscriber&lt;/td>
 &lt;td>需對齊現有 subscriber 數&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Component 上限&lt;/td>
 &lt;td>依 tier 提升&lt;/td>
 &lt;td>Pro 有上限、Business 放寬&lt;/td>
 &lt;td>大型 page 要逐項確認&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Notification channel&lt;/td>
 &lt;td>Email / SMS / Slack / Teams / webhook / RSS / Atom&lt;/td>
 &lt;td>Email / SMS / Slack / Discord / Teams / Telegram / RSS / Webhook&lt;/td>
 &lt;td>Instatus 多 chat channel&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Metrics 圖表&lt;/td>
 &lt;td>Datadog / Pingdom / New Relic / Library&lt;/td>
 &lt;td>Datadog / Pingdom / New Relic / StatusCake / API&lt;/td>
 &lt;td>payload / auth 要重接&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>SAML SSO&lt;/td>
 &lt;td>Enterprise tier&lt;/td>
 &lt;td>Business tier&lt;/td>
 &lt;td>不是產品缺口、是 tier 差異&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Audit / activity log&lt;/td>
 &lt;td>Enterprise / team governance 能力&lt;/td>
 &lt;td>需依 plan 確認&lt;/td>
 &lt;td>強合規要逐項驗證&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>SLA / uptime report&lt;/td>
 &lt;td>內建能力較成熟&lt;/td>
 &lt;td>需確認 plan 或外接&lt;/td>
 &lt;td>contract deliverable 要驗證&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>API parity&lt;/td>
 &lt;td>完整 REST&lt;/td>
 &lt;td>REST API&lt;/td>
 &lt;td>endpoint / schema 不同&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>成本差距是這條 migration 的 &lt;em>driver&lt;/em>、但表格右側的 tier 差異是 &lt;em>blocker candidate&lt;/em>。對 &lt;em>不需要 Enterprise governance / 強 SLA reporting / 深 Atlassian 整合&lt;/em> 的中小 SaaS、從 Statuspage Business / Enterprise 降到 Instatus Pro / Business 可以有明顯 savings、cutover 工作量通常落在 1-4 週；對 &lt;em>enterprise 強合規&lt;/em> 的場景、SSO、audit、reporting 與可用性承諾任一不能讓步時、migration 要先停在 compatibility audit。&lt;/p></description><content:encoded><![CDATA[<table>
  <thead>
      <tr>
          <th>項目</th>
          <th>Atlassian Statuspage（Business / Enterprise）</th>
          <th>Instatus（Pro / Business）</th>
          <th>差距判讀</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>月費</td>
          <td>Business 約 $399/mo、Enterprise 約 $1,499/mo 起</td>
          <td>Pro 約 $20/mo、Business 約 $300/mo</td>
          <td>savings 取決於 target tier</td>
      </tr>
      <tr>
          <td>Custom domain + SSL</td>
          <td>內建</td>
          <td>Free tier 起就含</td>
          <td>持平</td>
      </tr>
      <tr>
          <td>Subscriber 上限</td>
          <td>依 tier 提升</td>
          <td>Pro 約 5,000 subscriber、Business 約 25,000 subscriber</td>
          <td>需對齊現有 subscriber 數</td>
      </tr>
      <tr>
          <td>Component 上限</td>
          <td>依 tier 提升</td>
          <td>Pro 有上限、Business 放寬</td>
          <td>大型 page 要逐項確認</td>
      </tr>
      <tr>
          <td>Notification channel</td>
          <td>Email / SMS / Slack / Teams / webhook / RSS / Atom</td>
          <td>Email / SMS / Slack / Discord / Teams / Telegram / RSS / Webhook</td>
          <td>Instatus 多 chat channel</td>
      </tr>
      <tr>
          <td>Metrics 圖表</td>
          <td>Datadog / Pingdom / New Relic / Library</td>
          <td>Datadog / Pingdom / New Relic / StatusCake / API</td>
          <td>payload / auth 要重接</td>
      </tr>
      <tr>
          <td>SAML SSO</td>
          <td>Enterprise tier</td>
          <td>Business tier</td>
          <td>不是產品缺口、是 tier 差異</td>
      </tr>
      <tr>
          <td>Audit / activity log</td>
          <td>Enterprise / team governance 能力</td>
          <td>需依 plan 確認</td>
          <td>強合規要逐項驗證</td>
      </tr>
      <tr>
          <td>SLA / uptime report</td>
          <td>內建能力較成熟</td>
          <td>需確認 plan 或外接</td>
          <td>contract deliverable 要驗證</td>
      </tr>
      <tr>
          <td>API parity</td>
          <td>完整 REST</td>
          <td>REST API</td>
          <td>endpoint / schema 不同</td>
      </tr>
  </tbody>
</table>
<p>成本差距是這條 migration 的 <em>driver</em>、但表格右側的 tier 差異是 <em>blocker candidate</em>。對 <em>不需要 Enterprise governance / 強 SLA reporting / 深 Atlassian 整合</em> 的中小 SaaS、從 Statuspage Business / Enterprise 降到 Instatus Pro / Business 可以有明顯 savings、cutover 工作量通常落在 1-4 週；對 <em>enterprise 強合規</em> 的場景、SSO、audit、reporting 與可用性承諾任一不能讓步時、migration 要先停在 compatibility audit。</p>
<p>這篇是 Type B drop-in migration playbook、結構順序是：先跑 <em>compatibility audit</em>（確認 gap 都可接受）→ 再進 cutover。Type B 看起來簡單、但跳過 audit 直接切是這 batch 第三常見的事故來源。</p>
<h2 id="為什麼是-type-b全-low">為什麼是 Type B（全 Low）</h2>
<p>跑 <a href="/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/#6-%e7%b6%ad-diff-dimension-audit" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">6 維 diff dimension audit</a>：</p>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>評</th>
          <th>說明</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Schema</td>
          <td>Low</td>
          <td>component / incident / subscriber model 接近一致、欄位名稱 1:1</td>
      </tr>
      <tr>
          <td>Operational</td>
          <td>Low</td>
          <td>都是 public status page + notification、ops 模型相同</td>
      </tr>
      <tr>
          <td>Paradigm</td>
          <td>Low</td>
          <td>同 paradigm（public service status disclosure）</td>
      </tr>
      <tr>
          <td>Components</td>
          <td>Low</td>
          <td>都是單一 SaaS</td>
      </tr>
      <tr>
          <td>App change</td>
          <td>Low</td>
          <td>API 端點換、payload 接近一致</td>
      </tr>
      <tr>
          <td>Topology</td>
          <td>Low</td>
          <td>都是 cloud SaaS</td>
      </tr>
  </tbody>
</table>
<p>全 Low → <strong>Type B drop-in + compatibility audit prefix</strong>。</p>
<h2 id="compatibility-audit-prefix">Compatibility audit prefix</h2>
<p>切換前先跑 audit、確認以下 9 項 <em>對自己的 case 是否可接受</em>。任一項是 <em>no</em>、回頭評估是否真要遷：</p>
<h3 id="1-subscriber-channel-完整度">1. Subscriber channel 完整度</h3>
<p>Statuspage 主要 channel：Email、SMS、Slack、Microsoft Teams、Webhook、RSS、Atom。Instatus 多了 Discord 跟 Telegram、少了 Atom（RSS 仍在）。</p>
<ul>
<li>確認現有 subscriber 用的 channel 都在 Instatus 支援列表</li>
<li>特別注意 <em>legacy RSS Atom feed reader</em> — 有些 monitoring service 用 Atom 訂閱、要改成 RSS 或 webhook</li>
</ul>
<h3 id="2-saml-sso">2. SAML SSO</h3>
<p>SAML SSO 是 <em>tier decision</em>、不是單純產品有無。Statuspage 把 SAML 放在較高 tier；Instatus 也在 Business tier 提供 SAML。真正要判斷的是：成本 savings 是否仍成立、以及 IdP / SCIM / role mapping 是否符合 audit 要求。</p>
<ul>
<li>確認 target Instatus plan 是否包含 SAML</li>
<li>確認 IdP / group / role mapping 是否能對上現有 audit requirement</li>
<li>如果 savings 只在 Pro tier 成立、但 compliance 要 SAML，就不能用 Pro tier 當 ROI 基準</li>
</ul>
<h3 id="3-audit-log">3. Audit log</h3>
<p>Audit log 是 governance surface。誰 publish 哪則 incident、誰改了哪個 component status、誰匯入 subscriber，這些事件在 Statuspage Enterprise / Instatus Business 類 plan 的支援深度與匯出能力要逐項比對。</p>
<ul>
<li>確認 status page 變更是否需要 internal audit trail</li>
<li>確認 target plan 是否能查詢、匯出與保留 admin activity</li>
<li>金融 / 醫療場景要把 audit retention 與 evidence export 放進 go/no-go gate</li>
</ul>
<h3 id="4-sla--uptime-report-自動產出">4. SLA / uptime report 自動產出</h3>
<p>SLA / uptime report 是 customer contract surface。Statuspage 的 enterprise workflow 通常更成熟；Instatus 是否能直接覆蓋，要看 plan、API 與既有客戶報表格式。</p>
<ul>
<li>如果 contract 寫了「每月 SLA report 自動推送客戶」、Instatus 要外接補這條</li>
<li>評估外接成本（一條 cron + 一個 BI dashboard、3-5 天工程）vs Statuspage 內建</li>
</ul>
<h3 id="5-可用性承諾與-provider-outage">5. 可用性承諾與 provider outage</h3>
<p>Status page provider 本身的可用性承諾是 compatibility audit 的一部分。強合規或大型 customer-facing page 要確認 provider SLA、status page provider 自身 outage 時的 fallback、以及是否需要獨立備援頁。</p>
<ul>
<li>多數場景能接受 status page provider 跟自己 service 不同供應商已經足夠</li>
<li>強合規 + 「status page must never be down」場景要設獨立 fallback，而不是只比較 UI 功能</li>
</ul>
<h3 id="6-metrics-integration-來源">6. Metrics integration 來源</h3>
<p>兩家都接 Datadog / Pingdom / New Relic / StatusCake / Library API。Instatus 多了 StatusCake、少了某些 Statuspage 內建 library。</p>
<ul>
<li>確認當前 metrics 顯示圖表的 source 在 Instatus 支援列表</li>
<li>特別注意 <em>custom metrics from API</em>（自家 push 上去的）— 兩家都支援、payload 格式不同、要重寫 push script</li>
</ul>
<h3 id="7-custom-css--branding-完整度">7. Custom CSS / branding 完整度</h3>
<p>Statuspage Enterprise 允許 <em>完整 custom CSS override</em>、Instatus Pro / Team 允許 <em>theme customization</em>（颜色 / logo / font）但 <em>不允許任意 CSS injection</em>。</p>
<ul>
<li>如果有大量 custom CSS 跟既有品牌 site 視覺 1:1 對齊、Instatus 可能達不到、要評估視覺退讓</li>
<li>大多數 status page 視覺 ≠ 主 product site、退讓常見</li>
</ul>
<h3 id="8-api-parity-跟自動化-hook">8. API parity 跟自動化 hook</h3>
<p>兩家都有完整 REST API（create incident、update component status、push subscriber）。但 <em>endpoint URL / auth scheme / payload schema 不同</em>：</p>
<ul>
<li>Statuspage：<code>https://api.statuspage.io/v1/pages/{page_id}/...</code>、OAuth bearer token</li>
<li>Instatus：<code>https://api.instatus.com/v1/{page_id}/...</code>、API key header</li>
</ul>
<p>如果有 <em>從 IR 平台（incident.io / Rootly / FireHydrant / 自製 webhook）push status update</em> 的自動化、要重寫對接、估算 2-5 天工程。</p>
<h3 id="9-atlassian-生態整合opsgenie--jsm--confluence">9. Atlassian 生態整合（Opsgenie / JSM / Confluence）</h3>
<p>Statuspage 跟 Opsgenie / JSM / Confluence 同生態、有原生整合（Opsgenie incident → Statuspage incident draft、Confluence post-mortem auto-link）。Instatus 跟 Atlassian 沒原生整合、要走 webhook。</p>
<ul>
<li>如果 Atlassian 整合是核心 workflow、評估走 webhook 工作量</li>
<li>如果是 incident.io / Rootly / FireHydrant 主用、Instatus 反而有原生整合（這條變優勢）</li>
</ul>
<h2 id="cutover-階段">Cutover 階段</h2>
<p>Audit 全過後、Type B drop-in 不需要 11-phase 結構、4 階段：</p>
<h3 id="stage-1setup--parallel-run1-週">Stage 1：Setup + parallel run（1 週）</h3>
<ul>
<li>在 Instatus 開帳號、設 component（先複製 Statuspage 結構 1:1）</li>
<li>設 custom domain + SSL（Instatus 預設 free tier 已含）</li>
<li>接 subscriber channels（先不切 DNS、純內部測試）</li>
<li>用 Instatus API 從 Statuspage export incident history 灌回 Instatus（保留歷史 uptime 連續性）</li>
<li>Parallel run：當前若有 incident、在 Statuspage 跟 Instatus 兩邊都 push、確認 subscriber 在兩邊都收到、UI 都正常</li>
</ul>
<h3 id="stage-2dns-預備1-天">Stage 2：DNS 預備（1 天）</h3>
<ul>
<li>Statuspage custom domain CNAME / ALIAS 預設 TTL 通常 1 小時、提前 48 小時把 TTL 降到 5 分鐘</li>
<li>這步是 minimize cutover window 的關鍵、不做的話 cutover 期間有 1 小時 DNS cache 兩邊 page 不同步</li>
</ul>
<h3 id="stage-3dns-cutover30-分鐘---1-小時">Stage 3：DNS cutover（30 分鐘 - 1 小時）</h3>
<ul>
<li>把 status page custom domain 從 Statuspage CNAME 改指 Instatus CNAME</li>
<li>5 分鐘 TTL 後新流量都進 Instatus</li>
<li>監控 1 小時、確認 subscriber notification 從 Instatus 發出、metrics 圖表 wire 正確、history uptime continuity 沒斷</li>
<li>既有 IR 平台 webhook 改指 Instatus API endpoint</li>
</ul>
<h3 id="stage-4statuspage-關閉2-4-週後">Stage 4：Statuspage 關閉（2-4 週後）</h3>
<ul>
<li>不要立即取消 Statuspage 帳號 — 留 2-4 週作 rollback 緩衝</li>
<li>Subscriber 通知「status page URL 不變、underlying provider 換了」（多數場景不需要、subscriber 不會察覺）</li>
<li>確認 incident history / uptime data 在 Instatus 完整、Statuspage rollback 場景 &lt; 0.5% 後、取消 Statuspage subscription</li>
</ul>
<p>完成標準：DNS 100% 流量在 Instatus、Statuspage subscription 取消、SRE / SaaS provisioning team 不再 maintain Statuspage account。</p>
<h2 id="5-個-production-踩雷">5 個 production 踩雷</h2>
<h3 id="1-sso-tier-選錯導致-admin-login-退化">1. SSO tier 選錯導致 admin login 退化</h3>
<p>audit 漏掉 <em>當前 admin 用 SAML 登入</em> 這個事實、卻用不含 SAML 的 target tier 計算 savings，cutover 後 admin login 被迫退回 email/password + 2FA。修法是 Stage 1 就用含 SAML 的 target plan 測試 IdP、group mapping 與 break-glass admin。對 SOC 2 audit 期間 <em>admin login method 變更要記錄</em>的 org 來說，這是不可預期的 audit finding、要在 Stage 1 就溝通。</p>
<h3 id="2-metrics-圖表來源整合斷">2. Metrics 圖表來源整合斷</h3>
<p>Statuspage 接 Datadog metrics 的 OAuth integration 在 Instatus 要重接、auth flow 重做、Datadog API key 重 provision。常見漏網之魚：</p>
<ul>
<li>跨 region Datadog account（US / EU）integration 重 provision 時 region 沒選對、圖表全空</li>
<li>Pingdom check ID 在新 integration 重新 register、historic data 斷層</li>
<li>自家 push metrics 的 webhook payload schema 不同（Statuspage 是 <code>{component_id, status, ...}</code>、Instatus 是 <code>{componentId, status, ...}</code> camelCase）</li>
</ul>
<p>修法是 Stage 1 parallel run 期間就把所有 metrics integration 在 Instatus wire 通、對比兩邊圖表一致再進 Stage 2。</p>
<h3 id="3-subscriber-import-format-不一致">3. Subscriber import format 不一致</h3>
<p>Statuspage subscriber export CSV 是 <code>email, phone, slack_webhook_url, ...</code> 一行多 channel；Instatus import CSV 是 <code>email\nemail\n...</code> 純 email list、其他 channel 要分開 import。如果有 5000 subscriber 包含 SMS / Slack mix、import 時要拆開、否則 SMS subscriber 會掉。</p>
<p>修法是寫 import script 把 Statuspage CSV 拆成多個 channel-specific CSV、分批 import Instatus。</p>
<h3 id="4-sla-report-月報突然斷">4. SLA report 月報突然斷</h3>
<p>Statuspage 月報自動 push 給客戶、cutover 後 Instatus 沒原生 SLA report、客戶下個月沒收到報表會問。修法是 <em>cutover 前先建外接 SLA report</em>：</p>
<ul>
<li>寫 cron job（per month）從 Instatus API 拉 component uptime data</li>
<li>用簡單 template（Google Doc / PDF generator）產 report</li>
<li>自動 email 推給原 Statuspage SLA report distribution list</li>
</ul>
<p>如果這條 contract 強制、外接成本約 3-5 天工程、要算進 migration 總成本。</p>
<h3 id="5-custom-css--branding-視覺退讓">5. Custom CSS / branding 視覺退讓</h3>
<p>Statuspage Enterprise 有大量 custom CSS、cutover 後 Instatus 視覺對齊不到 1:1。視覺退讓清單通常是：</p>
<ul>
<li>font weight 跟 line-height 微差</li>
<li>mobile breakpoint 不同</li>
<li>incident timeline 排版 spacing 略不同</li>
</ul>
<p>修法是 cutover 前先在 Instatus theme customization 內把能調的調好、能接受的退讓在 Stage 1 跟設計 / brand team 確認、不能接受的就回去 audit Step 7 重新評估是否要遷。</p>
<h2 id="容量與成本對比">容量與成本對比</h2>
<p>對中小 SaaS（3000 subscriber、10 component、月均 2 incident）：</p>
<table>
  <thead>
      <tr>
          <th>項目</th>
          <th>Statuspage Business</th>
          <th>Instatus Pro</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>月費</td>
          <td>約 $399</td>
          <td>約 $20</td>
      </tr>
      <tr>
          <td>Subscriber 上限</td>
          <td>依 plan</td>
          <td>約 5,000</td>
      </tr>
      <tr>
          <td>Component</td>
          <td>依 plan</td>
          <td>有上限</td>
      </tr>
      <tr>
          <td>工程成本（cutover）</td>
          <td>-</td>
          <td>1-4 週</td>
      </tr>
      <tr>
          <td>外接 SLA report</td>
          <td>不需要或較成熟</td>
          <td>0-5 天 / 持續維運</td>
      </tr>
      <tr>
          <td>年化 saving</td>
          <td>-</td>
          <td>約數千美元等級</td>
      </tr>
  </tbody>
</table>
<p>對 enterprise（30000 subscriber、50+ component、強合規）：</p>
<table>
  <thead>
      <tr>
          <th>項目</th>
          <th>Statuspage Enterprise</th>
          <th>Instatus Business / Enterprise</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>月費</td>
          <td>約 $1,499 起或 custom</td>
          <td>低於典型 Enterprise quote</td>
      </tr>
      <tr>
          <td>SAML / Audit log</td>
          <td>必要</td>
          <td>需逐項驗證</td>
      </tr>
      <tr>
          <td>SLA / uptime report</td>
          <td>必要</td>
          <td>需逐項驗證或外接</td>
      </tr>
      <tr>
          <td>結論</td>
          <td>未必適合遷</td>
          <td>先跑 audit、不要只看月費</td>
      </tr>
  </tbody>
</table>
<h2 id="何時不要切">何時不要切</h2>
<ul>
<li><strong>SAML SSO + audit log 是 compliance requirement</strong>：金融 / 醫療 / 政府場景、Statuspage Enterprise 留</li>
<li><strong>SLA report 是 customer contract 強制</strong>：如果 contract 寫明 SLA report deliverable、外接成本 + 風險高、Statuspage 留</li>
<li><strong>Provider availability / fallback 必要</strong>：status page provider 自身 outage 時仍要可訪、先設獨立 fallback 或保留 Enterprise 級 provider</li>
<li><strong>Atlassian 整合（Opsgenie / JSM / Confluence）是核心 workflow</strong>：原生整合斷會多很多 webhook 維護、Statuspage 留</li>
<li><strong>subscriber &gt; 10K + 強客戶 SLA</strong>：規模本身讓 Instatus 風險增大、Statuspage Enterprise 比較穩</li>
</ul>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>平行 batch：<a href="/blog/backend/08-incident-response/vendors/pagerduty/migrate-to-incident-io/" data-link-title="PagerDuty → incident.io：「On-call」是個 retconned word、同名不同 contract" data-link-desc="PagerDuty → incident.io 不是 schema translation — 兩家的「on-call」字面相同、contract 不同（alert routing vs IR coordination &#43; Slack-native &#43; retrospective）。本文走 Type E paradigm shift、6 維 audit 顯示 paradigm / schema / operational 三軸 High、用 4-phase partial migration（不收斂、Phase 1-2 多數 org 停留）、5 個 production 踩雷（雙系統 state drift / severity 翻譯失真 / schedule layer 漏 / Slack channel 過載 / retrospective 斷層）、跟 PagerDuty Process Automation / AIOps 沒對應的 capability gap">PagerDuty → incident.io</a>（Type E paradigm shift）/ <a href="/blog/backend/08-incident-response/vendors/opsgenie/migrate-from-pagerduty/" data-link-title="PagerDuty → Opsgenie：Atlassian 全家桶整合 vs Opsgenie 2027 EOL 的 vendor consolidation 取捨" data-link-desc="PagerDuty → Opsgenie 是 Type A phased schema translation、但 Atlassian 已宣布 Opsgenie 2027-04 EOL — 這條 migration 只在 Atlassian-heavy org &#43; 明確 JSM unification roadmap 下成立、本質是 PD → Opsgenie → JSM Cloud 的雙 hop migration。本文走 6 維 audit（Schema Medium-High 其他 Low）、PagerDuty ↔ Opsgenie ↔ JSM field mapping 對照、5 production 踩雷（escalation step / Heartbeat 缺對應 / integration key dedup 重設 / schedule 時區 / Atlassian Identity SSO 整合）、何時直接走 PD → JSM 跳過 Opsgenie">PagerDuty → Opsgenie</a>（Type A schema translation）</li>
<li>同 batch Type B：（待補、本篇是 batch 唯一 Type B）</li>
<li>vendor 對照：<a href="/blog/backend/08-incident-response/vendors/atlassian-statuspage/" data-link-title="Atlassian Statuspage" data-link-desc="公開狀態頁 SaaS、Atlassian 出品、enterprise polish &#43; Atlassian 生態整合、subscriber notification &#43; component dependency 是核心責任">Atlassian Statuspage</a> / <a href="/blog/backend/08-incident-response/vendors/instatus/" data-link-title="Instatus" data-link-desc="輕量 status page SaaS、現代 UI、價格敏感替代">Instatus</a></li>
<li>方法論：<a href="/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">Migration Playbook Methodology</a>（Type B drop-in + compatibility audit prefix 結構說明）</li>
</ul>
]]></content:encoded></item><item><title>JMeter → k6：k6 不是 JMeter 的「script 版本」、是 VU model 取代 thread model</title><link>https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/k6/migrate-from-jmeter/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/k6/migrate-from-jmeter/</guid><description>&lt;p>k6 不是 JMeter 的 &lt;em>「script 版本」&lt;/em>。&lt;/p>
&lt;p>這個誤解是 JMeter → k6 migration 第一週最常見的事故來源。Migration 啟動會議常聽到「JMeter 的 thread group 翻成 k6 的 VU 就好了吧」、然後團隊把 &lt;code>.jmx&lt;/code> 內 100 thread → k6 &lt;code>vus: 100&lt;/code>、跑下去發現 RPS 差三倍、p95 延遲表完全不同形狀、以為 k6 壞了。&lt;/p>
&lt;p>實際上 k6 的 &lt;em>Virtual User (VU)&lt;/em> 跟 JMeter 的 &lt;em>Thread&lt;/em> 是 &lt;em>兩種不同的使用者行為建模方式&lt;/em>：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>JMeter Thread&lt;/strong>：一個 OS thread = 一個 user、&lt;code>numThreads=100&lt;/code> 就 &lt;em>固定 100 個 concurrent 使用者一直跑&lt;/em>、ramp-up period 控制怎麼啟動、無 explicit arrival rate 概念&lt;/li>
&lt;li>&lt;strong>k6 VU&lt;/strong>：一個 goroutine-like execution context、預設 &lt;code>vus&lt;/code> 是 &lt;em>concurrent VU pool&lt;/em>、但 k6 更推薦用 &lt;code>arrival-rate executor&lt;/code> — 直接表達 &lt;em>每秒進來幾個 request&lt;/em>、VU 是 &lt;em>為了達到 arrival rate 動態起的 worker&lt;/em>&lt;/li>
&lt;/ul>
&lt;p>差別在 &lt;em>測量視角&lt;/em>：JMeter 預設視角是 &lt;em>「我有 100 個使用者在用系統」&lt;/em>、k6 預設視角是 &lt;em>「我每秒有 N 個請求進來」&lt;/em>。兩種視角下 &lt;em>同一個系統的瓶頸結果完全不同&lt;/em>：100 concurrent user 模型在 server 慢時 throughput 會自動降（user 等回應）、100 RPS arrival rate 模型在 server 慢時 queue 會累積、暴露 &lt;em>真實 production behavior&lt;/em>（user 不會體諒、會繼續送請求）。&lt;/p>
&lt;p>這篇 migration playbook 不是 schema translation 文（&lt;code>.jmx&lt;/code> 翻成 &lt;code>.js&lt;/code> 只是表面）、是 &lt;em>paradigm shift&lt;/em> — 從 closed-system model（thread）到 open-system model（arrival rate）的視角轉換。&lt;/p>
&lt;h2 id="為什麼是-type-eschema--paradigm-同-high">為什麼是 Type E（schema + paradigm 同 High）&lt;/h2>
&lt;p>跑 &lt;a href="https://tarrragon.github.io/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/#6-%e7%b6%ad-diff-dimension-audit" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">6 維 diff dimension audit&lt;/a>：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>維度&lt;/th>
 &lt;th>評&lt;/th>
 &lt;th>說明&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Schema&lt;/td>
 &lt;td>High&lt;/td>
 &lt;td>&lt;code>.jmx&lt;/code> XML vs JavaScript scenario、test plan 完全不同 file format / DSL&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Operational&lt;/td>
 &lt;td>Medium&lt;/td>
 &lt;td>CLI / distributed run 接近、CI integration 差別大、distributed runner 模型不同&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Paradigm&lt;/td>
 &lt;td>High&lt;/td>
 &lt;td>thread group closed model → arrival rate open model、測試思維不同&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Components&lt;/td>
 &lt;td>Low&lt;/td>
 &lt;td>都是 load test runner、no multi-tool decomposition&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>App change&lt;/td>
 &lt;td>N/A&lt;/td>
 &lt;td>是 test code、不是 production code&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Topology&lt;/td>
 &lt;td>Low&lt;/td>
 &lt;td>都是 CLI / runner 跑、無 sharding&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>Schema High + Paradigm High 兩軸 High。按優先序 Schema &amp;gt; Paradigm、預設選 Type A。但對 JMeter → k6 的讀者來說、&lt;em>paradigm shift 才是難關&lt;/em> — schema translation 是工作量、但搞錯 paradigm 會讓 migration 後的測試結果 &lt;em>跟 production 不對應&lt;/em>。所以選 &lt;strong>Type E paradigm shift&lt;/strong> 結構、schema translation 抽出 Phase 1-2 補充。&lt;/p></description><content:encoded><![CDATA[<p>k6 不是 JMeter 的 <em>「script 版本」</em>。</p>
<p>這個誤解是 JMeter → k6 migration 第一週最常見的事故來源。Migration 啟動會議常聽到「JMeter 的 thread group 翻成 k6 的 VU 就好了吧」、然後團隊把 <code>.jmx</code> 內 100 thread → k6 <code>vus: 100</code>、跑下去發現 RPS 差三倍、p95 延遲表完全不同形狀、以為 k6 壞了。</p>
<p>實際上 k6 的 <em>Virtual User (VU)</em> 跟 JMeter 的 <em>Thread</em> 是 <em>兩種不同的使用者行為建模方式</em>：</p>
<ul>
<li><strong>JMeter Thread</strong>：一個 OS thread = 一個 user、<code>numThreads=100</code> 就 <em>固定 100 個 concurrent 使用者一直跑</em>、ramp-up period 控制怎麼啟動、無 explicit arrival rate 概念</li>
<li><strong>k6 VU</strong>：一個 goroutine-like execution context、預設 <code>vus</code> 是 <em>concurrent VU pool</em>、但 k6 更推薦用 <code>arrival-rate executor</code> — 直接表達 <em>每秒進來幾個 request</em>、VU 是 <em>為了達到 arrival rate 動態起的 worker</em></li>
</ul>
<p>差別在 <em>測量視角</em>：JMeter 預設視角是 <em>「我有 100 個使用者在用系統」</em>、k6 預設視角是 <em>「我每秒有 N 個請求進來」</em>。兩種視角下 <em>同一個系統的瓶頸結果完全不同</em>：100 concurrent user 模型在 server 慢時 throughput 會自動降（user 等回應）、100 RPS arrival rate 模型在 server 慢時 queue 會累積、暴露 <em>真實 production behavior</em>（user 不會體諒、會繼續送請求）。</p>
<p>這篇 migration playbook 不是 schema translation 文（<code>.jmx</code> 翻成 <code>.js</code> 只是表面）、是 <em>paradigm shift</em> — 從 closed-system model（thread）到 open-system model（arrival rate）的視角轉換。</p>
<h2 id="為什麼是-type-eschema--paradigm-同-high">為什麼是 Type E（schema + paradigm 同 High）</h2>
<p>跑 <a href="/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/#6-%e7%b6%ad-diff-dimension-audit" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">6 維 diff dimension audit</a>：</p>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>評</th>
          <th>說明</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Schema</td>
          <td>High</td>
          <td><code>.jmx</code> XML vs JavaScript scenario、test plan 完全不同 file format / DSL</td>
      </tr>
      <tr>
          <td>Operational</td>
          <td>Medium</td>
          <td>CLI / distributed run 接近、CI integration 差別大、distributed runner 模型不同</td>
      </tr>
      <tr>
          <td>Paradigm</td>
          <td>High</td>
          <td>thread group closed model → arrival rate open model、測試思維不同</td>
      </tr>
      <tr>
          <td>Components</td>
          <td>Low</td>
          <td>都是 load test runner、no multi-tool decomposition</td>
      </tr>
      <tr>
          <td>App change</td>
          <td>N/A</td>
          <td>是 test code、不是 production code</td>
      </tr>
      <tr>
          <td>Topology</td>
          <td>Low</td>
          <td>都是 CLI / runner 跑、無 sharding</td>
      </tr>
  </tbody>
</table>
<p>Schema High + Paradigm High 兩軸 High。按優先序 Schema &gt; Paradigm、預設選 Type A。但對 JMeter → k6 的讀者來說、<em>paradigm shift 才是難關</em> — schema translation 是工作量、但搞錯 paradigm 會讓 migration 後的測試結果 <em>跟 production 不對應</em>。所以選 <strong>Type E paradigm shift</strong> 結構、schema translation 抽出 Phase 1-2 補充。</p>
<h2 id="driverdeveloper-ergonomic--ci-gate-friendly">Driver：developer ergonomic + CI gate friendly</h2>
<p>從 JMeter 遷出 k6 的核心拉力是 <em>developer ergonomic + CI 友善</em>：</p>
<ul>
<li><strong><code>.jmx</code> XML 在 git 內 diff 不可讀</strong>：兩個 <code>.jmx</code> PR 的 diff 是 XML attribute reorder noise、reviewer 看不出來實際邏輯改了什麼；JavaScript 是純文字 + AST、PR diff 直接可讀</li>
<li><strong>GUI 學習曲線</strong>：JMeter GUI 不是現代 IDE、不熟的工程師寫一個 scenario 要花半天找對的 sampler 跟 listener；JavaScript 用既有 IDE（VS Code / IntelliJ）、autocomplete + lint + format 全有</li>
<li><strong>CI integration 步驟差</strong>：JMeter 在 CI 跑要 packaging plugin + non-GUI mode + result XML parser；k6 直接 <code>k6 run script.js</code>、result 是 JSON / Prometheus metrics、threshold pass/fail 直接 exit code</li>
<li><strong>單機 VU 容量</strong>：JMeter 單機通常 ~500-1000 thread（受 JVM 跟 OS thread limit）、k6 單機可跑 30K-50K VU（Go runtime + goroutine）、distributed runner 需求降低</li>
<li><strong>Workload model expressiveness</strong>：k6 <code>arrival-rate executor</code> + <code>ramping-vus</code> + <code>constant-vus</code> 三種 executor 直接對應 <em>open system / ramping / closed system</em> 三種測量視角、不像 JMeter 需要組合 Constant Throughput Timer + Synchronizing Timer + thread group 才達到</li>
</ul>
<p>這條 driver 在 <em>QA 團隊 GUI 維護 .jmx asset</em> 的 org 沒拉力（GUI 反而是優勢）、但對 <em>dev / SRE 寫 performance test 進 CI</em> 的 org 是強拉力。Audience 不同、migration value 完全不同。</p>
<h2 id="4-phase-partial-migration不收斂">4-phase partial migration（不收斂）</h2>
<p>Type E 的特徵是 <em>不收斂</em> — 多數 org 不會把 <code>.jmx</code> 全退役、會停在某個 phase 變成 hybrid：</p>
<h3 id="phase-1學會-k6-paradigm不寫實際-test">Phase 1：學會 k6 paradigm（不寫實際 test）</h3>
<p>寫一個 throwaway script 跑當前 production-like API、不為了 migrate、為了搞清楚 k6 paradigm：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kr">import</span> <span class="nx">http</span> <span class="nx">from</span> <span class="s1">&#39;k6/http&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">check</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;k6&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="kr">export</span> <span class="kr">const</span> <span class="nx">options</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">  <span class="c1">// 不要用 vus: 100、用 arrival rate
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="c1"></span>  <span class="nx">scenarios</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="nx">open_model</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">      <span class="nx">executor</span><span class="o">:</span> <span class="s1">&#39;constant-arrival-rate&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">      <span class="nx">rate</span><span class="o">:</span> <span class="mi">100</span><span class="p">,</span>           <span class="c1">// 每秒 100 request
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="c1"></span>      <span class="nx">timeUnit</span><span class="o">:</span> <span class="s1">&#39;1s&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">      <span class="nx">duration</span><span class="o">:</span> <span class="s1">&#39;5m&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">      <span class="nx">preAllocatedVUs</span><span class="o">:</span> <span class="mi">200</span><span class="p">,</span> <span class="c1">// 預先準備 VU 數
</span></span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="c1"></span>      <span class="nx">maxVUs</span><span class="o">:</span> <span class="mi">500</span><span class="p">,</span>          <span class="c1">// 上限
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="c1"></span>    <span class="p">},</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">  <span class="nx">thresholds</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">    <span class="nx">http_req_duration</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;p(95)&lt;500&#39;</span><span class="p">],</span> <span class="c1">// p95 &lt; 500ms
</span></span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="c1"></span>    <span class="nx">http_req_failed</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;rate&lt;0.01&#39;</span><span class="p">],</span>   <span class="c1">// 失敗率 &lt; 1%
</span></span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="c1"></span>  <span class="p">},</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">
</span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="kr">export</span> <span class="k">default</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">  <span class="kr">const</span> <span class="nx">res</span> <span class="o">=</span> <span class="nx">http</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;https://api.example.com/orders&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">  <span class="nx">check</span><span class="p">(</span><span class="nx">res</span><span class="p">,</span> <span class="p">{</span> <span class="s1">&#39;status 200&#39;</span><span class="o">:</span> <span class="p">(</span><span class="nx">r</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="nx">r</span><span class="p">.</span><span class="nx">status</span> <span class="o">===</span> <span class="mi">200</span> <span class="p">});</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><p>對比同一個 test 用 <code>.jmx</code> 寫的形狀、思考 <em>為什麼 arrival rate 跟 thread group 測出來不一樣</em>。這 phase 的目標是 <em>paradigm internalization</em>、不是產出 migration artifact。團隊每個寫 performance test 的人都要過這一關、不能跳。</p>
<p>完成標準：寫的人能講清楚「arrival rate 100 / 5 分鐘」跟「100 thread / 5 分鐘 ramp-up」的 production behavior 差異。</p>
<h3 id="phase-2高價值-critical-path-改-k6gui-留-jmeter">Phase 2：高價值 critical path 改 k6（GUI 留 JMeter）</h3>
<p>選 <em>最常跑 + 最重要</em> 的 1-3 條 scenario 改寫 k6、不全部一次轉。典型候選：</p>
<ul>
<li>Pre-release smoke test（核心 API 的 baseline check）</li>
<li>Nightly regression（per-commit performance gate）</li>
<li>Peak readiness rehearsal scenario（活動前 T-7 跑的 stress test）</li>
</ul>
<p>GUI / QA 團隊維護的 <code>.jmx</code> <em>不動</em> — 那些通常是 multi-protocol（JDBC / JMS / FTP）、不在 k6 適合 scope。</p>
<p>工作主要塊：</p>
<ul>
<li><code>.jmx</code> thread group → k6 scenario executor 的 <em>paradigm-correct</em> 翻譯（不是欄位翻譯）</li>
<li>HTTP request 跟 assertion 翻譯（payload / header / cookies）</li>
<li>CSV data source（JMeter CSV Data Set Config）→ k6 <code>SharedArray</code> from JSON</li>
<li>結果輸出 schema 改變（XML / JTL → JSON / Prometheus / k6 Cloud）</li>
<li>CI integration 重做（GitHub Actions / GitLab CI 直接 <code>k6 run</code>、不需要 packaging）</li>
</ul>
<p>完成標準：critical path 的 k6 baseline 跟 <code>.jmx</code> baseline 數據對比一致（p50 / p95 / throughput 在 10% 誤差內、行為不一致時知道是 paradigm 差還是 bug）。</p>
<h3 id="phase-3qa-團隊雙工具技能hybrid-穩定形態">Phase 3：QA 團隊雙工具技能（hybrid 穩定形態）</h3>
<p>很多 org 停在這個 phase：QA 團隊用 GUI 維護 multi-protocol .jmx（covering JDBC / JMS / LDAP / SOAP / FTP）、dev / SRE 用 k6 維護 HTTP / gRPC / WebSocket performance test in CI。Two-tool stack 不是 broken state、是 <em>not-converged-by-design</em>。</p>
<p>這個 phase 的工作主要塊：</p>
<ul>
<li>文件化：哪類 test 用 k6、哪類用 JMeter、決策樹寫在 team handbook</li>
<li>結果整合：兩個工具的 metrics 都進同一個 Grafana dashboard（k6 → Prometheus 直接、JMeter → InfluxDB / Prometheus exporter）</li>
<li>Release gate 用 k6 為主（CI 整合直接）、JMeter 用於 manual QA campaign / multi-protocol 場景</li>
</ul>
<p>多數 org 不進 Phase 4。</p>
<h3 id="phase-4jmeter-退役少見">Phase 4：JMeter 退役（少見）</h3>
<p>只有當 <em>所有 protocol 都換到 k6 extension</em> 或 <em>捨棄了 multi-protocol coverage</em> 時、才 fully 退役 JMeter。常見路徑：</p>
<ul>
<li>用 k6 xk6 extensions 補 protocol（xk6-sql for JDBC、xk6-kafka for Kafka、xk6-amqp for RabbitMQ、xk6-mqtt for MQTT）</li>
<li>評估每個 extension 的 maturity / community support — xk6 ecosystem 比 JMeter plugin 小很多</li>
<li>接受 part of legacy <code>.jmx</code> test 直接 deprecate（covered by integration test 而非 load test）</li>
</ul>
<p>完成標準：所有 protocol 都在 k6 + xk6 內可表達、<code>.jmx</code> 全部 archive。</p>
<h2 id="5-個-production-踩雷">5 個 production 踩雷</h2>
<h3 id="1-thread-group--vu-直接翻譯最常見phase-2-必踩">1. Thread group → VU 直接翻譯（最常見、Phase 2 必踩）</h3>
<p>把 <code>numThreads=100</code> 翻成 <code>vus: 100</code> 就完事 — 結果 RPS 跟 JMeter 不一致、p95 完全不同形狀。原因：JMeter 100 thread 是 <em>closed model</em>（thread 等回應才送下一個）、k6 <code>vus: 100</code> 預設也是 closed model、但 <em>iteration 結束就立刻送下一個</em>（無 think time）— 兩者的 <em>throughput 行為</em> 差異來自 think time / response time。</p>
<p>修法：</p>
<ul>
<li>不用 <code>vus: N</code>、用 <code>constant-arrival-rate</code> 或 <code>ramping-arrival-rate</code>、直接表達 <em>每秒幾個請求</em></li>
<li>如果一定要 closed model（pre-existing JMeter scenario 對比）、在 default function 內加 <code>sleep(thinkTime)</code> 模擬 JMeter Think Time</li>
</ul>
<h3 id="2-arrival-rate-vs-concurrent-vu-混淆">2. Arrival rate vs concurrent VU 混淆</h3>
<p><code>arrival-rate</code> executor 的 <code>rate: 100</code> 意思是 <em>每秒進來 100 request</em>、<code>preAllocatedVUs: 200</code> 是 <em>預先準備 200 個 VU worker pool</em>。如果 service 變慢（p95 從 100ms 飄到 500ms）、需要的 VU 數會從 100/sec * 0.1s = 10 暴增到 100/sec * 0.5s = 50、<code>preAllocatedVUs</code> 不夠就會 warning「ran out of VUs」、實際 arrival rate 達不到 spec。</p>
<p>修法：</p>
<ul>
<li><code>preAllocatedVUs</code> 設為 <code>maxVUs / 2</code></li>
<li><code>maxVUs</code> 設為 <code>rate * worst_case_response_time_seconds * 5</code>（5x safety margin）</li>
<li>Monitor <code>dropped_iterations</code> metric — 不該 &gt; 0、&gt; 0 表示 worker pool 不夠</li>
</ul>
<h3 id="3-protocol-gapk6-沒原生對應-jmeter-的部分">3. Protocol gap（k6 沒原生對應 JMeter 的部分）</h3>
<p>k6 原生支援 HTTP/1.1 / HTTP/2 / gRPC / WebSocket / SSE。<strong>沒有</strong>原生支援：</p>
<ul>
<li>JDBC（要 xk6-sql extension）</li>
<li>JMS（要 xk6-amqp / xk6-kafka extension）</li>
<li>LDAP（無 extension、要外接 LDAP client）</li>
<li>FTP（無 extension）</li>
<li>SMTP / IMAP / POP3（無 extension）</li>
<li>SOAP（HTTP module 內手寫 XML body、無 helper）</li>
</ul>
<p>如果 <code>.jmx</code> 用了這些 protocol、評估 xk6 extension 成熟度（GitHub stars、recent commit、issue volume）、不成熟就把這些 test 留在 JMeter。</p>
<h3 id="4-結果輸出-schema-改變result-post-processing-全部要重寫">4. 結果輸出 schema 改變（result post-processing 全部要重寫）</h3>
<p>JMeter 預設輸出 JTL XML（per-sample 一行）、有 listener 後處理。k6 預設輸出 stdout summary + optional JSON / CSV / Prometheus / k6 Cloud。如果有既有 <em>result analysis pipeline</em>（從 JTL 拉 data 進 BI tool、產 trend chart）、Phase 2 必須重寫。</p>
<p>修法：</p>
<ul>
<li>評估直接接 Prometheus + Grafana（k6 native）取代既有 BI dashboard</li>
<li>或寫 k6 JSON output → 自家 BI 的 transformation script</li>
</ul>
<h3 id="5-ci-integration-重做distributed-runner-模型不同">5. CI integration 重做（distributed runner 模型不同）</h3>
<p>JMeter 在 CI 跑要：JVM provision、plugin install、<code>.jmx</code> upload、non-GUI mode 跑、JTL 結果 parse、exit code 對應 threshold。k6 在 CI 跑：<code>k6 run script.js</code>、threshold pass / fail 直接 exit code、result 進 Prometheus / k6 Cloud。</p>
<p>看起來 k6 簡單、但有踩雷：</p>
<ul>
<li>Distributed run model 不同：JMeter 用 master-slave、k6 OSS 不內建 distributed、要 Grafana Cloud k6 或自建 k6-operator on Kubernetes</li>
<li>大規模負載（&gt; 50K VU）必須 distributed、Phase 2 評估時要先確認 distributed setup 不是 blocker</li>
<li>CI runner 資源：k6 是 native binary、CPU / memory 用量比 JMeter（JVM）低、但 runner spec 要按 max VU 估</li>
</ul>
<h2 id="protocol-gap-詳表">Protocol gap 詳表</h2>
<table>
  <thead>
      <tr>
          <th>Protocol</th>
          <th>JMeter sampler</th>
          <th>k6 對應</th>
          <th>成熟度 / 替代方案</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>HTTP/1.1</td>
          <td>HTTP Request</td>
          <td><code>k6/http</code></td>
          <td>原生、成熟</td>
      </tr>
      <tr>
          <td>HTTP/2</td>
          <td>HTTP/2 sampler</td>
          <td><code>k6/http</code>（auto）</td>
          <td>原生、成熟</td>
      </tr>
      <tr>
          <td>gRPC</td>
          <td>（無原生、要 plugin）</td>
          <td><code>k6/net/grpc</code></td>
          <td>原生、成熟</td>
      </tr>
      <tr>
          <td>WebSocket</td>
          <td>WebSocket sampler（plugin）</td>
          <td><code>k6/ws</code></td>
          <td>原生、成熟</td>
      </tr>
      <tr>
          <td>SSE</td>
          <td>（無原生）</td>
          <td>xk6-sse</td>
          <td>extension、中等</td>
      </tr>
      <tr>
          <td>JDBC</td>
          <td>JDBC Request</td>
          <td>xk6-sql</td>
          <td>extension、不成熟、留 JMeter</td>
      </tr>
      <tr>
          <td>JMS</td>
          <td>JMS sampler</td>
          <td>xk6-amqp / xk6-kafka</td>
          <td>extension、protocol-specific</td>
      </tr>
      <tr>
          <td>LDAP</td>
          <td>LDAP Request</td>
          <td>（無）</td>
          <td>外接 / 留 JMeter</td>
      </tr>
      <tr>
          <td>FTP</td>
          <td>FTP Request</td>
          <td>（無）</td>
          <td>留 JMeter</td>
      </tr>
      <tr>
          <td>SMTP / IMAP</td>
          <td>Mail sampler</td>
          <td>（無）</td>
          <td>留 JMeter</td>
      </tr>
      <tr>
          <td>SOAP / XML-RPC</td>
          <td>SOAP / XML-RPC Request</td>
          <td><code>k6/http</code> 手寫 XML body</td>
          <td>工作量大、留 JMeter</td>
      </tr>
      <tr>
          <td>TCP socket</td>
          <td>TCP sampler</td>
          <td><code>k6/net/tcp</code></td>
          <td>原生但簡單、複雜 protocol 留 JMeter</td>
      </tr>
  </tbody>
</table>
<h2 id="容量與成本對照">容量與成本對照</h2>
<table>
  <thead>
      <tr>
          <th>項目</th>
          <th>JMeter</th>
          <th>k6 OSS</th>
          <th>Grafana Cloud k6</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Cost</td>
          <td>Free (Apache)</td>
          <td>Free (Apache 2.0)</td>
          <td>$49+ / mo (Pro)</td>
      </tr>
      <tr>
          <td>單機 VU 容量</td>
          <td>~500-1000 thread</td>
          <td>30K-50K VU</td>
          <td>unlimited（cloud runner）</td>
      </tr>
      <tr>
          <td>Distributed</td>
          <td>master-slave 內建</td>
          <td>不內建、需 k6-operator</td>
          <td>cloud-native</td>
      </tr>
      <tr>
          <td>Result store</td>
          <td>JTL XML（local）</td>
          <td>stdout / JSON / Prom</td>
          <td>cloud retained</td>
      </tr>
      <tr>
          <td>CI integration</td>
          <td>需 packaging</td>
          <td>native CLI</td>
          <td>native + cloud</td>
      </tr>
      <tr>
          <td>Multi-protocol coverage</td>
          <td>廣</td>
          <td>窄（HTTP/gRPC/WS）+ xk6</td>
          <td>同 OSS</td>
      </tr>
  </tbody>
</table>
<p>對 dev-driven CI gate use case：k6 OSS 已經夠用、Grafana Cloud k6 在 <em>跨 region runner + result retention + dashboard 整合</em> 時才有 ROI。對既有 multi-protocol .jmx asset：考慮 Phase 3 hybrid stable state、不要強推 Phase 4。</p>
<h2 id="何時不要切">何時不要切</h2>
<ul>
<li><strong>multi-protocol coverage 是核心需求</strong>：JDBC + JMS + LDAP + FTP 必要、xk6 extension 不夠成熟、留 JMeter</li>
<li><strong>QA 團隊維護 GUI .jmx</strong>：QA 不寫 code、<code>.jmx</code> GUI 是團隊資產、貿然轉 k6 等於 throwaway QA team</li>
<li><strong>既有 multi-year .jmx asset 大量</strong>：500+ scenario 全部翻譯成本 &gt; k6 ergonomic 收益、考慮 Phase 3 stable hybrid</li>
<li><strong>Distributed run 需求極大（&gt; 100K VU）但 ops budget 緊</strong>：k6-operator on Kubernetes 不便宜、Grafana Cloud k6 對應 tier 也不便宜、JMeter master-slave 仍是 cost-effective 選項</li>
</ul>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>平行 batch：<a href="/blog/backend/09-performance-capacity/vendors/datadog-continuous-profiler/migrate-from-pyroscope/" data-link-title="Pyroscope → Datadog Continuous Profiler：profiling deployment lifecycle 各階段 operational ownership 轉手" data-link-desc="Pyroscope → Datadog Continuous Profiler 是 Type C operational hybrid migration — pprof data model 接近、profile lifecycle 五階段（install / instrument / ingest / query / cost）的 ops ownership 從 self-host 轉到 SaaS。本文走 6 維 audit（Operational High 其他 Low）、4-phase migration（operational audit &#43; agent parallel &#43; tag reconcile &#43; cutover）、5 production 踩雷（agent 重複 overhead / tag schema 不一致 / trace_id correlation 斷 / cost 突增 / retention 政策變動）、何時保留 Pyroscope（資料主權 / 內網 / OSS-first / cost sensitive）">Pyroscope → Datadog Profiler</a>（Type C operational hybrid）</li>
<li>同 batch Type E：<a href="/blog/backend/08-incident-response/vendors/pagerduty/migrate-to-incident-io/" data-link-title="PagerDuty → incident.io：「On-call」是個 retconned word、同名不同 contract" data-link-desc="PagerDuty → incident.io 不是 schema translation — 兩家的「on-call」字面相同、contract 不同（alert routing vs IR coordination &#43; Slack-native &#43; retrospective）。本文走 Type E paradigm shift、6 維 audit 顯示 paradigm / schema / operational 三軸 High、用 4-phase partial migration（不收斂、Phase 1-2 多數 org 停留）、5 個 production 踩雷（雙系統 state drift / severity 翻譯失真 / schedule layer 漏 / Slack channel 過載 / retrospective 斷層）、跟 PagerDuty Process Automation / AIOps 沒對應的 capability gap">PagerDuty → incident.io</a>（IR paradigm shift）</li>
<li>上游：<a href="/blog/backend/09-performance-capacity/load-test-tooling/" data-link-title="9.3 壓測工具選型" data-link-desc="k6 / JMeter / Gatling / Locust / Vegeta / Production Replay 的工程選型">9.3 壓測工具選型</a> / <a href="/blog/backend/09-performance-capacity/workload-modeling/" data-link-title="9.2 Workload Modeling" data-link-desc="把 production traffic shape 翻成可重播的壓測模型">9.2 Workload Modeling</a></li>
<li>下游：<a href="/blog/backend/06-reliability/performance-regression-gate/" data-link-title="6.13 Performance Regression Gate" data-link-desc="把效能 baseline 從一次性壓測變成持續對齊的 release gate，涵蓋 baseline 設定、判讀方法、variance 控制與退化定位">6.13 Performance Regression Gate</a>（CI gate integration）</li>
<li>vendor 對照：<a href="/blog/backend/09-performance-capacity/vendors/jmeter/" data-link-title="Apache JMeter" data-link-desc="用 GUI、plugin 與多 protocol sampler 承接企業壓測資產的效能工程工具">JMeter</a> / <a href="/blog/backend/09-performance-capacity/vendors/k6/" data-link-title="k6" data-link-desc="用 scriptable scenario 建立 API、protocol 與 CI 友善壓測的效能工程工具">k6</a> / <a href="/blog/backend/09-performance-capacity/vendors/gatling/" data-link-title="Gatling" data-link-desc="用 JVM DSL、simulation 與 injection profile 表達複雜 scenario 的效能工程工具">Gatling</a> / <a href="/blog/backend/09-performance-capacity/vendors/locust/" data-link-title="Locust" data-link-desc="用 Python user behavior 與 distributed worker 表達高自訂負載模型的效能工程工具">Locust</a></li>
<li>方法論：<a href="/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">Migration Playbook Methodology</a>（Type E paradigm shift 結構說明）</li>
</ul>
]]></content:encoded></item><item><title>PagerDuty → incident.io：「On-call」是個 retconned word、同名不同 contract</title><link>https://tarrragon.github.io/blog/backend/08-incident-response/vendors/pagerduty/migrate-to-incident-io/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/08-incident-response/vendors/pagerduty/migrate-to-incident-io/</guid><description>&lt;p>「On-call」是個被 retconned 的詞。PagerDuty 用了十年定義它為 &lt;em>alert routing + schedule + escalation&lt;/em> — 重點是「誰會被叫醒」。incident.io 2024 年推出 On-call 模組時保留了同一個詞、但 contract 變了：On-call 在 incident.io 是 &lt;em>IR coordination + Slack-native workflow + retrospective integration&lt;/em> 的 paging 入口 — 重點是「被叫醒之後做什麼」。&lt;/p>
&lt;p>這個語意 retroactive 是這篇 migration playbook 必須先講清楚的事。讀者打開比較表會看到「PagerDuty 有 schedule、incident.io 有 schedule、PagerDuty 有 escalation policy、incident.io 有 escalation policy」、以為這是一場 schema translation 文。實際上 schema 翻譯只是其中一個工作塊、更難的是 &lt;em>org 的事故行為從「等 PagerDuty 叫」變成「在 Slack channel 內跑 lifecycle」&lt;/em>。&lt;/p>
&lt;h2 id="為什麼是-type-e不是-type-a">為什麼是 Type E（不是 Type A）&lt;/h2>
&lt;p>跑 &lt;a href="https://tarrragon.github.io/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/#6-%e7%b6%ad-diff-dimension-audit" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">6 維 diff dimension audit&lt;/a>：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>維度&lt;/th>
 &lt;th>評&lt;/th>
 &lt;th>說明&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Schema&lt;/td>
 &lt;td>High&lt;/td>
 &lt;td>service / escalation policy / schedule / integration 跟 incident / role / action / catalog 沒 1:1 對應&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Operational&lt;/td>
 &lt;td>High&lt;/td>
 &lt;td>alert routing → Slack-native IR coordination + retrospective workflow&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Paradigm&lt;/td>
 &lt;td>High&lt;/td>
 &lt;td>「alert someone」 → 「coordinate full incident lifecycle from declare to retro」&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Components&lt;/td>
 &lt;td>Medium&lt;/td>
 &lt;td>incident.io 整合 Slack / Linear / Jira / Confluence 變 multi-component&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>App change&lt;/td>
 &lt;td>Medium&lt;/td>
 &lt;td>webhook / integration key / IaC 都要改&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Topology&lt;/td>
 &lt;td>Low&lt;/td>
 &lt;td>都是 cloud SaaS、無 sharding / region 議題&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>三軸 High（schema / operational / paradigm）。按優先序 schema &amp;gt; paradigm &amp;gt; operational、預設會選 Type A。但這條優先序是 &lt;em>audience-dependent heuristic&lt;/em> — 對「我要把 PagerDuty config 翻譯成 incident.io」的讀者選 Type A、對「我要把事故管理 paradigm 從 paging-first 變成 Slack-first」的讀者選 Type E。&lt;/p></description><content:encoded><![CDATA[<p>「On-call」是個被 retconned 的詞。PagerDuty 用了十年定義它為 <em>alert routing + schedule + escalation</em> — 重點是「誰會被叫醒」。incident.io 2024 年推出 On-call 模組時保留了同一個詞、但 contract 變了：On-call 在 incident.io 是 <em>IR coordination + Slack-native workflow + retrospective integration</em> 的 paging 入口 — 重點是「被叫醒之後做什麼」。</p>
<p>這個語意 retroactive 是這篇 migration playbook 必須先講清楚的事。讀者打開比較表會看到「PagerDuty 有 schedule、incident.io 有 schedule、PagerDuty 有 escalation policy、incident.io 有 escalation policy」、以為這是一場 schema translation 文。實際上 schema 翻譯只是其中一個工作塊、更難的是 <em>org 的事故行為從「等 PagerDuty 叫」變成「在 Slack channel 內跑 lifecycle」</em>。</p>
<h2 id="為什麼是-type-e不是-type-a">為什麼是 Type E（不是 Type A）</h2>
<p>跑 <a href="/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/#6-%e7%b6%ad-diff-dimension-audit" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">6 維 diff dimension audit</a>：</p>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>評</th>
          <th>說明</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Schema</td>
          <td>High</td>
          <td>service / escalation policy / schedule / integration 跟 incident / role / action / catalog 沒 1:1 對應</td>
      </tr>
      <tr>
          <td>Operational</td>
          <td>High</td>
          <td>alert routing → Slack-native IR coordination + retrospective workflow</td>
      </tr>
      <tr>
          <td>Paradigm</td>
          <td>High</td>
          <td>「alert someone」 → 「coordinate full incident lifecycle from declare to retro」</td>
      </tr>
      <tr>
          <td>Components</td>
          <td>Medium</td>
          <td>incident.io 整合 Slack / Linear / Jira / Confluence 變 multi-component</td>
      </tr>
      <tr>
          <td>App change</td>
          <td>Medium</td>
          <td>webhook / integration key / IaC 都要改</td>
      </tr>
      <tr>
          <td>Topology</td>
          <td>Low</td>
          <td>都是 cloud SaaS、無 sharding / region 議題</td>
      </tr>
  </tbody>
</table>
<p>三軸 High（schema / operational / paradigm）。按優先序 schema &gt; paradigm &gt; operational、預設會選 Type A。但這條優先序是 <em>audience-dependent heuristic</em> — 對「我要把 PagerDuty config 翻譯成 incident.io」的讀者選 Type A、對「我要把事故管理 paradigm 從 paging-first 變成 Slack-first」的讀者選 Type E。</p>
<p>決定因素是 <em>讀者最關心什麼</em>。從 PagerDuty 出發評估 incident.io 的 org 通常 <em>已經有 Slack channel 跑 IR</em> 的痛感（雙系統 state drift / context switching cost / Slack bot 補 PagerDuty 的能力斷裂）、進來找的是 paradigm 統一、不是欄位翻譯。schema translation 是工作量、但不是讀者來找答案的問題。所以選 <strong>Type E paradigm shift</strong> 結構、schema translation 抽出獨立段補充。</p>
<h2 id="為什麼遷im-native-coordination-的拉力">為什麼遷：IM-native coordination 的拉力</h2>
<p>事故反應在已經 Slack 中心的 org 是 <em>從 Slack 自然發生</em> 的 — 觀測 alert 進 Slack、SRE 開 thread、PM 跳進來問影響、customer-facing team 在 incident channel 看通報、所有上下文都在 IM 內。PagerDuty 在這個 reality 下變成 <em>第二個 system of record</em>：incident 開在 PagerDuty 也開在 Slack、PagerDuty timeline 跟 Slack scroll 是兩條時間線、status update 要 mirror 兩次、責任分派在 Slack 講但要在 PagerDuty 點。</p>
<p>PagerDuty 注意到這個問題、後加了 Status Updates / Slack integration / Postmortem 模組想把 Slack 拉回 PagerDuty。但結構性還是 <em>PagerDuty 是主、Slack 是 mirror</em> — incident object 的 source of truth 在 PagerDuty、Slack 的訊息只是 attachment。對 <em>Slack-first</em> 的 org 來說這個 ownership 反了：Slack channel 才是事故進行中的 ground truth、PagerDuty incident 應該是 paging 入口的 artifact。</p>
<p>incident.io 設計上把這個關係翻過來：Slack channel 是 IR ground truth、incident object 是 channel 的 metadata 投影。declare incident 在 Slack、role 指派在 Slack bot prompt、status update 在 channel reply、retrospective 從 channel 訊息自動 stitch — incident.io dashboard 是 <em>管理視圖</em>、不是事故 <em>進行視圖</em>。On-call 模組加進來後、連 paging 入口也跟 IR coordination 收斂到同一個 system of record。</p>
<p>這個 pull 是這條 migration 的 <em>driver</em>。schema 翻譯只是把這條 pull 落地的工作。</p>
<h2 id="4-phase-partial-migration不收斂">4-phase partial migration（不收斂）</h2>
<p>Type E paradigm shift 的特徵是 <em>不收斂</em> — 多數 org 不會把 PagerDuty 全退役、會停在某個 phase 變成穩定的 hybrid。下面 4 phase 是 <em>常見演進路徑</em>、不是 <em>必要完成步驟</em>：</p>
<h3 id="phase-1slack-first-responsepaging-留-pagerduty">Phase 1：Slack-first response（paging 留 PagerDuty）</h3>
<p>incident.io 接 PagerDuty incident webhook、PagerDuty 開 incident → incident.io 自動開 Slack channel、跑 response lifecycle（declare / role / status / close / retro）。PagerDuty 仍管 paging schedule + escalation、incident.io 管 response coordination。</p>
<p>這個 phase 的工作主要塊是：</p>
<ul>
<li>incident.io 跟 PagerDuty 雙向 webhook 接（PD incident.trigger → IO open channel、IO incident.resolved → PD ack）</li>
<li>Slack workspace 整合（permissions、channel naming、stakeholder broadcast channel）</li>
<li>Severity 對應表（PagerDuty P1-P5 對 incident.io SEV1-SEV4、語意 reconcile）</li>
<li>跑 2-4 週 dual ops、訓練 SRE 在 Slack 內跑 lifecycle、不要回 PagerDuty 點 timeline</li>
</ul>
<p>完成標準：incident commander 不再需要進 PagerDuty UI、status update / role 指派 / action item 都在 Slack。</p>
<h3 id="phase-2catalog--service-ownership-migrate">Phase 2：Catalog + service ownership migrate</h3>
<p>把 PagerDuty 的 service registry（service / team / escalation policy 關聯）抽出進 incident.io 的 Catalog。Catalog 是 incident.io 的 <em>service metadata source of truth</em>、把 service 跟 team / Slack channel / Linear project / runbook URL 綁在一起、incident 發生時自動推薦 role 跟通知 stakeholder。</p>
<p>工作主要塊：</p>
<ul>
<li>從 PagerDuty API export service / team / escalation policy（REST endpoint <code>/services</code>、<code>/teams</code>、<code>/escalation_policies</code>）</li>
<li>Schema mapping：PagerDuty service → incident.io catalog entry、escalation policy → 暫時不動（留在 PagerDuty）</li>
<li>補 PagerDuty 沒有的欄位：Slack channel、Linear project、runbook URL、tier（catalog 比 PagerDuty service 多 metadata 維度）</li>
<li>Service ownership reconcile（PagerDuty 的 team grant 通常跟 GitHub team / IAM group 不一致、Catalog 是重新對齊機會）</li>
</ul>
<p>完成標準：incident 發生時自動知道 owner team 跟對應 Slack channel、不需要人查。</p>
<h3 id="phase-3schedule--escalation-移到-incidentio-on-call">Phase 3：Schedule + escalation 移到 incident.io On-call</h3>
<p>PagerDuty 的 schedule + escalation policy 改進 incident.io On-call。這是 <em>paging 入口的 ownership 轉移</em> — Phase 1 是 PD 觸發 IO response、Phase 3 是 IO 直接收 alert source 觸發 paging。</p>
<p>工作主要塊：</p>
<ul>
<li>Alert source 改線：Splunk / Datadog / Cloudflare WAF / cloud control plane 的 webhook 從 PagerDuty Event API 改成 incident.io webhook endpoint、deduplication key / severity mapping 重做</li>
<li>Schedule 重建：PagerDuty schedule layer model（多 layer 疊加 + restriction + override）跟 incident.io schedule rule（單純 weekly rotation + override）不是 1:1、複雜 schedule 要重新設計</li>
<li>Escalation policy 重建：PagerDuty 的 multi-step escalation + level-based timeout 對應 incident.io 的 escalation path、policy 比 PagerDuty 簡單但要重新測 failover 行為</li>
<li>Mobile app 切換：on-call 人員裝 incident.io app、PagerDuty app 保留作為 backup paging（Phase 4 才完全捨棄）</li>
</ul>
<p>完成標準：日常 paging 全走 incident.io、PagerDuty 留作 fallback 或退役。</p>
<h3 id="phase-4retrospective--完全退役-pagerduty">Phase 4：Retrospective + 完全退役 PagerDuty</h3>
<p>把 retrospective workflow 切到 incident.io 內建的 post-incident flow、捨棄 PagerDuty Postmortems / Jeli 整合。incident.io 的 retro template 從 Slack channel 訊息自動 stitch timeline、action item 推 Linear / Jira、learning review 結構化。</p>
<p>工作主要塊：</p>
<ul>
<li>既有 Jeli / PagerDuty Postmortems 歷史 export（PagerDuty REST 不直接給 postmortem export、要從 Jeli web app 手動 export）</li>
<li>Retrospective template 對應到 org 既有的 post-incident review 結構</li>
<li>Action item lifecycle 整合（incident.io 推 Linear / Jira → close → retrospective 自動標 done）</li>
</ul>
<p>多數 org 停在 Phase 2 或 Phase 3。完整 Phase 4 退役 PagerDuty 不是必要、且常見的選擇是 <em>PagerDuty 留作 backup paging route</em> 或 <em>特定 integration 持續用</em>（見下一段 capability gap）。</p>
<h2 id="5-個-production-踩雷">5 個 production 踩雷</h2>
<p>實際遷過程踩過的 5 個典型問題：</p>
<h3 id="1-雙系統-state-driftphase-1-最常見">1. 雙系統 state drift（Phase 1 最常見）</h3>
<p>PagerDuty incident.trigger → incident.io 開 channel、但 PagerDuty 上 incident 被自動 resolve（例如 monitoring tool 認為 issue cleared）後、incident.io 沒收到對應 webhook、Slack channel 還 active 顯示 in-progress。修法是雙向 webhook 都要接（PD resolved → IO 自動 close channel），但 webhook 失序的場景仍要有 nightly reconcile job 對比兩邊狀態。</p>
<h3 id="2-severity-翻譯失真">2. Severity 翻譯失真</h3>
<p>PagerDuty 的 P1-P5 跟 incident.io 的 SEV1-SEV4 不是 5:4 對應、是兩個獨立 schema。同一個事故在 PagerDuty 是 P2（高優先但非全面 outage）、進 incident.io 可能變 SEV2（部分服務影響）或 SEV1（依 incident.io custom severity 定義）。Phase 1 雙系統並行時 SRE 在 Slack 看到 SEV1 跑進 war room mode、PagerDuty 同 incident 是 P2 沒拉 stakeholder bridge — 同事故兩邊嚴重度不同步、回應節奏錯亂。修法是事先寫死 mapping table（PD P1 → IO SEV1、PD P2 → IO SEV2、不 case-by-case 判斷），並在 Phase 3 後讓 incident.io severity 變唯一 source of truth。</p>
<h3 id="3-schedule-layer-漏-holiday-override--restriction-layer">3. Schedule layer 漏 holiday override / restriction layer</h3>
<p>PagerDuty schedule 是 layer model — primary rotation（layer 1） + secondary rotation（layer 2） + holiday override（layer 3） + restriction（每層 time-of-day 限制）可以疊加。Export 出來只看 layer 1 通常會漏 holiday override 跟 restriction layer、incident.io schedule rule 是單一 rotation + override list、不 cover 多 layer 疊加。修法是 export 時用 PagerDuty API <code>/schedules/{id}</code> 的完整 layer + final_schedule 一起拉、用 incident.io schedule 的 override list 模擬 layer 疊加、複雜 schedule（例如 follow-the-sun + 4 region + holiday override）可能要拆成多個 incident.io schedule 用 escalation chain 串。</p>
<h3 id="4-slack-channel-過載">4. Slack channel 過載</h3>
<p>incident.io 預設每個 incident 開一個 channel。Phase 1 啟用後 SRE 一週收 50+ channel notification、即使 P3 / P4 也開 channel、Slack sidebar 被淹沒。修法是 incident type 設計時把低 severity（SEV3 / SEV4）改成 <em>don&rsquo;t auto-create channel</em> 或 <em>use shared low-severity channel</em>、只 SEV1 / SEV2 開獨立 channel。incident.io 有這個 configuration、但預設不開、要主動設定。</p>
<h3 id="5-retrospective-切換時歷史-learning-斷層">5. Retrospective 切換時歷史 learning 斷層</h3>
<p>從 Jeli / PagerDuty Postmortems 切到 incident.io retro 後、過去 2 年 postmortem 留在原系統、search 跨不到、新 retro template 跟舊的結構不同、learning review 的 trend analysis 斷層。修法是 Phase 4 前先 export 既有 postmortem 為 markdown 進 GitHub Wiki / Confluence 集中保存、incident.io retro 自動 export 到同位置、retro search 不依賴 vendor lock-in。</p>
<h2 id="schema-translation-主要工作量塊">Schema translation 主要工作量塊</h2>
<p>雖然 Type E 結構不以 schema translation 為主、但 translation 工作量塊在 Phase 2-3 仍佔多數時間：</p>
<table>
  <thead>
      <tr>
          <th>來源（PagerDuty）</th>
          <th>目標（incident.io）</th>
          <th>註</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Service</td>
          <td>Catalog entry</td>
          <td>增加 Slack channel / Linear project metadata</td>
      </tr>
      <tr>
          <td>Team</td>
          <td>Catalog team</td>
          <td>多對應 GitHub team / IAM group</td>
      </tr>
      <tr>
          <td>Escalation policy</td>
          <td>Escalation path</td>
          <td>比 PD 簡單、複雜 escalation 要拆</td>
      </tr>
      <tr>
          <td>Schedule（multi-layer）</td>
          <td>Schedule + override list</td>
          <td>不是 1:1、複雜 schedule 要拆多個</td>
      </tr>
      <tr>
          <td>Integration（webhook）</td>
          <td>Webhook endpoint</td>
          <td>全部 alert source 要重 wire</td>
      </tr>
      <tr>
          <td>Incident workflow</td>
          <td>Incident type + role</td>
          <td>重新設計、不直接翻譯</td>
      </tr>
      <tr>
          <td>Event Orchestration rule</td>
          <td>Workflows</td>
          <td>incident.io workflows 比 EO 簡單、複雜 routing 要外接</td>
      </tr>
      <tr>
          <td>AIOps / Process Automation</td>
          <td>（無對應）</td>
          <td>見 capability gap 段</td>
      </tr>
      <tr>
          <td>Postmortem / Jeli</td>
          <td>Post-incident flow</td>
          <td>template 重寫、歷史保存獨立</td>
      </tr>
  </tbody>
</table>
<h2 id="capability-gappagerduty-有但-incidentio-沒有">Capability gap：PagerDuty 有但 incident.io 沒有</h2>
<p>不是所有功能 incident.io 都有對應。Phase 3-4 推進前要先確認這些能力是否在用、是否願意捨棄或外接：</p>
<ul>
<li><strong>AIOps（intelligent grouping / noise reduction）</strong>：PagerDuty Enterprise tier 用 ML 自動 group alert、incident.io 沒對應、grouping 靠 alert source 端 deduplication key</li>
<li><strong>Process Automation（runbook automation）</strong>：PagerDuty 收購 Rundeck、提供 automated remediation step、incident.io 沒對應、要外接 Tines / n8n / 自製 Lambda</li>
<li><strong>Status Page 整合（PagerDuty 內建）</strong>：PagerDuty 提供 Status Page 模組、incident.io status page 是 separate product、定價跟 feature 不同</li>
<li><strong>Multi-region / 強合規（FedRAMP / IL5）</strong>：PagerDuty 在金融 / 政府 / 高合規 deploy 成熟度高、incident.io SOC 2 + ISO 27001 但 FedRAMP 還在追</li>
</ul>
<p>如果在用 AIOps + Process Automation 而且重要、不要做這個 migration、或保留 PagerDuty 作為 AIOps + Automation 後端、incident.io 處理 response coordination — Phase 1 永久 hybrid。</p>
<h2 id="容量與成本對照">容量與成本對照</h2>
<table>
  <thead>
      <tr>
          <th>項目</th>
          <th>PagerDuty</th>
          <th>incident.io</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>計費模式</td>
          <td>Per-user / month、tier-based（Pro / Business / Enterprise）</td>
          <td>Per-user / month、On-call 模組另計</td>
      </tr>
      <tr>
          <td>隱性容量上限</td>
          <td>API rate limit（10K / minute）</td>
          <td>Slack workspace seat 上限（IR participant ≤ workspace user）</td>
      </tr>
      <tr>
          <td>AIOps 加價</td>
          <td>Enterprise tier + AIOps add-on</td>
          <td>不適用</td>
      </tr>
      <tr>
          <td>Status page</td>
          <td>內建（Business tier+）</td>
          <td>獨立 product</td>
      </tr>
      <tr>
          <td>Process Auto</td>
          <td>Rundeck-based、separate pricing</td>
          <td>不適用</td>
      </tr>
  </tbody>
</table>
<p>實際成本對比需要 RFP — 50 人 SRE org 大致 PD Business + AIOps ~$30-40 / user / mo、incident.io Pro + On-call ~$25-35 / user / mo、cost 差距通常不是 migration 主因（是 paradigm fit + Slack-native）。</p>
<h2 id="何時不要做這個-migration">何時不要做這個 migration</h2>
<ul>
<li><strong>Slack 不是 IR ground truth</strong>：Discord / Teams primary 或 ticket system 為主的 org、incident.io Slack-first 設計無法落地</li>
<li><strong>AIOps + Process Automation 是核心能力</strong>：用了 PD AIOps 自動 group alert 跟 Rundeck 自動 remediation、且這條 chain 重要 — incident.io 沒對應</li>
<li><strong>規模 &lt; 20 SRE / 50 eng</strong>：incident.io 的 catalog + opinionated workflow 設計給中大型 org、小團隊 PagerDuty Lite 或 Grafana OnCall 已經夠用</li>
<li><strong>強合規場景（FedRAMP / IL5 / 金融 SOC 1 type II）</strong>：PagerDuty 合規成熟度高、incident.io 在追、合規團隊不會 sign-off</li>
<li><strong>不打算改變事故行為</strong>：如果 org 只是想換廠商但不想改變 <em>事故在 Slack 跑 lifecycle</em> 的工作模式、這條 migration 的價值丟一半、不如走 <a href="/blog/backend/08-incident-response/vendors/opsgenie/migrate-from-pagerduty/" data-link-title="PagerDuty → Opsgenie：Atlassian 全家桶整合 vs Opsgenie 2027 EOL 的 vendor consolidation 取捨" data-link-desc="PagerDuty → Opsgenie 是 Type A phased schema translation、但 Atlassian 已宣布 Opsgenie 2027-04 EOL — 這條 migration 只在 Atlassian-heavy org &#43; 明確 JSM unification roadmap 下成立、本質是 PD → Opsgenie → JSM Cloud 的雙 hop migration。本文走 6 維 audit（Schema Medium-High 其他 Low）、PagerDuty ↔ Opsgenie ↔ JSM field mapping 對照、5 production 踩雷（escalation step / Heartbeat 缺對應 / integration key dedup 重設 / schedule 時區 / Atlassian Identity SSO 整合）、何時直接走 PD → JSM 跳過 Opsgenie">PagerDuty → Opsgenie</a>（Type A schema translation、同 paradigm）</li>
</ul>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>平行 batch：<a href="/blog/backend/08-incident-response/vendors/opsgenie/migrate-from-pagerduty/" data-link-title="PagerDuty → Opsgenie：Atlassian 全家桶整合 vs Opsgenie 2027 EOL 的 vendor consolidation 取捨" data-link-desc="PagerDuty → Opsgenie 是 Type A phased schema translation、但 Atlassian 已宣布 Opsgenie 2027-04 EOL — 這條 migration 只在 Atlassian-heavy org &#43; 明確 JSM unification roadmap 下成立、本質是 PD → Opsgenie → JSM Cloud 的雙 hop migration。本文走 6 維 audit（Schema Medium-High 其他 Low）、PagerDuty ↔ Opsgenie ↔ JSM field mapping 對照、5 production 踩雷（escalation step / Heartbeat 缺對應 / integration key dedup 重設 / schedule 時區 / Atlassian Identity SSO 整合）、何時直接走 PD → JSM 跳過 Opsgenie">PagerDuty → Opsgenie</a>（Type A、同 paradigm 換廠商）/ <a href="/blog/backend/08-incident-response/vendors/atlassian-statuspage/migrate-to-instatus/" data-link-title="Atlassian Statuspage → Instatus：status page 成本下降、但 compatibility audit 不能跳" data-link-desc="Atlassian Statuspage → Instatus 是 Type B drop-in migration、6 維 audit 全 Low；典型情境是從 Statuspage Business / Enterprise 降到 Instatus Pro / Business、但 savings 取決於 subscriber、SSO、audit 與 SLA report 需求。本文走 compatibility audit prefix（subscriber channel 完整度 / SAML SSO / audit log / metrics integration / SLA report / API parity）、4 階段 cutover（DNS TTL &#43; parallel run）、5 個 production 踩雷（SSO tier 選錯、metrics 來源整合斷、subscriber import format / SLA report 缺、custom CSS 不完全相容）、何時不要切（enterprise compliance / 強 Atlassian 整合）">Atlassian Statuspage → Instatus</a>（Type B drop-in）</li>
<li>同 batch Type E：<a href="/blog/backend/09-performance-capacity/vendors/k6/migrate-from-jmeter/" data-link-title="JMeter → k6：k6 不是 JMeter 的「script 版本」、是 VU model 取代 thread model" data-link-desc="JMeter → k6 是 Type E paradigm shift、不是把 .jmx XML 翻成 JavaScript — VU (virtual user) model 跟 thread group model 是兩種對「使用者行為」不同的建模方式。本文走 6 維 audit（Schema High / Paradigm High / Operational Medium）、釐清反向定義、4-phase partial migration（多數 org 停 Phase 2-3 hybrid）、5 production 踩雷（thread group 翻譯失真 / arrival rate vs concurrent VU 混淆 / protocol gap / 結果 schema 改 / CI integration 重做）、protocol gap（JDBC / JMS / LDAP 在 k6 沒原生對應）、何時不要切">JMeter → k6</a>（scripting paradigm shift）</li>
<li>上游：<a href="/blog/backend/08-incident-response/incident-workflow-automation-boundary/" data-link-title="8.21 Incident Workflow Automation Boundary" data-link-desc="定義哪些事故流程適合自動化，哪些決策需要保留人工確認">8.10 Incident Workflow Automation Boundary</a>（automation handoff）</li>
<li>下游：<a href="/blog/backend/08-incident-response/post-incident-review/" data-link-title="8.5 復盤與改進追蹤" data-link-desc="把 RCA 與 action items 轉成可驗證閉環">8.18 Post-Incident Review</a>（incident.io retrospective workflow）</li>
<li>vendor 對照：<a href="/blog/backend/08-incident-response/vendors/pagerduty/" data-link-title="PagerDuty" data-link-desc="On-call / alerting 主流 SaaS、IR 平台演化">PagerDuty</a> / <a href="/blog/backend/08-incident-response/vendors/incident-io/" data-link-title="incident.io" data-link-desc="Slack-native IR 平台、整合 paging / response / retro">incident.io</a></li>
<li>方法論：<a href="/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">Migration Playbook Methodology</a>（Type E paradigm shift 結構說明）</li>
</ul>
]]></content:encoded></item><item><title>PagerDuty → Opsgenie：Atlassian 全家桶整合 vs Opsgenie 2027 EOL 的 vendor consolidation 取捨</title><link>https://tarrragon.github.io/blog/backend/08-incident-response/vendors/opsgenie/migrate-from-pagerduty/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/08-incident-response/vendors/opsgenie/migrate-from-pagerduty/</guid><description>&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>PagerDuty 物件&lt;/th>
 &lt;th>Opsgenie 對應&lt;/th>
 &lt;th>JSM Cloud 對應（2027 後）&lt;/th>
 &lt;th>翻譯難度&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Service&lt;/td>
 &lt;td>Integration&lt;/td>
 &lt;td>Service registry&lt;/td>
 &lt;td>低&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Escalation Policy&lt;/td>
 &lt;td>Escalation&lt;/td>
 &lt;td>Escalation&lt;/td>
 &lt;td>中&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Schedule（layer model）&lt;/td>
 &lt;td>Schedule（rotation）&lt;/td>
 &lt;td>Schedule&lt;/td>
 &lt;td>中-高&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>User&lt;/td>
 &lt;td>User&lt;/td>
 &lt;td>Atlassian Account&lt;/td>
 &lt;td>中（IdP 整合）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Team&lt;/td>
 &lt;td>Team&lt;/td>
 &lt;td>JSM Team&lt;/td>
 &lt;td>低&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Event API v2&lt;/td>
 &lt;td>Alert API&lt;/td>
 &lt;td>JSM REST API&lt;/td>
 &lt;td>中&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Event Orchestration&lt;/td>
 &lt;td>Policy&lt;/td>
 &lt;td>Routing rule&lt;/td>
 &lt;td>中-高&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Status Page&lt;/td>
 &lt;td>Statuspage（同產品）&lt;/td>
 &lt;td>Statuspage&lt;/td>
 &lt;td>低&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Postmortem&lt;/td>
 &lt;td>（無原生）&lt;/td>
 &lt;td>（Confluence template）&lt;/td>
 &lt;td>高（要外接）&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>這張對照表是 PagerDuty → Opsgenie migration 的 &lt;em>表面 schema mapping&lt;/em>、但表前必須先處理一個前提：&lt;strong>Atlassian 2025 公開宣布 Opsgenie 將在 2027-04 EOL&lt;/strong>、現有 Opsgenie 客戶會被遷往 &lt;a href="https://www.atlassian.com/software/jira/service-management">Jira Service Management Premium / Enterprise&lt;/a> 內建的 on-call 能力。這條 migration 不是 PagerDuty ↔ Opsgenie 的 vendor swap、是 &lt;em>PagerDuty → Opsgenie → JSM Cloud&lt;/em> 的雙 hop migration。&lt;/p>
&lt;h2 id="誰應該考慮這條-migration">誰應該考慮這條 migration&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>適用條件&lt;/th>
 &lt;th>不適用&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>已是 Atlassian-heavy ecosystem（JSM / Confluence / Bitbucket）&lt;/td>
 &lt;td>純 Slack-first org（考慮 &lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/vendors/pagerduty/migrate-to-incident-io/" data-link-title="PagerDuty → incident.io：「On-call」是個 retconned word、同名不同 contract" data-link-desc="PagerDuty → incident.io 不是 schema translation — 兩家的「on-call」字面相同、contract 不同（alert routing vs IR coordination &amp;#43; Slack-native &amp;#43; retrospective）。本文走 Type E paradigm shift、6 維 audit 顯示 paradigm / schema / operational 三軸 High、用 4-phase partial migration（不收斂、Phase 1-2 多數 org 停留）、5 個 production 踩雷（雙系統 state drift / severity 翻譯失真 / schedule layer 漏 / Slack channel 過載 / retrospective 斷層）、跟 PagerDuty Process Automation / AIOps 沒對應的 capability gap">→ incident.io&lt;/a>）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>已買 JSM Premium / Enterprise、Opsgenie 是 entitled benefit&lt;/td>
 &lt;td>新案、無 Atlassian 基礎&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>願意走 PD → Opsgenie → JSM 雙 hop（或直接跳 JSM）&lt;/td>
 &lt;td>不想多次 migration、想一步到位&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Atlassian Identity / Cloud admin 已成熟&lt;/td>
 &lt;td>SSO / IdP 跟 Atlassian 沒整合好&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>OSS / 自管不可行（compliance / 規模）&lt;/td>
 &lt;td>規模 &amp;lt; 20 SRE（&lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/vendors/grafana-oncall/" data-link-title="Grafana OnCall" data-link-desc="OSS-friendly on-call 平台、Grafana Labs 維護、Apache 2.0、Grafana IRM bundle 把 OnCall &amp;#43; Incident 收進一個 alert-to-resolve 流程">Grafana OnCall&lt;/a> 或 PagerDuty Lite 已足夠）&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>對 &lt;em>新案&lt;/em>：不要選 Opsgenie standalone。直接評估 PagerDuty → JSM Premium 一次到位、或 PagerDuty → incident.io（如果 Slack-first 是 driver）。&lt;/p></description><content:encoded><![CDATA[<table>
  <thead>
      <tr>
          <th>PagerDuty 物件</th>
          <th>Opsgenie 對應</th>
          <th>JSM Cloud 對應（2027 後）</th>
          <th>翻譯難度</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Service</td>
          <td>Integration</td>
          <td>Service registry</td>
          <td>低</td>
      </tr>
      <tr>
          <td>Escalation Policy</td>
          <td>Escalation</td>
          <td>Escalation</td>
          <td>中</td>
      </tr>
      <tr>
          <td>Schedule（layer model）</td>
          <td>Schedule（rotation）</td>
          <td>Schedule</td>
          <td>中-高</td>
      </tr>
      <tr>
          <td>User</td>
          <td>User</td>
          <td>Atlassian Account</td>
          <td>中（IdP 整合）</td>
      </tr>
      <tr>
          <td>Team</td>
          <td>Team</td>
          <td>JSM Team</td>
          <td>低</td>
      </tr>
      <tr>
          <td>Event API v2</td>
          <td>Alert API</td>
          <td>JSM REST API</td>
          <td>中</td>
      </tr>
      <tr>
          <td>Event Orchestration</td>
          <td>Policy</td>
          <td>Routing rule</td>
          <td>中-高</td>
      </tr>
      <tr>
          <td>Status Page</td>
          <td>Statuspage（同產品）</td>
          <td>Statuspage</td>
          <td>低</td>
      </tr>
      <tr>
          <td>Postmortem</td>
          <td>（無原生）</td>
          <td>（Confluence template）</td>
          <td>高（要外接）</td>
      </tr>
  </tbody>
</table>
<p>這張對照表是 PagerDuty → Opsgenie migration 的 <em>表面 schema mapping</em>、但表前必須先處理一個前提：<strong>Atlassian 2025 公開宣布 Opsgenie 將在 2027-04 EOL</strong>、現有 Opsgenie 客戶會被遷往 <a href="https://www.atlassian.com/software/jira/service-management">Jira Service Management Premium / Enterprise</a> 內建的 on-call 能力。這條 migration 不是 PagerDuty ↔ Opsgenie 的 vendor swap、是 <em>PagerDuty → Opsgenie → JSM Cloud</em> 的雙 hop migration。</p>
<h2 id="誰應該考慮這條-migration">誰應該考慮這條 migration</h2>
<table>
  <thead>
      <tr>
          <th>適用條件</th>
          <th>不適用</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>已是 Atlassian-heavy ecosystem（JSM / Confluence / Bitbucket）</td>
          <td>純 Slack-first org（考慮 <a href="/blog/backend/08-incident-response/vendors/pagerduty/migrate-to-incident-io/" data-link-title="PagerDuty → incident.io：「On-call」是個 retconned word、同名不同 contract" data-link-desc="PagerDuty → incident.io 不是 schema translation — 兩家的「on-call」字面相同、contract 不同（alert routing vs IR coordination &#43; Slack-native &#43; retrospective）。本文走 Type E paradigm shift、6 維 audit 顯示 paradigm / schema / operational 三軸 High、用 4-phase partial migration（不收斂、Phase 1-2 多數 org 停留）、5 個 production 踩雷（雙系統 state drift / severity 翻譯失真 / schedule layer 漏 / Slack channel 過載 / retrospective 斷層）、跟 PagerDuty Process Automation / AIOps 沒對應的 capability gap">→ incident.io</a>）</td>
      </tr>
      <tr>
          <td>已買 JSM Premium / Enterprise、Opsgenie 是 entitled benefit</td>
          <td>新案、無 Atlassian 基礎</td>
      </tr>
      <tr>
          <td>願意走 PD → Opsgenie → JSM 雙 hop（或直接跳 JSM）</td>
          <td>不想多次 migration、想一步到位</td>
      </tr>
      <tr>
          <td>Atlassian Identity / Cloud admin 已成熟</td>
          <td>SSO / IdP 跟 Atlassian 沒整合好</td>
      </tr>
      <tr>
          <td>OSS / 自管不可行（compliance / 規模）</td>
          <td>規模 &lt; 20 SRE（<a href="/blog/backend/08-incident-response/vendors/grafana-oncall/" data-link-title="Grafana OnCall" data-link-desc="OSS-friendly on-call 平台、Grafana Labs 維護、Apache 2.0、Grafana IRM bundle 把 OnCall &#43; Incident 收進一個 alert-to-resolve 流程">Grafana OnCall</a> 或 PagerDuty Lite 已足夠）</td>
      </tr>
  </tbody>
</table>
<p>對 <em>新案</em>：不要選 Opsgenie standalone。直接評估 PagerDuty → JSM Premium 一次到位、或 PagerDuty → incident.io（如果 Slack-first 是 driver）。</p>
<p>對 <em>已是 Opsgenie 客戶但從 PagerDuty 遷入的 org</em>（少見、通常是 acquisition consolidation）：本文仍適用、但要把 Phase 5 EOL 路徑放在規劃裡。</p>
<h2 id="為什麼是-type-aschema-為主">為什麼是 Type A（schema 為主）</h2>
<p>跑 <a href="/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/#6-%e7%b6%ad-diff-dimension-audit" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">6 維 diff dimension audit</a>：</p>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>評</th>
          <th>說明</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Schema</td>
          <td>Medium-High</td>
          <td>escalation policy / schedule / integration / API endpoint 都有 mapping、但概念對應度高</td>
      </tr>
      <tr>
          <td>Operational</td>
          <td>Low</td>
          <td>同為 alert routing + on-call schedule 平台、ops 模型一致</td>
      </tr>
      <tr>
          <td>Paradigm</td>
          <td>Low</td>
          <td>同 paging-first paradigm</td>
      </tr>
      <tr>
          <td>Components</td>
          <td>Low</td>
          <td>都是 SaaS 平台、no multi-tool decomposition</td>
      </tr>
      <tr>
          <td>App change</td>
          <td>Medium</td>
          <td>webhook URL / integration key 要換、application code 改動少</td>
      </tr>
      <tr>
          <td>Topology</td>
          <td>Low</td>
          <td>都是 cloud SaaS</td>
      </tr>
  </tbody>
</table>
<p>Schema = Medium-High（其他 Low） → <strong>Type A phased translation</strong>。比標準 Type A 11-12 章短、因 paradigm 不變、不需要重新訓練 SRE 行為。</p>
<h2 id="driveratlassian-vendor-consolidation">Driver：Atlassian vendor consolidation</h2>
<p>從 PagerDuty 遷入 Opsgenie 的核心 driver 是 <em>Atlassian 全家桶整合</em> — 已經買 JSM + Confluence + Bitbucket + Statuspage 的 org、再買 PagerDuty 等於多一條 SaaS 採購線、SSO 配置、billing 對接、user provisioning 重複。Opsgenie（或未來 JSM Premium 內建 on-call）走 Atlassian Identity、跟 JSM ticket / Confluence runbook / Statuspage component 同一個身份體系、incident 跟 ticket / status update 跨產品聯動不用 webhook chain。</p>
<p>這條 consolidation 拉力的具體形態：</p>
<ul>
<li><strong>單一 SSO + provisioning</strong>：Atlassian Cloud admin 一處 manage user / group / SSO、不需要 PagerDuty 獨立 SCIM + IdP 配置</li>
<li><strong>Ticket ↔ incident bi-directional</strong>：JSM ticket 升級成 incident、incident 自動建 ticket、close incident 自動 close ticket、不用 PagerDuty Jira integration plugin</li>
<li><strong>Runbook 跟 incident channel 同產品</strong>：Confluence runbook 從 Opsgenie alert 直接 link、不用維護兩套權限</li>
<li><strong>Status Page 共用 component model</strong>：Statuspage 已是 Atlassian 產品、Opsgenie incident 觸發 Status Page update 不用 webhook（內部 event）</li>
<li><strong>Billing 整合</strong>：Atlassian Cloud subscription bundle、CFO 不用對 5 條獨立 SaaS invoice</li>
</ul>
<p>這條 driver 在 PagerDuty 後加的 Status Updates / Jira plugin / Postmortems 模組下被部分削弱、但本質仍是 <em>Atlassian 是主、PagerDuty 是外掛</em> vs <em>全部都在 Atlassian</em> 的差別。</p>
<h2 id="type-a-phased-migration5-phase">Type A phased migration（5 phase）</h2>
<h3 id="phase-1schema-對照--識別差異">Phase 1：Schema 對照 + 識別差異</h3>
<p>把 PagerDuty 當前 config 完整 export（API endpoint <code>/services</code>、<code>/escalation_policies</code>、<code>/schedules</code>、<code>/users</code>、<code>/teams</code>、<code>/integrations</code>、<code>/event_orchestrations</code>）、對照上方 schema mapping table、識別 <em>無 1:1 對應的物件</em>：</p>
<ul>
<li>Event Orchestration rule 對 Opsgenie 的 Policy + Routing rule（複雜 routing 要拆）</li>
<li>Schedule layer model 對 Opsgenie 的 Rotation + Override（layer 疊加要展平）</li>
<li>PagerDuty AIOps / Process Automation 對 Opsgenie 的 <em>無對應</em> — 要評估是否丟掉這條能力</li>
</ul>
<p>完成標準：寫出 PagerDuty config inventory + Opsgenie target spec、確認所有物件都有 mapping path（即使是「捨棄」也算 mapping）。</p>
<h3 id="phase-2schedule--escalation-移植">Phase 2：Schedule + Escalation 移植</h3>
<p>PagerDuty schedule 是 layer 疊加（primary + secondary + override + restriction）、Opsgenie 是 <em>單一 rotation list + override</em>。簡單 schedule（單一 weekly rotation + 偶爾 override）直接對應、複雜 schedule（follow-the-sun + holiday + restriction time-of-day）要展平：</p>
<ul>
<li>PagerDuty <code>/schedules/{id}</code> 拉完整 <code>final_schedule</code>、用 <em>實際輪值結果</em> 重建 Opsgenie rotation</li>
<li>多層 schedule 在 Opsgenie 拆成多個 rotation、用 escalation chain 串</li>
<li>Restriction layer 在 Opsgenie 沒對應、要在 rotation rule 內 inline 時段限制</li>
</ul>
<p>Escalation policy 多 step + level-based timeout 在 Opsgenie 是 <em>step-based escalation</em>、直接對應、但每步 timeout 跟 acknowledge behavior 要 retest。</p>
<p>完成標準：on-call rotation 在 Opsgenie 跑一週、跟 PagerDuty parallel 對比實際 paging 行為一致（同一個 alert 兩邊都叫到對的人）。</p>
<h3 id="phase-3integration--webhook-改線">Phase 3：Integration / Webhook 改線</h3>
<p>每個 alert source（Splunk / Datadog / Cloudflare WAF / cloud control plane / synthetic monitor）的 webhook URL 從 PagerDuty Event API 換成 Opsgenie Alert API：</p>
<ul>
<li>Endpoint：<code>https://events.pagerduty.com/v2/enqueue</code> → <code>https://api.opsgenie.com/v2/alerts</code></li>
<li>Auth：PagerDuty <code>routing_key</code> → Opsgenie API key（per-integration）</li>
<li>Deduplication：PagerDuty <code>dedup_key</code> → Opsgenie <code>alias</code>（行為相同、欄位名不同）</li>
<li>Severity mapping：PagerDuty <code>severity</code>（info/warning/error/critical） → Opsgenie <code>priority</code>（P1-P5）</li>
</ul>
<p>這 phase 的工作量主要塊不是 schema 翻譯、是 <em>每個 integration 都要重新測 deduplication + severity</em>。新 integration key 配上去後第一週要密切監控、避免 dedup key 重設導致同事故開 100 個 incident。</p>
<p>完成標準：所有 alert source 都接 Opsgenie、PagerDuty 端 alert volume 降為 0。</p>
<h3 id="phase-4cutover--dual-ops-period">Phase 4：Cutover + dual ops period</h3>
<p>2-4 週 dual ops：alert 都進 Opsgenie 為主、PagerDuty 留作 backup paging（同樣 alert 也 mirror 進 PD、但 SRE response 全在 Opsgenie）。確認沒漏 alert、escalation 行為正確、Atlassian 整合（JSM ticket / Confluence runbook / Statuspage） wire 通。</p>
<p>完成標準：dual ops 4 週無漏 alert、SRE 沒回去 PagerDuty UI 操作。</p>
<h3 id="phase-5pagerduty-退役--opsgenie--jsm-eol-路徑規劃">Phase 5：PagerDuty 退役 + Opsgenie → JSM EOL 路徑規劃</h3>
<p>PagerDuty 退役後立即進入 <em>Opsgenie 2027 EOL 倒數</em>。這 phase 不是 PD migration 的尾巴、是 <em>下一條 migration 的起點</em>：</p>
<ul>
<li>2025-2026：Atlassian 推 JSM Premium 的 on-call 能力、提供 Opsgenie → JSM 遷移工具</li>
<li>2026-2027：實際遷 Opsgenie → JSM、schedule / integration / API 改線</li>
<li>2027-04：Opsgenie EOL、所有 traffic 必須在 JSM</li>
</ul>
<p>完成標準：PagerDuty 帳號取消、Opsgenie deployment 健康運作 + JSM unification roadmap 寫進 2026-2027 SRE OKR。</p>
<h2 id="5-個-production-踩雷">5 個 production 踩雷</h2>
<h3 id="1-escalation-step-routing-行為差異">1. Escalation step routing 行為差異</h3>
<p>PagerDuty escalation policy 的 step timeout 是 <em>每步獨立 acknowledge window</em>（step 1 等 5 分鐘沒人 ack → step 2 等 5 分鐘沒人 ack → &hellip;）、Opsgenie escalation 的行為類似但 <em>step 之間的 notification cumulative behavior</em> 不同 — Opsgenie 預設 step 2 觸發後 step 1 的人 <em>仍會收到 notification</em>（除非設定 step 1 not yet acknowledged 才繼續）。修法是寫測試 case 對比 alert 在兩邊 escalation 過程的 notification timeline、調整 Opsgenie escalation rule 的 acknowledge propagation 設定到跟 PD 一致。</p>
<h3 id="2-heartbeat-monitoring-在-pagerduty-沒對應">2. Heartbeat monitoring 在 PagerDuty 沒對應</h3>
<p>Opsgenie Heartbeat 是 <em>被動 monitoring</em> — service 必須定期 ping 一個 endpoint、超過 interval 沒 ping 就觸發 alert、用來監控 cron job / scheduled task 是否還在跑。PagerDuty 沒原生 Heartbeat、通常用 external service（Healthchecks.io / Dead Man&rsquo;s Snitch）。從 PD 遷入 Opsgenie 時、把這些 external service 收回 Opsgenie Heartbeat、減少 SaaS 數量。但反向（從 Opsgenie 遷出時要先把 Heartbeat dependency 外接）是不同問題、不在本篇 scope。</p>
<h3 id="3-integration-key-改線時-deduplication-重設">3. Integration key 改線時 deduplication 重設</h3>
<p>PagerDuty <code>dedup_key</code> → Opsgenie <code>alias</code> 行為相同、但 <em>新 integration key 上線後第一個 alert 不會跟舊 PD incident 對應</em> — 同一個事故在 PD 上是 incident #5234、在 Opsgenie 上是新 alert 從零開始。Phase 3 切換時間點如果剛好遇到 active incident、會分裂成兩個系統內各自的 incident、SRE confusion。修法是 cutover 時間點選擇在 <em>known quiet period</em>（一般是週末早上、避開 deploy 時段）、並接受第一個切換期間有手動 reconcile 的工作。</p>
<h3 id="4-schedule-時區處理">4. Schedule 時區處理</h3>
<p>PagerDuty schedule 的 timezone 是 <em>per-layer</em> 設定（layer 1 可以 PST、layer 2 可以 GMT）、Opsgenie rotation timezone 是 <em>per-schedule</em> 設定。Follow-the-sun schedule（亞太 / 歐洲 / 美洲三層）在 PD 是三 layer 各自 timezone、在 Opsgenie 要拆成三個 schedule 各自設定 timezone 用 escalation 串。Daylight saving transition 是另一個高風險點 — PD 跟 Opsgenie 在 DST 切換週的行為要分別測試。</p>
<h3 id="5-atlassian-identity-sso-整合">5. Atlassian Identity SSO 整合</h3>
<p>如果 org 既有 SSO（Okta / Azure AD）已經跟 PagerDuty 整合、遷 Opsgenie 時要 <em>重新對接 Atlassian Identity</em>。Atlassian Cloud 的 SSO 是在 Atlassian admin 層設定、跟個別產品（Opsgenie / JSM）獨立。常見問題：</p>
<ul>
<li>PagerDuty user email 不一定等於 Atlassian account email（有人用 work email 註冊 PD、用 personal email 註冊 Atlassian）</li>
<li>SCIM provisioning rule 要重寫、group / role mapping 重新設計</li>
<li>Just-in-time user provisioning behavior 不同（PD 是即時、Atlassian 可能需要 admin 手動 approve）</li>
</ul>
<p>修法是 Phase 1 schema mapping 時就把 user identity reconcile 列為獨立工作塊、不要假設 email 唯一對應。</p>
<h2 id="容量與成本對照">容量與成本對照</h2>
<table>
  <thead>
      <tr>
          <th>項目</th>
          <th>PagerDuty</th>
          <th>Opsgenie</th>
          <th>JSM Premium（2027 後）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>計費模式</td>
          <td>Per-user / month、tier-based</td>
          <td>Per-user / month、Free tier ≤ 5 user</td>
          <td>JSM seat + on-call entitlement</td>
      </tr>
      <tr>
          <td>Atlassian bundle</td>
          <td>獨立 SaaS</td>
          <td>Atlassian Cloud subscription</td>
          <td>JSM Premium / Enterprise 內建</td>
      </tr>
      <tr>
          <td>AIOps</td>
          <td>Enterprise + add-on</td>
          <td>弱（無原生 ML grouping）</td>
          <td>（roadmap）</td>
      </tr>
      <tr>
          <td>Heartbeat</td>
          <td>不適用</td>
          <td>內建</td>
          <td>內建</td>
      </tr>
      <tr>
          <td>Status Page</td>
          <td>內建（Business tier+）</td>
          <td>Statuspage（同 Atlassian、單獨計費）</td>
          <td>Statuspage 整合</td>
      </tr>
      <tr>
          <td>隱性 EOL 風險</td>
          <td>無</td>
          <td>2027-04 EOL</td>
          <td>Atlassian 主推</td>
      </tr>
  </tbody>
</table>
<p>實際 TCO 對比 <em>不能只看 per-seat price</em> — 必須加上：</p>
<ul>
<li>Atlassian Cloud bundle discount（多產品同訂閱通常有 15-25% 折扣）</li>
<li>PagerDuty AIOps + Process Automation 是否在用（如果在用、Opsgenie 沒對應、要外接成本）</li>
<li>雙 hop migration（PD → Opsgenie → JSM）的累計工程成本 vs 單 hop（PD → JSM 跳過 Opsgenie）</li>
</ul>
<h2 id="何時跳過-opsgenie-直接-pd--jsm">何時跳過 Opsgenie 直接 PD → JSM</h2>
<p>對 <em>已是 Atlassian-heavy org</em> 但 <em>尚未用 Opsgenie</em> 的場景、Opsgenie 2027 EOL 表示 PD → Opsgenie → JSM 雙 hop 不划算。直接 PD → JSM Premium：</p>
<ul>
<li>等 Atlassian 2026 公開 JSM 內建 on-call 的完整能力、確認 feature parity 跟 Opsgenie 相當</li>
<li>規劃 PD → JSM 一次 migration、結構接近本篇但 target 換成 JSM</li>
<li>風險：JSM 內建 on-call 在 2026 仍可能成熟度不夠、決策時點要看 Atlassian 公開 roadmap</li>
</ul>
<p>對 <em>已是 Opsgenie 客戶</em> 的場景、本篇的 PD → Opsgenie 路徑仍適用、但 Phase 5 EOL 路徑規劃是必要 deliverable、不是 optional。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>平行 batch：<a href="/blog/backend/08-incident-response/vendors/pagerduty/migrate-to-incident-io/" data-link-title="PagerDuty → incident.io：「On-call」是個 retconned word、同名不同 contract" data-link-desc="PagerDuty → incident.io 不是 schema translation — 兩家的「on-call」字面相同、contract 不同（alert routing vs IR coordination &#43; Slack-native &#43; retrospective）。本文走 Type E paradigm shift、6 維 audit 顯示 paradigm / schema / operational 三軸 High、用 4-phase partial migration（不收斂、Phase 1-2 多數 org 停留）、5 個 production 踩雷（雙系統 state drift / severity 翻譯失真 / schedule layer 漏 / Slack channel 過載 / retrospective 斷層）、跟 PagerDuty Process Automation / AIOps 沒對應的 capability gap">PagerDuty → incident.io</a>（Type E、Slack-first paradigm shift）/ <a href="/blog/backend/08-incident-response/vendors/atlassian-statuspage/migrate-to-instatus/" data-link-title="Atlassian Statuspage → Instatus：status page 成本下降、但 compatibility audit 不能跳" data-link-desc="Atlassian Statuspage → Instatus 是 Type B drop-in migration、6 維 audit 全 Low；典型情境是從 Statuspage Business / Enterprise 降到 Instatus Pro / Business、但 savings 取決於 subscriber、SSO、audit 與 SLA report 需求。本文走 compatibility audit prefix（subscriber channel 完整度 / SAML SSO / audit log / metrics integration / SLA report / API parity）、4 階段 cutover（DNS TTL &#43; parallel run）、5 個 production 踩雷（SSO tier 選錯、metrics 來源整合斷、subscriber import format / SLA report 缺、custom CSS 不完全相容）、何時不要切（enterprise compliance / 強 Atlassian 整合）">Atlassian Statuspage → Instatus</a>（Type B drop-in）</li>
<li>同 batch Type A：（待補、本篇是 batch 唯一 Type A）</li>
<li>上游：<a href="/blog/backend/08-incident-response/incident-workflow-automation-boundary/" data-link-title="8.21 Incident Workflow Automation Boundary" data-link-desc="定義哪些事故流程適合自動化，哪些決策需要保留人工確認">8.10 Incident Workflow Automation Boundary</a></li>
<li>下游：未來 Opsgenie → JSM Premium migration（2026-2027 寫）</li>
<li>vendor 對照：<a href="/blog/backend/08-incident-response/vendors/pagerduty/" data-link-title="PagerDuty" data-link-desc="On-call / alerting 主流 SaaS、IR 平台演化">PagerDuty</a> / <a href="/blog/backend/08-incident-response/vendors/opsgenie/" data-link-title="Opsgenie" data-link-desc="Atlassian on-call、跟 Jira / Statuspage 套件整合、JSM Premium migration 議題">Opsgenie</a> / <a href="/blog/backend/08-incident-response/vendors/incident-io/" data-link-title="incident.io" data-link-desc="Slack-native IR 平台、整合 paging / response / retro">incident.io</a></li>
<li>方法論：<a href="/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">Migration Playbook Methodology</a>（Type A phased translation 結構說明）</li>
</ul>
]]></content:encoded></item><item><title>Pyroscope → Datadog Continuous Profiler：profiling deployment lifecycle 各階段 operational ownership 轉手</title><link>https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/datadog-continuous-profiler/migrate-from-pyroscope/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/09-performance-capacity/vendors/datadog-continuous-profiler/migrate-from-pyroscope/</guid><description>&lt;p>Continuous profiling deployment 的 lifecycle 有五階段：&lt;strong>install&lt;/strong>（agent / SDK 部署） → &lt;strong>instrument&lt;/strong>（service / env / version tag 注入） → &lt;strong>ingest&lt;/strong>（profile sample 進 backend store） → &lt;strong>query&lt;/strong>（flame graph / diff / explore） → &lt;strong>cost&lt;/strong>（storage retention / billing）。Pyroscope 跟 Datadog Continuous Profiler 在這五階段的 &lt;em>ops ownership 分布完全不同&lt;/em>：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>階段&lt;/th>
 &lt;th>Pyroscope（self-host）&lt;/th>
 &lt;th>Datadog Continuous Profiler&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Install&lt;/td>
 &lt;td>Grafana Alloy / Pyroscope agent / per-language SDK、自己部署&lt;/td>
 &lt;td>Datadog Agent（多半 APM 已部署）、SDK 加 flag&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Instrument&lt;/td>
 &lt;td>tag schema 自己設計&lt;/td>
 &lt;td>用 Datadog 既有 &lt;code>service&lt;/code> / &lt;code>env&lt;/code> / &lt;code>version&lt;/code> tag&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Ingest&lt;/td>
 &lt;td>Pyroscope server（自管 storage / scaling）&lt;/td>
 &lt;td>Datadog SaaS（vendor 管）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Query&lt;/td>
 &lt;td>Grafana datasource explore / flame graph panel&lt;/td>
 &lt;td>Datadog APM 介面、跟 trace / log / metrics deep link&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Cost&lt;/td>
 &lt;td>self-host TCO（storage + ops + on-call）&lt;/td>
 &lt;td>按 APM host 計費（profiling 是 add-on）&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>從 Pyroscope 遷出 Datadog Continuous Profiler 的本質是 &lt;em>operational ownership 從 self-host 轉手到 SaaS&lt;/em> — pprof data model 跟 flame graph 視覺幾乎一樣、profile diff workflow 接近、&lt;em>差異 90% 在 ops 跟 ecosystem integration&lt;/em>。schema / paradigm 差距小、operational 差距大、就是 Type C operational hybrid 的 signature。&lt;/p>
&lt;h2 id="為什麼是-type-coperational-為主">為什麼是 Type C（operational 為主）&lt;/h2>
&lt;p>跑 &lt;a href="https://tarrragon.github.io/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/#6-%e7%b6%ad-diff-dimension-audit" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">6 維 diff dimension audit&lt;/a>：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>維度&lt;/th>
 &lt;th>評&lt;/th>
 &lt;th>說明&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Schema&lt;/td>
 &lt;td>Low-Medium&lt;/td>
 &lt;td>pprof 是 industry standard、profile types (CPU / heap / etc) 接近&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Operational&lt;/td>
 &lt;td>High&lt;/td>
 &lt;td>self-host backend storage / retention / scaling → SaaS 全託管&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Paradigm&lt;/td>
 &lt;td>Low&lt;/td>
 &lt;td>都是 pprof-based continuous profiling、diff workflow 接近&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Components&lt;/td>
 &lt;td>Low-Medium&lt;/td>
 &lt;td>都需要 agent + backend、元件數量接近&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>App change&lt;/td>
 &lt;td>Low&lt;/td>
 &lt;td>agent / SDK config 改、code instrumentation 接近&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Topology&lt;/td>
 &lt;td>Low&lt;/td>
 &lt;td>都是 agent → backend 單向 ingest&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>Operational = High（其他 Low） → &lt;strong>Type C operational hybrid&lt;/strong>。Type C 結構是 &lt;em>operational audit prefix + 4-phase drop-in cutover&lt;/em> — operational diff 集中在 ingest / cost / retention 三階段、其他階段是 schema-level drop-in。&lt;/p></description><content:encoded><![CDATA[<p>Continuous profiling deployment 的 lifecycle 有五階段：<strong>install</strong>（agent / SDK 部署） → <strong>instrument</strong>（service / env / version tag 注入） → <strong>ingest</strong>（profile sample 進 backend store） → <strong>query</strong>（flame graph / diff / explore） → <strong>cost</strong>（storage retention / billing）。Pyroscope 跟 Datadog Continuous Profiler 在這五階段的 <em>ops ownership 分布完全不同</em>：</p>
<table>
  <thead>
      <tr>
          <th>階段</th>
          <th>Pyroscope（self-host）</th>
          <th>Datadog Continuous Profiler</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Install</td>
          <td>Grafana Alloy / Pyroscope agent / per-language SDK、自己部署</td>
          <td>Datadog Agent（多半 APM 已部署）、SDK 加 flag</td>
      </tr>
      <tr>
          <td>Instrument</td>
          <td>tag schema 自己設計</td>
          <td>用 Datadog 既有 <code>service</code> / <code>env</code> / <code>version</code> tag</td>
      </tr>
      <tr>
          <td>Ingest</td>
          <td>Pyroscope server（自管 storage / scaling）</td>
          <td>Datadog SaaS（vendor 管）</td>
      </tr>
      <tr>
          <td>Query</td>
          <td>Grafana datasource explore / flame graph panel</td>
          <td>Datadog APM 介面、跟 trace / log / metrics deep link</td>
      </tr>
      <tr>
          <td>Cost</td>
          <td>self-host TCO（storage + ops + on-call）</td>
          <td>按 APM host 計費（profiling 是 add-on）</td>
      </tr>
  </tbody>
</table>
<p>從 Pyroscope 遷出 Datadog Continuous Profiler 的本質是 <em>operational ownership 從 self-host 轉手到 SaaS</em> — pprof data model 跟 flame graph 視覺幾乎一樣、profile diff workflow 接近、<em>差異 90% 在 ops 跟 ecosystem integration</em>。schema / paradigm 差距小、operational 差距大、就是 Type C operational hybrid 的 signature。</p>
<h2 id="為什麼是-type-coperational-為主">為什麼是 Type C（operational 為主）</h2>
<p>跑 <a href="/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/#6-%e7%b6%ad-diff-dimension-audit" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">6 維 diff dimension audit</a>：</p>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>評</th>
          <th>說明</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Schema</td>
          <td>Low-Medium</td>
          <td>pprof 是 industry standard、profile types (CPU / heap / etc) 接近</td>
      </tr>
      <tr>
          <td>Operational</td>
          <td>High</td>
          <td>self-host backend storage / retention / scaling → SaaS 全託管</td>
      </tr>
      <tr>
          <td>Paradigm</td>
          <td>Low</td>
          <td>都是 pprof-based continuous profiling、diff workflow 接近</td>
      </tr>
      <tr>
          <td>Components</td>
          <td>Low-Medium</td>
          <td>都需要 agent + backend、元件數量接近</td>
      </tr>
      <tr>
          <td>App change</td>
          <td>Low</td>
          <td>agent / SDK config 改、code instrumentation 接近</td>
      </tr>
      <tr>
          <td>Topology</td>
          <td>Low</td>
          <td>都是 agent → backend 單向 ingest</td>
      </tr>
  </tbody>
</table>
<p>Operational = High（其他 Low） → <strong>Type C operational hybrid</strong>。Type C 結構是 <em>operational audit prefix + 4-phase drop-in cutover</em> — operational diff 集中在 ingest / cost / retention 三階段、其他階段是 schema-level drop-in。</p>
<h2 id="drivertco--datadog-ecosystem-內-deep-linking">Driver：TCO + Datadog ecosystem 內 deep linking</h2>
<p>從 Pyroscope 遷出 Datadog Profiler 的核心 driver 有兩條：</p>
<p><strong>TCO（total cost of ownership）</strong>：self-host Pyroscope 看起來免費（Apache 2.0）、但實際 ops 成本：</p>
<ul>
<li>Storage：profile sample 大、retention 與 storage cost 需要自己估（每 service 每天可能 1-10 GB）</li>
<li>Scaling：profile ingestion 突增（deploy event / canary rollout 期間）要 storage / ingester 撐住</li>
<li>On-call：Pyroscope server 自己會壞、要 on-call 帶</li>
<li>Ops engineer time：規模成長後可能需要 0.5-1 個 FTE 維護 Grafana stack 內的 Pyroscope</li>
</ul>
<p>對 <em>已經有 Datadog APM 帳單</em> 的 org、profiling 會跟 APM / profiled host 進同一個商務談判與 usage report，不需要額外 ops headcount。這條 TCO 拉力對 50-500 人 eng 規模最強 — 小於 50 人 self-host 也撐得住、大於 500 人 self-host 的 economy of scale 可能開始 favored Pyroscope。</p>
<p><strong>Ecosystem deep linking</strong>：Datadog Profiler 跟 trace / log / metrics <em>在同一個介面</em>、profile span 直接連到 trace span、deploy marker 直接顯示在 flame graph timeline、cross-signal query 不用 wire。Pyroscope 要透過 Grafana datasource correlation 達到類似效果、但需要 Tempo / Loki 已部署 + 手動配 correlation rule、整合精度跟自動程度都不如 Datadog 內建。</p>
<p>這條 driver 對 <em>已是 Datadog-heavy org</em> 強、對 <em>Grafana-heavy org</em> 弱（後者 Pyroscope 才是自然選擇、Datadog Profiler 反而 ecosystem misfit）。</p>
<h2 id="type-c-migration4-phase">Type C migration（4-phase）</h2>
<h3 id="phase-1operational-audit">Phase 1：Operational audit</h3>
<p>確認 Datadog Continuous Profiler 能 cover Pyroscope 當前用途、且 ops ownership 轉移可接受：</p>
<ul>
<li><strong>Language coverage</strong>：當前 Pyroscope 用哪些 SDK？Datadog Profiler 支援 Go / Java / Python / Node / Ruby / .NET / PHP / Rust / C / C++，但每個語言的 profiler type 與啟用方式不同；Erlang 等較小眾語言仍要逐項驗證</li>
<li><strong>Profile type coverage</strong>：Pyroscope 抓的 profile type（CPU / heap / allocation / goroutine / lock / wall time）在 Datadog Profiler 同語言是否都支援？Java 跟 Go 兩家都全、其他語言可能 partial</li>
<li><strong>Retention requirement</strong>：Pyroscope retention 可自管；Datadog Profiler retention 依產品資料保留政策與合約設定，要確認是否滿足既有 long-term baseline / audit 查詢需求</li>
<li><strong>資料主權</strong>：profile data 包含 application function name / line number、有時帶 customer data hint（function 名字暗示 customer-specific 邏輯）— 是否能 send to SaaS？</li>
<li><strong>Cost forecast</strong>：Datadog public pricing 以 profiled host / APM tier 計費，估算時要用實際 host 數、container density、APM plan 與 commit discount 跟 Pyroscope self-host TCO 比</li>
</ul>
<p>完成標準：寫出「Datadog 能 cover、不能 cover、不確定」三欄、不確定欄全部問過 Datadog SE / 用 trial 跑過 production-like load。</p>
<h3 id="phase-2agent-parallel-runprofile-雙寫">Phase 2：Agent parallel run（profile 雙寫）</h3>
<p>Datadog Agent 多半已部署（如果在用 Datadog APM）。Phase 2 在現有 Datadog Agent 開 profiling flag、<em>不關 Pyroscope agent</em>、跑 2-4 週 parallel：</p>
<ul>
<li>設定 <code>DD_PROFILING_ENABLED=true</code>（per service env var）</li>
<li>每個 service SDK init 加對應 profiling enable call（Go: <code>profiler.Start()</code>、Python: <code>import ddtrace.profiling.auto</code>、Java: agent flag 即可）</li>
<li>Pyroscope SDK / Alloy 繼續跑、profile 雙寫到兩家</li>
<li>對比同一個 service / 同一個時間段在 Pyroscope flame graph 跟 Datadog Profiler flame graph、確認 hot path 一致</li>
</ul>
<p>Parallel run 期間的 overhead：兩邊 agent 同時跑 profiling、CPU overhead 大致 2-4%（單一 profiler 通常 1-2%、雙寫 double）、production-acceptable but not free。Phase 2 不要超過 4 週、避免長期 double overhead。</p>
<p>完成標準：每個 production service 在 Datadog Profiler 都有 4 週連續 profile data、跟 Pyroscope flame graph 對比一致。</p>
<h3 id="phase-3tag-schema-reconcile--trace-correlation">Phase 3：Tag schema reconcile + trace correlation</h3>
<p>Pyroscope tag schema（自己設計）跟 Datadog standard tag（<code>service</code> / <code>env</code> / <code>version</code> / <code>host</code>）對齊：</p>
<ul>
<li>Pyroscope tag <code>app=checkout-api</code> → Datadog <code>service:checkout-api</code></li>
<li>Pyroscope tag <code>env=prod-us</code> → Datadog <code>env:prod</code> + <code>region:us-east-1</code></li>
<li>Pyroscope tag <code>git_sha=abc123</code> → Datadog <code>version:abc123</code>（透過 <code>DD_VERSION</code>）</li>
<li>Custom tag（team / business unit）→ Datadog custom tag（透過 SDK config 或 agent label）</li>
</ul>
<p>Trace correlation：Datadog Profiler 自動跟 APM trace 關聯（透過 <code>trace_id</code> injection into profile sample）— Phase 3 要驗證這個 correlation 可用（在 Datadog APM 點 trace span、應該能跳到對應時段 profile）。</p>
<p>Deploy marker：CI 在 deploy 時打 Datadog deployment marker（<code>datadog-ci deployment mark</code> 或 API call）、讓 Profiler diff view 知道 baseline / candidate 邊界。</p>
<p>完成標準：tag schema 1:1 對應、trace → profile deep link 可用、deploy marker 自動推送。</p>
<h3 id="phase-4pyroscope-agent-關掉--server-退役">Phase 4：Pyroscope agent 關掉 + server 退役</h3>
<p>逐步關 Pyroscope agent（per service rollout）：</p>
<ul>
<li>先關低重要性 service（dev / staging / non-critical prod）</li>
<li>觀察 1-2 週、確認沒事故再關下一批</li>
<li>最後關 critical service、留 Pyroscope server 跑 1-2 週空 ingest（rollback 緩衝）</li>
<li>取消 Pyroscope server（decommission storage、release K8s resource、關 on-call rotation）</li>
</ul>
<p>Pyroscope 歷史 profile data 保留策略：</p>
<ul>
<li>多數場景：直接 archive S3 / GCS、未來查得到但不維護 query UI</li>
<li>強合規場景：export Pyroscope flame graph data 為 pprof file 保存（pprof 是長期可讀格式）</li>
</ul>
<p>完成標準：所有 production service 只走 Datadog Profiler、Pyroscope server 取消、TCO 對比驗證符合預期。</p>
<h2 id="5-個-production-踩雷">5 個 production 踩雷</h2>
<h3 id="1-兩家-agent-同時跑造成-production-overhead">1. 兩家 agent 同時跑造成 production overhead</h3>
<p>Phase 2 parallel run 期間 CPU overhead 2-4%、預期內。但有些 service 設定錯誤（例如 sampling rate 預設都拉高）變成 6-10% overhead、p99 飄升、誤判為 Datadog Profiler 自己的問題。修法是 <em>parallel run 期間 Pyroscope sampling rate 降低 50%</em>（已經有歷史 baseline、不需要全採）、且 Phase 2 不要在 peak event 期間跑。</p>
<h3 id="2-tag-schema-不一致導致-historic-baseline-對不上">2. Tag schema 不一致導致 historic baseline 對不上</h3>
<p>Pyroscope tag <code>app=checkout-api</code> 跟 Datadog <code>service:checkout-api</code> 都指同一個 service、但 Datadog 內 <em>historic profile</em> 沒有 <code>app</code> tag、所以從 Pyroscope 視角看 baseline 跟 Datadog 視角看 baseline <em>是不同的時段切片</em>。Release regression 比較時用錯 baseline、會誤判 release 沒問題（實際 baseline 不對應）。修法是 Phase 3 明確記錄 <em>Datadog Profiler 的 baseline 起算時間是 Phase 2 開始日</em>、Pyroscope 歷史不直接搬入比較。</p>
<h3 id="3-trace_id-correlation-斷phase-3-最常見">3. Trace_id correlation 斷（Phase 3 最常見）</h3>
<p>Datadog Profiler 自動關聯 trace 的前提是 <em>同一個 Datadog Agent + APM SDK 注入 trace_id</em>。如果 service 用 OpenTelemetry SDK + Datadog Agent（OTel-first 配置）、trace_id 注入方式不同、profile 跟 trace 可能無法自動 correlate。修法是 <em>確認所有 service 用 Datadog SDK 或正確配 OTel-to-Datadog converter</em>、在 Datadog APM 介面 random 抽 10 個 trace 驗證 profile correlation 是否 wire 通。</p>
<h3 id="4-cost-突增phase-4-後常見">4. Cost 突增（Phase 4 後常見）</h3>
<p>關掉 Pyroscope agent 後、Datadog Profiler 變成 sole profile source、ingest volume 上升、Datadog bill 比預估高 30-50%。原因通常是：</p>
<ul>
<li>Profile sampling rate 不小心開太高（部分 service config 沒對齊）</li>
<li>Custom tag 太多（每個 unique tag combination 增加 indexing cost）</li>
<li>Profile event 量比預估高（service count × sampling rate × profile types）</li>
</ul>
<p>修法是 Phase 1 cost forecast 要保留 30% buffer、且 Phase 4 完成後立即跑 Datadog usage report 確認 actual 跟 forecast 對比。</p>
<h3 id="5-retention--baseline-政策變動造成歷史-query-斷層">5. Retention / baseline 政策變動造成歷史 query 斷層</h3>
<p>Pyroscope 自管 retention 可以設成配合內部 storage 與 compliance policy；Datadog Profiler 的 retention 依產品資料保留政策與合約設定。真正的風險不是固定「7 天 vs 90 天」，而是 <em>既有 baseline 查詢習慣是否還成立</em>：原 Pyroscope user 可能習慣查特定 release 前後的 flame graph、Datadog 端則要看 profile tag、deployment marker 與保留政策能否支援同樣查詢。修法是 Phase 1 明確列出「要查多久前、用什麼 tag 找、誰有權限看」三個問題，超出 profile retention 的長期 trend 改用 Datadog metrics-derived signal（cumulative CPU% / memory growth rate）或保留 Pyroscope archive。</p>
<h2 id="capability-對照">Capability 對照</h2>
<table>
  <thead>
      <tr>
          <th>能力</th>
          <th>Pyroscope（self-host）</th>
          <th>Datadog Continuous Profiler</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Language SDK 覆蓋</td>
          <td>Go / Java / Python / Node / Ruby / .NET / Rust / PHP</td>
          <td>Go / Java / Python / Node / Ruby / .NET / PHP / Rust / C / C++</td>
      </tr>
      <tr>
          <td>Profile type（CPU / heap / lock / etc）</td>
          <td>全（依語言 SDK 而定）</td>
          <td>全（依語言 SDK 而定）</td>
      </tr>
      <tr>
          <td>Flame graph diff workflow</td>
          <td>Grafana panel</td>
          <td>Datadog Profile Comparison</td>
      </tr>
      <tr>
          <td>Trace correlation</td>
          <td>手動配 Grafana correlation rule</td>
          <td>自動（trace_id injection）</td>
      </tr>
      <tr>
          <td>Deploy marker</td>
          <td>手動</td>
          <td>datadog-ci 自動</td>
      </tr>
      <tr>
          <td>Retention</td>
          <td>自管（無上限、cost 自負）</td>
          <td>依 Datadog retention policy / 合約設定</td>
      </tr>
      <tr>
          <td>資料主權</td>
          <td>完全自管</td>
          <td>SaaS（profile 出境）</td>
      </tr>
      <tr>
          <td>Ops ownership</td>
          <td>自管（storage / scaling / on-call）</td>
          <td>Vendor</td>
      </tr>
      <tr>
          <td>Cost model</td>
          <td>self-host TCO</td>
          <td>profiled host / APM tier / commit discount</td>
      </tr>
      <tr>
          <td>Cross-signal query</td>
          <td>Grafana cross-datasource</td>
          <td>Datadog native（trace / log / profile / metrics 同一 query bar）</td>
      </tr>
  </tbody>
</table>
<h2 id="何時不要切保留-pyroscope">何時不要切（保留 Pyroscope）</h2>
<ul>
<li><strong>資料主權 / compliance 不允許 profile data 出境</strong>：金融 / 醫療 / 政府 / 國防、保留 Pyroscope self-host</li>
<li><strong>內網 / air-gap 部署</strong>：物理上連不到 Datadog SaaS、保留 Pyroscope</li>
<li><strong>OSS-first / vendor neutrality policy</strong>：org 政策不允許 vendor lock-in profiling、保留 Pyroscope</li>
<li><strong>規模超大（&gt; 500 APM host）</strong>：Datadog Profiler add-on cost × host 數可能超過 Pyroscope self-host TCO、計算交叉點</li>
<li><strong>Long retention / 自訂 archive 強需求</strong>：若 profile data 必須照內部 retention policy 長期保存、保留 Pyroscope 或建立 export / archive 流程</li>
<li><strong>Datadog 不支援的語言或 profiler type</strong>：Erlang、特定 runtime 或特定 profile type 若 Datadog 無法覆蓋，保留 Pyroscope 為對應 service profiling</li>
</ul>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>平行 batch：<a href="/blog/backend/09-performance-capacity/vendors/k6/migrate-from-jmeter/" data-link-title="JMeter → k6：k6 不是 JMeter 的「script 版本」、是 VU model 取代 thread model" data-link-desc="JMeter → k6 是 Type E paradigm shift、不是把 .jmx XML 翻成 JavaScript — VU (virtual user) model 跟 thread group model 是兩種對「使用者行為」不同的建模方式。本文走 6 維 audit（Schema High / Paradigm High / Operational Medium）、釐清反向定義、4-phase partial migration（多數 org 停 Phase 2-3 hybrid）、5 production 踩雷（thread group 翻譯失真 / arrival rate vs concurrent VU 混淆 / protocol gap / 結果 schema 改 / CI integration 重做）、protocol gap（JDBC / JMS / LDAP 在 k6 沒原生對應）、何時不要切">JMeter → k6</a>（Type E paradigm shift）</li>
<li>同 batch Type C：（待補、本篇是 batch 唯一 Type C）</li>
<li>上游：<a href="/blog/backend/09-performance-capacity/performance-observability/" data-link-title="9.8 效能可觀測性" data-link-desc="saturation metric、USE / RED method、cost dashboard">9.8 Performance Observability</a> / <a href="/blog/backend/04-observability/continuous-profiling/" data-link-title="4.9 Continuous Profiling" data-link-desc="把 CPU / memory / lock profile 從一次性除錯升級為持續訊號">4.9 Continuous Profiling</a></li>
<li>下游：<a href="/blog/backend/09-performance-capacity/improvement-loop/" data-link-title="9.9 Performance Improvement Loop" data-link-desc="壓測 → profile → fix → re-test → release gate 的閉環">9.9 Performance Improvement Loop</a>（profile diff 接入 release regression workflow）</li>
<li>vendor 對照：<a href="/blog/backend/09-performance-capacity/vendors/pyroscope/" data-link-title="Pyroscope" data-link-desc="用 Grafana 生態與開源 profiling backend 建立可自管 profile diff 與 flame graph 的工具">Pyroscope</a> / <a href="/blog/backend/09-performance-capacity/vendors/datadog-continuous-profiler/" data-link-title="Datadog Continuous Profiler" data-link-desc="用 SaaS APM 整合、deployment marker 與 profile diff 支援 release regression 定位的 profiling 工具">Datadog Continuous Profiler</a> / <a href="/blog/backend/09-performance-capacity/vendors/parca/" data-link-title="Parca" data-link-desc="用 eBPF 與開源 continuous profiling 平台建立 infrastructure-wide profile evidence 的工具">Parca</a></li>
<li>方法論：<a href="/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">Migration Playbook Methodology</a>（Type C operational hybrid 結構說明）</li>
</ul>
]]></content:encoded></item></channel></rss>