<?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>Cloud on Tarragon</title><link>https://tarrragon.github.io/blog/tags/cloud/</link><description>Recent content in Cloud on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Fri, 26 Jun 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/tags/cloud/index.xml" rel="self" type="application/rss+xml"/><item><title>有 SSH 但沒有 IaC 的雲端環境接管</title><link>https://tarrragon.github.io/blog/infra/takeover/cloud-no-iac/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/takeover/cloud-no-iac/</guid><description>&lt;p>雲端資源存在且正在服務 production 流量，但沒有人能回答「我們有什麼、為什麼這樣設定、改了會影響什麼」。Console 裡有幾十個資源，有些名稱是 &lt;code>test-final-v2&lt;/code>，有些沒有名稱，security group 規則不知道哪條還在用，IAM user 清單裡有幾個已離職的人。這是接手全手動雲端環境的典型起點。&lt;/p>
&lt;p>接管的操作順序是：先拍下現況（盤點）、再理解結構（依賴）、再收斂風險（credential、備份）、再建立紀律（變更紀錄）、最後才考慮 IaC 導入。每一步都在不改動 production 的前提下進行。&lt;/p>
&lt;h2 id="資源盤點拍下雲端現況">資源盤點：拍下雲端現況&lt;/h2>
&lt;p>盤點的目標是把「雲端上有什麼」轉成一份可版本控制的清單。這份清單是後續所有操作的事實基礎 — 沒有清單就無法判斷哪些資源重要、哪些可以回收、哪些的設定有風險。&lt;/p>
&lt;p>盤點的工具依環境類型不同：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>VM 為主（EC2 / GCE）&lt;/strong> → 先跑 &lt;a href="#vm-%e5%b1%a4%e7%b4%9a%e7%9a%84%e5%bf%ab%e7%85%a7">VM 快照與系統清單&lt;/a>，再跑 &lt;a href="#%e7%94%a8-cli-%e6%8b%89%e6%b8%85%e5%96%ae">CLI 資源盤點&lt;/a>&lt;/li>
&lt;li>&lt;strong>Managed service 為主（RDS / Lambda / S3）&lt;/strong> → 直接跑 &lt;a href="#%e7%94%a8-cli-%e6%8b%89%e6%b8%85%e5%96%ae">CLI 資源盤點&lt;/a>&lt;/li>
&lt;li>&lt;strong>混合（VM + managed）&lt;/strong> → 兩個都跑：先 VM 快照（拍下機器狀態），再 CLI 盤點（拍下所有雲端資源）&lt;/li>
&lt;/ul>
&lt;h3 id="用-cli-拉清單">用 CLI 拉清單&lt;/h3>
&lt;p>盤點有三層工具可用，從粗到細：&lt;/p>
&lt;p>&lt;strong>全貌掃描&lt;/strong>：先用跨服務工具拿到「到底有多少資源」的量級感。AWS Resource Explorer 在 Console 開啟後可以用搜尋語法跨 region、跨 service 查資源（例如搜 &lt;code>resourcetype:ec2:instance&lt;/code> 列出所有 EC2）。Steampipe 是開源的 SQL 介面雲端查詢工具，用 &lt;code>select * from aws_ec2_instance&lt;/code> 這類語法查詢，對習慣 SQL 的人比 CLI flag 直覺。兩者都能在幾分鐘內拿到環境的全貌。&lt;/p>
&lt;p>&lt;strong>Tag 層掃描&lt;/strong>：AWS Resource Groups Tagging API 能跨服務撈出所有被標記的資源，但會漏掉沒有 tag 的 — 而接手環境裡沒 tag 的資源往往是風險最高的（沒人認領、不敢動）。&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">aws resourcegroupstaggingapi get-resources &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> --output json &amp;gt; inventory/tagged-resources.json&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>Per-service 細節&lt;/strong>：全貌掃描只告訴你資源存在，細節（備份設定、SG 規則、IAM policy）要用 per-service describe 拉。以下是接手時最該優先盤點的四類：&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"># EC2：哪些機器在跑、什麼規格、在哪個 subnet&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">aws ec2 describe-instances &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> --query &lt;span class="s1">&amp;#39;Reservations[].Instances[].[InstanceId,InstanceType,State.Name,SubnetId,SecurityGroups[].GroupId,Tags]&amp;#39;&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> --output json &amp;gt; inventory/ec2.json
&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"># RDS：資料庫的備份設定、刪除保護、Multi-AZ&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">aws rds describe-db-instances &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> --query &lt;span class="s1">&amp;#39;DBInstances[].[DBInstanceIdentifier,Engine,DBInstanceClass,MultiAZ,BackupRetentionPeriod,DeletionProtection]&amp;#39;&lt;/span> &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> --output json &amp;gt; inventory/rds.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"># Security Group：哪些規則對外開放&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">aws ec2 describe-security-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> --query &lt;span class="s1">&amp;#39;SecurityGroups[].[GroupId,GroupName,IpPermissions]&amp;#39;&lt;/span> &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> --output json &amp;gt; inventory/security-groups.json
&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"># S3：哪些 bucket、versioning 是否開啟&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl">&lt;span class="k">for&lt;/span> bucket in &lt;span class="k">$(&lt;/span>aws s3api list-buckets --query &lt;span class="s1">&amp;#39;Buckets[].Name&amp;#39;&lt;/span> --output text&lt;span class="k">)&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">do&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl"> &lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$bucket&lt;/span>&lt;span class="s2">: &lt;/span>&lt;span class="k">$(&lt;/span>aws s3api get-bucket-versioning --bucket &lt;span class="nv">$bucket&lt;/span> --query &lt;span class="s1">&amp;#39;Status&amp;#39;&lt;/span> --output text&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl">&lt;span class="k">done&lt;/span> &amp;gt; inventory/s3-versioning.txt&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>把所有輸出存進一個 Git repo 的 &lt;code>inventory/&lt;/code> 目錄。這份快照的價值在於：一週後再跑一次比對差異，就能看出環境在背景長出了什麼新資源。&lt;/p>
&lt;h3 id="優先查三件事">優先查三件事&lt;/h3>
&lt;p>盤點不需要一次做完所有服務，但三件事要第一天就查：&lt;/p>
&lt;p>&lt;strong>對外暴露面&lt;/strong>：security group 裡有沒有 &lt;code>0.0.0.0/0&lt;/code> 入站規則指向非 HTTP/HTTPS 的 port（22、3306、5432、6379）。手動逐條查很慢 — 用安全掃描工具一次跑完更可靠。Prowler 是開源的 AWS 安全掃描工具，一次執行就能產出「哪些 SG 對外開放、哪些 S3 public、哪些 IAM 過寬」的分類報告：&lt;/p></description><content:encoded><![CDATA[<p>雲端資源存在且正在服務 production 流量，但沒有人能回答「我們有什麼、為什麼這樣設定、改了會影響什麼」。Console 裡有幾十個資源，有些名稱是 <code>test-final-v2</code>，有些沒有名稱，security group 規則不知道哪條還在用，IAM user 清單裡有幾個已離職的人。這是接手全手動雲端環境的典型起點。</p>
<p>接管的操作順序是：先拍下現況（盤點）、再理解結構（依賴）、再收斂風險（credential、備份）、再建立紀律（變更紀錄）、最後才考慮 IaC 導入。每一步都在不改動 production 的前提下進行。</p>
<h2 id="資源盤點拍下雲端現況">資源盤點：拍下雲端現況</h2>
<p>盤點的目標是把「雲端上有什麼」轉成一份可版本控制的清單。這份清單是後續所有操作的事實基礎 — 沒有清單就無法判斷哪些資源重要、哪些可以回收、哪些的設定有風險。</p>
<p>盤點的工具依環境類型不同：</p>
<ul>
<li><strong>VM 為主（EC2 / GCE）</strong> → 先跑 <a href="#vm-%e5%b1%a4%e7%b4%9a%e7%9a%84%e5%bf%ab%e7%85%a7">VM 快照與系統清單</a>，再跑 <a href="#%e7%94%a8-cli-%e6%8b%89%e6%b8%85%e5%96%ae">CLI 資源盤點</a></li>
<li><strong>Managed service 為主（RDS / Lambda / S3）</strong> → 直接跑 <a href="#%e7%94%a8-cli-%e6%8b%89%e6%b8%85%e5%96%ae">CLI 資源盤點</a></li>
<li><strong>混合（VM + managed）</strong> → 兩個都跑：先 VM 快照（拍下機器狀態），再 CLI 盤點（拍下所有雲端資源）</li>
</ul>
<h3 id="用-cli-拉清單">用 CLI 拉清單</h3>
<p>盤點有三層工具可用，從粗到細：</p>
<p><strong>全貌掃描</strong>：先用跨服務工具拿到「到底有多少資源」的量級感。AWS Resource Explorer 在 Console 開啟後可以用搜尋語法跨 region、跨 service 查資源（例如搜 <code>resourcetype:ec2:instance</code> 列出所有 EC2）。Steampipe 是開源的 SQL 介面雲端查詢工具，用 <code>select * from aws_ec2_instance</code> 這類語法查詢，對習慣 SQL 的人比 CLI flag 直覺。兩者都能在幾分鐘內拿到環境的全貌。</p>
<p><strong>Tag 層掃描</strong>：AWS Resource Groups Tagging API 能跨服務撈出所有被標記的資源，但會漏掉沒有 tag 的 — 而接手環境裡沒 tag 的資源往往是風險最高的（沒人認領、不敢動）。</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 resourcegroupstaggingapi get-resources <span class="se">\
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="se"></span>  --output json &gt; inventory/tagged-resources.json</span></span></code></pre></div><p><strong>Per-service 細節</strong>：全貌掃描只告訴你資源存在，細節（備份設定、SG 規則、IAM policy）要用 per-service describe 拉。以下是接手時最該優先盤點的四類：</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"># EC2：哪些機器在跑、什麼規格、在哪個 subnet</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">aws ec2 describe-instances <span class="se">\
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="se"></span>  --query <span class="s1">&#39;Reservations[].Instances[].[InstanceId,InstanceType,State.Name,SubnetId,SecurityGroups[].GroupId,Tags]&#39;</span> <span class="se">\
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="se"></span>  --output json &gt; inventory/ec2.json
</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"># RDS：資料庫的備份設定、刪除保護、Multi-AZ</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">aws rds describe-db-instances <span class="se">\
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="se"></span>  --query <span class="s1">&#39;DBInstances[].[DBInstanceIdentifier,Engine,DBInstanceClass,MultiAZ,BackupRetentionPeriod,DeletionProtection]&#39;</span> <span class="se">\
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="se"></span>  --output json &gt; inventory/rds.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"># Security Group：哪些規則對外開放</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">aws ec2 describe-security-groups <span class="se">\
</span></span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="se"></span>  --query <span class="s1">&#39;SecurityGroups[].[GroupId,GroupName,IpPermissions]&#39;</span> <span class="se">\
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="se"></span>  --output json &gt; inventory/security-groups.json
</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"># S3：哪些 bucket、versioning 是否開啟</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="k">for</span> bucket in <span class="k">$(</span>aws s3api list-buckets --query <span class="s1">&#39;Buckets[].Name&#39;</span> --output text<span class="k">)</span><span class="p">;</span> <span class="k">do</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">  <span class="nb">echo</span> <span class="s2">&#34;</span><span class="nv">$bucket</span><span class="s2">: </span><span class="k">$(</span>aws s3api get-bucket-versioning --bucket <span class="nv">$bucket</span> --query <span class="s1">&#39;Status&#39;</span> --output text<span class="k">)</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="k">done</span> &gt; inventory/s3-versioning.txt</span></span></code></pre></div><p>把所有輸出存進一個 Git repo 的 <code>inventory/</code> 目錄。這份快照的價值在於：一週後再跑一次比對差異，就能看出環境在背景長出了什麼新資源。</p>
<h3 id="優先查三件事">優先查三件事</h3>
<p>盤點不需要一次做完所有服務，但三件事要第一天就查：</p>
<p><strong>對外暴露面</strong>：security group 裡有沒有 <code>0.0.0.0/0</code> 入站規則指向非 HTTP/HTTPS 的 port（22、3306、5432、6379）。手動逐條查很慢 — 用安全掃描工具一次跑完更可靠。Prowler 是開源的 AWS 安全掃描工具，一次執行就能產出「哪些 SG 對外開放、哪些 S3 public、哪些 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"># 安裝後執行，針對最相關的服務掃描</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">prowler aws --services ec2 iam s3 rds -M json-ocsf -o inventory/
</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"># 如果只想快速查 SG 暴露面，用 CLI：</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">aws ec2 describe-security-groups <span class="se">\
</span></span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="se"></span>  --query <span class="s1">&#39;SecurityGroups[].IpPermissions[?contains(IpRanges[].CidrIp, `0.0.0.0/0`)]&#39;</span> <span class="se">\
</span></span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="se"></span>  --output json <span class="p">|</span> jq <span class="s1">&#39;[.[][] | select(.FromPort != 80 and .FromPort != 443)]&#39;</span></span></span></code></pre></div><p>ScoutSuite 是類似工具、支援多雲（AWS / GCP / Azure）。AWS Trusted Advisor 的免費 tier 也有基本安全檢查（S3 public access、SG 開放埠），但覆蓋面比 Prowler 窄。接手時三者選一跑一次，比手動翻 Console 快且不會漏。</p>
<p><strong>備份狀態</strong>：RDS 的 <code>BackupRetentionPeriod</code> 是不是 0（代表沒有自動備份）。S3 的 versioning 是不是關的。如果是，這是接手後第一個要改的設定 — 改備份設定不影響服務運作，但沒有備份時任何資料操作失誤都不可逆。</p>
<p><strong>誰最近在動環境</strong>：CloudTrail 記錄了所有 API 呼叫。查最近 30 天的變更事件，能看出哪些資源被頻繁修改、被誰修改。這比逐一問前團隊成員可靠——CloudTrail 不會漏記。</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 cloudtrail lookup-events <span class="se">\
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="se"></span>  --lookup-attributes <span class="nv">AttributeKey</span><span class="o">=</span>ReadOnly,AttributeValue<span class="o">=</span><span class="nb">false</span> <span class="se">\
</span></span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="se"></span>  --start-time <span class="k">$(</span>date -v-30d +%Y-%m-%dT%H:%M:%S<span class="k">)</span> <span class="se">\
</span></span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="se"></span>  --max-items <span class="m">50</span> <span class="se">\
</span></span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="se"></span>  --query <span class="s1">&#39;Events[].[EventTime,Username,EventName,Resources[0].ResourceName]&#39;</span> <span class="se">\
</span></span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="se"></span>  --output table</span></span></code></pre></div><h3 id="vm-層級的快照">VM 層級的快照</h3>
<p>如果接手的環境包含 EC2 或 GCE 等 VM，在做任何改動之前先對每台 VM 建一個 AMI（AWS）或 machine image（GCP）。這是最粗粒度但最完整的「拍照」——整台機器的 OS、安裝的軟體、設定檔、磁碟內容全部打包成一個可重建的映像。</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"># AWS: 對 EC2 建 AMI（--no-reboot 避免服務中斷）</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">aws ec2 create-image <span class="se">\
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="se"></span>  --instance-id i-0abc123 <span class="se">\
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="se"></span>  --name <span class="s2">&#34;takeover-baseline-</span><span class="k">$(</span>date +%Y%m%d<span class="k">)</span><span class="s2">&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="se"></span>  --no-reboot
</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"># 確認 AMI 建立完成</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">aws ec2 describe-images <span class="se">\
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="se"></span>  --owners self <span class="se">\
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="se"></span>  --filters <span class="s2">&#34;Name=name,Values=takeover-baseline-*&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="se"></span>  --query <span class="s1">&#39;Images[].[ImageId,Name,State]&#39;</span> <span class="se">\
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="se"></span>  --output table</span></span></code></pre></div><p><code>--no-reboot</code> 讓快照過程中服務不中斷，代價是檔案系統快照的一致性不如有 reboot 的版本（記憶體中的寫入可能還沒 flush 到磁碟），但對接手基線已經足夠。AMI 的費用是底層 EBS 快照的儲存費用（按 GB 計費、差異儲存），作為接手保險措施這筆成本值得。</p>
<p>除了 VM 快照，有 SSH 存取時也要拍 VM 內部的軟體環境——AMI 可以還原整台機器，但看不到「裡面裝了什麼、跑了什麼」的摘要：</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"># 作業系統與版本</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">cat /etc/os-release
</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"># 已安裝的套件清單</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">dpkg -l &gt; ~/takeover/packages-<span class="k">$(</span>date +%Y%m%d<span class="k">)</span>.txt   <span class="c1"># Debian/Ubuntu</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">rpm -qa &gt; ~/takeover/packages-<span class="k">$(</span>date +%Y%m%d<span class="k">)</span>.txt    <span class="c1"># RHEL/CentOS/Amazon Linux</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"># 執行中的服務</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">systemctl list-units --type<span class="o">=</span>service --state<span class="o">=</span>running &gt; ~/takeover/services.txt
</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"># 所有使用者的 cron jobs</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="k">for</span> user in <span class="k">$(</span>cut -f1 -d: /etc/passwd<span class="k">)</span><span class="p">;</span> <span class="k">do</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">  <span class="nb">echo</span> <span class="s2">&#34;=== </span><span class="nv">$user</span><span class="s2"> ===&#34;</span> &gt;&gt; ~/takeover/crontabs.txt
</span></span><span class="line"><span class="ln">14</span><span class="cl">  crontab -u <span class="s2">&#34;</span><span class="nv">$user</span><span class="s2">&#34;</span> -l 2&gt;/dev/null &gt;&gt; ~/takeover/crontabs.txt
</span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="k">done</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">
</span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="c1"># 網路監聽的 port（哪個 process 在聽哪個 port）</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">ss -tlnp &gt; ~/takeover/listening-ports.txt</span></span></code></pre></div><p>把這些輸出存進盤點 repo，跟 CLI 資源盤點（describe 指令的輸出）放在一起。<code>listening-ports.txt</code> 跟 security group 規則對照，可以看出「哪些 port 有服務在聽但 SG 沒開」（可能是內部服務）和「哪些 port SG 開了但沒有服務在聽」（可能是殘留規則）。</p>
<h2 id="依賴關係推導">依賴關係推導</h2>
<p>盤點回答「有什麼」，依賴推導回答「改一個會連帶影響什麼」。手動環境沒有 Terraform 的依賴圖可以看，需要從資源的引用關係反推。</p>
<h3 id="從-security-group-開始">從 security group 開始</h3>
<p>Security group 是依賴推導的最佳起點，因為它的引用關係最密集 — 幾乎每個資源都掛著至少一個 SG，而 SG 之間可以互相引用（app SG 的入站來源是 LB SG、DB SG 的入站來源是 app SG）。</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"># 列出每個 SG 被哪些 ENI（網卡）使用</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">aws ec2 describe-network-interfaces <span class="se">\
</span></span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="se"></span>  --query <span class="s1">&#39;NetworkInterfaces[].[NetworkInterfaceId,Description,Groups[].GroupId]&#39;</span> <span class="se">\
</span></span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="se"></span>  --output json &gt; inventory/sg-usage.json</span></span></code></pre></div><p>AWS Console 的 VPC 頁面有 Resource Map 功能，可以視覺化 subnet → instance → SG 的對應關係，接手時第一次瀏覽依賴用它比 CLI 直覺。要產出可存檔的依賴圖，draw.io（有 AWS icon set）或 Lucidchart 都能畫，重點是圖要存進 repo、不是畫完就丟。</p>
<p>如果後續打算導入 Terraform，Former2 可以掃描現有 AWS 資源、自動產出 Terraform / CloudFormation / CDK 程式碼。產出的程式碼不會完美（屬性常漏、命名要改），但作為反推依賴關係的起點比從零寫快。Inframap 則是從 Terraform state 產出依賴關係圖（在 import 階段才用得到）。</p>
<p>從 SG 的引用鏈可以畫出一張粗略的依賴圖：</p>
<table>
  <thead>
      <tr>
          <th>層次</th>
          <th>資源</th>
          <th>入站來自</th>
          <th>出站到</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>入口</td>
          <td>ALB</td>
          <td>0.0.0.0/0:443</td>
          <td>app SG</td>
      </tr>
      <tr>
          <td>應用</td>
          <td>EC2 / ECS</td>
          <td>ALB SG</td>
          <td>DB SG、外部 API</td>
      </tr>
      <tr>
          <td>資料</td>
          <td>RDS</td>
          <td>app SG:5432</td>
          <td>—</td>
      </tr>
  </tbody>
</table>
<p>這張圖不需要精確到每個 port — 它的用途是在改動任何資源前，快速判斷影響範圍。例如要改 app SG 的規則時，先查它被哪些 EC2 和 ECS 引用、它的入站來源 ALB SG 是否受影響。</p>
<h3 id="其他依賴面向">其他依賴面向</h3>
<p>除了 SG，以下幾個引用關係也要記錄：</p>
<ul>
<li><strong>EC2 → IAM role</strong>：instance profile 決定這台機器能存取什麼（S3 bucket、Secrets Manager、其他 AWS 服務）</li>
<li><strong>RDS → subnet group</strong>：決定資料庫在哪些 subnet 裡，改 VPC 或 subnet 時會受影響</li>
<li><strong>ALB → target group → EC2/ECS</strong>：流量路徑，改 target group 的 health check 或移除成員會影響服務可用性</li>
<li><strong>Lambda → VPC 設定</strong>：如果 Lambda 被放進 VPC，它的出站走 NAT，改 NAT 或 route table 會影響它</li>
<li><strong>Route 53 → ALB/EC2</strong>：DNS 指向哪個資源，改資源 IP 或 ALB 時要同步更新</li>
</ul>
<h2 id="credential-盤點與收斂">credential 盤點與收斂</h2>
<p>接手環境時，credential 是風險最高的一類 — 前團隊建立的 IAM user 和 access key 可能還在活躍狀態，而那些人已經不在團隊裡了。</p>
<p>接手後第一件事是用 aws-vault 管理自己的 credential。aws-vault 把 AWS access key 存在 OS keychain（macOS Keychain / Windows Credential Manager），而非明文放在 <code>~/.aws/credentials</code>。執行 AWS 指令時由 aws-vault 注入臨時 session，本地磁碟上不留長期 key 的明文。不要沿用前人留下的 AWS CLI profile — 那些 profile 的權限範圍和用途都不確定。</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"># 安裝後設定新的 profile</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">aws-vault add takeover-admin
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="c1"># 用臨時 session 執行指令</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">aws-vault <span class="nb">exec</span> takeover-admin -- aws sts get-caller-identity</span></span></code></pre></div><h3 id="產出-credential-報告">產出 credential 報告</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">aws iam generate-credential-report
</span></span><span class="line"><span class="ln">2</span><span class="cl">aws iam get-credential-report <span class="se">\
</span></span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="se"></span>  --query <span class="s1">&#39;Content&#39;</span> --output text <span class="p">|</span> base64 -d &gt; inventory/credential-report.csv</span></span></code></pre></div><p>這份 CSV 列出所有 IAM user、每把 access key 的建立時間、上次使用時間、MFA 是否啟用。從中篩出三類需要處理的：</p>
<table>
  <thead>
      <tr>
          <th>類別</th>
          <th>判斷方式</th>
          <th>處理</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>已離職人員的 key</td>
          <td>user 名稱對照離職清單</td>
          <td>停用 key → 觀察 7 天無異常 → 刪除 user</td>
      </tr>
      <tr>
          <td>超過 90 天未使用的 key</td>
          <td><code>access_key_last_used</code> 超過 90 天</td>
          <td>停用 → 觀察是否有服務中斷 → 確認無影響後刪除</td>
      </tr>
      <tr>
          <td>有 admin 權限的 key</td>
          <td>policy 含 <code>AdministratorAccess</code> 或 <code>*:*</code></td>
          <td>降權到實際需要的最小權限</td>
      </tr>
  </tbody>
</table>
<p>停用（deactivate）而非直接刪除是關鍵 — 停用後如果某個自動化腳本依賴這把 key 會立刻報錯，這時候可以快速重新啟用；直接刪除就回不去了。觀察期設 7 天，涵蓋一個完整的業務週期（含週末的 cron job）。</p>
<h3 id="檢查-key-散落的位置">檢查 key 散落的位置</h3>
<p>Access key 可能被寫在不只一個地方：</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"># EC2 user data 裡是否有 hardcode 的 key</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">aws ec2 describe-instance-attribute <span class="se">\
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="se"></span>  --instance-id i-xxx --attribute userData <span class="se">\
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="se"></span>  --query <span class="s1">&#39;UserData.Value&#39;</span> --output text <span class="p">|</span> base64 -d <span class="p">|</span> grep -i <span class="s2">&#34;aws_access_key\|aws_secret&#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 class="c1"># Lambda 環境變數</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">aws lambda list-functions --query <span class="s1">&#39;Functions[].FunctionName&#39;</span> --output text <span class="p">|</span> <span class="se">\
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="se"></span>  xargs -I<span class="o">{}</span> aws lambda get-function-configuration --function-name <span class="o">{}</span> <span class="se">\
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="se"></span>  --query <span class="s1">&#39;Environment.Variables&#39;</span> --output json <span class="p">|</span> grep -i <span class="s2">&#34;key\|secret\|password&#34;</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"># SSM Parameter Store</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">aws ssm describe-parameters --query <span class="s1">&#39;Parameters[].Name&#39;</span> --output text</span></span></code></pre></div><p>找到 hardcode 的 key 後，替換路徑是改用 IAM role（EC2 用 instance profile、Lambda 用 execution role）。替換前先確認 role 的 policy 涵蓋這把 key 原本在做的操作。</p>
<h2 id="備份驗證">備份驗證</h2>
<p>盤點出的每個 stateful 資源（RDS、S3、EBS）都要確認備份狀態。接手環境時不能假設「前團隊應該有設定備份」— 要親自驗證。</p>
<h3 id="rds-備份">RDS 備份</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"># 檢查每個 RDS instance 的備份設定</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">aws rds describe-db-instances <span class="se">\
</span></span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="se"></span>  --query <span class="s1">&#39;DBInstances[].[DBInstanceIdentifier,BackupRetentionPeriod,LatestRestorableTime,DeletionProtection]&#39;</span> <span class="se">\
</span></span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="se"></span>  --output table</span></span></code></pre></div><p><code>BackupRetentionPeriod</code> 為 0 代表沒有自動備份 — 立刻改成至少 7 天。<code>DeletionProtection</code> 為 false 代表一個誤操作就能刪掉資料庫 — 立刻開啟。這兩項設定的修改不需要重啟、不影響服務。</p>
<p>備份存在不等於備份可用。接手後的第一週內，從最近的 snapshot 還原一台測試 RDS、連進去確認資料完整。這個步驟的成本是一台 RDS 跑幾小時的費用，換到的是「備份確定能用」的確認 — 等到要用備份的時候才發現不能還原，代價是另一個量級。</p>
<h3 id="s3-versioning">S3 versioning</h3>
<p>沒有開 versioning 的 bucket，物件被覆寫或刪除後不可回復。對承載業務資料的 bucket（上傳的檔案、匯出的報表、設定檔），開啟 versioning：</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 s3api put-bucket-versioning <span class="se">\
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="se"></span>  --bucket my-business-data <span class="se">\
</span></span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="se"></span>  --versioning-configuration <span class="nv">Status</span><span class="o">=</span>Enabled</span></span></code></pre></div><p>開啟 versioning 不影響既有物件，但會讓後續的每次覆寫都保留舊版本。儲存成本會因為保留歷史版本而增加 — 配一條 lifecycle rule 設定 noncurrent version 的過期天數來控制。</p>
<h2 id="建立變更紀律">建立變更紀律</h2>
<p>盤點、依賴推導、credential 收斂做完後，環境的現況已經有一份可查的記錄。下一步是確保從現在開始的每一次變更都留下痕跡。</p>
<h3 id="變更日誌">變更日誌</h3>
<p>在 inventory repo 裡建一份 <code>CHANGELOG.md</code>，每次改動 production 就追加一筆：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-markdown" data-lang="markdown"><span class="line"><span class="ln">1</span><span class="cl"><span class="gu">## 2026-06-26
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="gu"></span>
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="k">-</span> **操作者**：alice
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="k">-</span> **資源**：rds/payments-prod
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="k">-</span> **變更**：BackupRetentionPeriod 0 → 14, DeletionProtection false → true
</span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="k">-</span> **原因**：接手盤點發現備份未開啟
</span></span><span class="line"><span class="ln">7</span><span class="cl">- <span class="gs">**回退方式**</span>：BackupRetentionPeriod 改回 0（不建議）</span></span></code></pre></div><h3 id="cloudtrail-確認">CloudTrail 確認</h3>
<p>確認 CloudTrail 正在記錄 management events。如果沒有 trail 存在，建一個指向 S3 bucket 的 trail — 這是事後追溯「誰動了什麼」的最後防線。</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 cloudtrail describe-trails --query <span class="s1">&#39;trailList[].{Name:Name,S3:S3BucketName,IsLogging:IsLogging}&#39;</span></span></span></code></pre></div><h3 id="開始標-tag">開始標 tag</h3>
<p>盤點過程中辨識出的每個資源，標上 <code>env</code>、<code>owner</code>、<code>service</code> 三個 tag。接手階段的 <code>owner</code> 通常標「待確認」或新接手的團隊名稱。tag 的價值在於讓後續的盤點和清理可以用查詢系統性地進行 — 沒有 tag 的資源無法被 filter 找到。</p>
<h2 id="往-iac-的銜接">往 IaC 的銜接</h2>
<p>盤點和紀律建立完成後，環境已經從「不知道有什麼」推進到「知道有什麼、知道誰在動、改了有紀錄」。這個狀態對應<a href="/blog/infra/00-infra-mindset/" data-link-title="模組零：infra 是什麼，為什麼 day 1 就要鋪地基" data-link-desc="基礎設施的責任邊界、成熟度階梯，以及地基為什麼總在環境爆炸時才被看見">成熟度階梯</a>的第零階到第一階之間。</p>
<h3 id="成本現況">成本現況</h3>
<p>接手環境通常伴隨「這個月帳單多少」的問題。AWS Cost Explorer（免費）能看過去幾個月的花費分布，按服務類型、帳號、tag 維度拆。接手時先拉一次 Cost Explorer 的月度趨勢，看有沒有異常成長或不預期的高額服務。後續導入 IaC 後，Infracost 可以在 <code>terraform plan</code> 階段預估變更的成本影響（例如「升 RDS 規格會多花多少」），讓成本決策在 apply 之前就被看見。</p>
<p>往 IaC 的銜接不需要一次做完。按穩定度和改動風險排序：</p>
<table>
  <thead>
      <tr>
          <th>優先級</th>
          <th>資源類型</th>
          <th>理由</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>先做</td>
          <td>VPC、subnet、route table</td>
          <td>形狀穩定、幾乎不會改、import 風險低</td>
      </tr>
      <tr>
          <td>次做</td>
          <td>security group</td>
          <td>規則明確、import 後 plan 容易驗證</td>
      </tr>
      <tr>
          <td>後做</td>
          <td>RDS、EC2、ALB</td>
          <td>stateful 或與部署耦合、import 風險較高</td>
      </tr>
      <tr>
          <td>最後</td>
          <td>Lambda、API Gateway</td>
          <td>通常跟應用程式碼耦合、import 後維護邊界需要釐清</td>
      </tr>
  </tbody>
</table>
<p>每批 import 的操作流程是：<code>terraform import</code> → <code>terraform plan</code> 確認零變更 → 寫 HCL 補齊差異 → 再跑 <code>plan</code> 直到零變更。具體的 import 步驟和工具選型在<a href="/blog/infra/01-minimal-iac/" data-link-title="模組一：最小可行 IaC — state 地基與 Console 唯讀鐵律" data-link-desc="Terraform / OpenTofu 選型、remote state 與 lock，以及「Console 只能看不能改」鐵律">模組一：最小可行 IaC</a>。</p>
<p>時程參考：10-20 個資源的環境，完成盤點 + credential 收斂 + 備份驗證約需 3-5 天；往 IaC 的 import 約需 1-2 週。兩者可以平行進行但建議先完成盤點 — 沒有完整的資源清單就開始 import，容易漏掉關鍵的依賴關係。</p>
<h2 id="跨分類引用">跨分類引用</h2>
<ul>
<li>→ <a href="/blog/infra/takeover/partial-iac-no-docs/" data-link-title="有半套 IaC 但文件缺失的環境接管" data-link-desc="IaC 覆蓋不完整、部分資源在 state 外、文件缺失的環境怎麼盤點差距、修復 state 健康、收斂 drift 並重建文件">有半套 IaC 但文件缺失的環境接管</a>：如果盤點過程中發現環境裡已有部分 Terraform code</li>
<li>→ <a href="/blog/infra/before-infra/" data-link-title="模組負一：還沒有 infra 的環境怎麼盡量做好" data-link-desc="手動點起家的環境怎麼守底線、降低未來納管成本、辨識何時該開始導入 IaC — 給還沒有能力上 IaC 的真實起點">模組負一：還沒有 infra 的環境</a>：盤點完成後的操作紀律對齊</li>
<li>→ <a href="/blog/infra/00-infra-mindset/" data-link-title="模組零：infra 是什麼，為什麼 day 1 就要鋪地基" data-link-desc="基礎設施的責任邊界、成熟度階梯，以及地基為什麼總在環境爆炸時才被看見">模組零：infra 是什麼</a>：成熟度階梯作為接手後現況評估的座標</li>
<li>→ <a href="/blog/infra/01-minimal-iac/" data-link-title="模組一：最小可行 IaC — state 地基與 Console 唯讀鐵律" data-link-desc="Terraform / OpenTofu 選型、remote state 與 lock，以及「Console 只能看不能改」鐵律">模組一：最小可行 IaC</a>：盤點完成後的第一步 IaC 導入</li>
<li>→ <a href="/blog/infra/02-identity-credentials/" data-link-title="模組二：身分與憑證地基 — IAM 與 OIDC" data-link-desc="IAM role / policy 設計、最小權限，以及用 OIDC 短期憑證取代長期 access key">模組二：身分與憑證</a>：credential 收斂的完整設計</li>
<li>→ <a href="/blog/infra/02-identity-credentials/team-access-management/" data-link-title="團隊權限分級與存取管理" data-link-desc="用 admin / operator / viewer 三級劃分團隊成員的雲端操作權限，設計臨時提權流程、定期 access review 節奏，以及 contractor 與外部 vendor 的存取邊界">團隊權限分級與存取管理</a>：接手後重新建立權限分級</li>
</ul>
]]></content:encoded></item><item><title>0.19 雲端服務對照地圖（AWS / GCP / Azure）</title><link>https://tarrragon.github.io/blog/backend/00-service-selection/cloud-vendor-capability-mapping/</link><pubDate>Wed, 27 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/00-service-selection/cloud-vendor-capability-mapping/</guid><description>&lt;p>面對「我該選 AWS 還是 GCP？」這類問題、第一步是把後端能力分類對應到三家雲廠商的具體服務名稱、技術細節放後面。本章提供這份對照地圖、同時警告一件事：AWS、GCP、Azure 在大部分能力上都有對應產品，但「對應」不等於「等價」— 同樣是 managed SQL、AWS RDS、GCP Cloud SQL、Azure SQL 在備份頻率、replica 行為、failover 時間、跨區複製成本上都有差異。對照表是入口、不是決策本身。&lt;/p>
&lt;h2 id="為什麼需要這張對照地圖">為什麼需要這張對照地圖&lt;/h2>
&lt;p>兩種使用情境會需要這張表。第一是初次選型時，讀者已經選定主要雲廠商，要對照各能力分類找出 vendor 名稱。第二是跨雲遷移評估，讀者要對照源端跟目標端的能力 gap。沒有這張表，每次都要重新查文件、容易漏掉某個能力。&lt;/p>
&lt;p>但這張表不能取代深入評估。每個 vendor 都有不在表格內的差異，例如配額、區域可用性、跨服務整合、計價模型。表格是路由起點，後續判讀要進到該 vendor 的 deep article。&lt;/p>
&lt;h2 id="能力--雲廠商對照表">能力 × 雲廠商對照表&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>能力分類&lt;/th>
 &lt;th>AWS&lt;/th>
 &lt;th>GCP&lt;/th>
 &lt;th>Azure&lt;/th>
 &lt;th>對照判讀重點&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>關聯式 DB（OLTP）&lt;/td>
 &lt;td>RDS / Aurora&lt;/td>
 &lt;td>Cloud SQL / AlloyDB&lt;/td>
 &lt;td>Azure SQL / Azure Database for Postgres&lt;/td>
 &lt;td>failover 時間、跨區 replica、IOPS 計價&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>全球分散式 DB&lt;/td>
 &lt;td>Aurora DSQL / DynamoDB Global Tables&lt;/td>
 &lt;td>Spanner&lt;/td>
 &lt;td>Cosmos DB&lt;/td>
 &lt;td>一致性模型、寫入延遲、計價單位&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>KV / Document DB&lt;/td>
 &lt;td>DynamoDB&lt;/td>
 &lt;td>Firestore / Bigtable&lt;/td>
 &lt;td>Cosmos DB&lt;/td>
 &lt;td>partition key 設計、capacity mode、跨區一致性&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>快取&lt;/td>
 &lt;td>ElastiCache（Redis / Memcached）&lt;/td>
 &lt;td>Memorystore&lt;/td>
 &lt;td>Azure Cache for Redis&lt;/td>
 &lt;td>跨區複製、persistence、容量上限&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>訊息佇列&lt;/td>
 &lt;td>SQS / SNS / Kinesis&lt;/td>
 &lt;td>Pub/Sub&lt;/td>
 &lt;td>Service Bus / Event Hubs&lt;/td>
 &lt;td>delivery guarantee、ordering、retention 期&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>事件流（Kafka）&lt;/td>
 &lt;td>MSK / Kinesis&lt;/td>
 &lt;td>Pub/Sub&lt;/td>
 &lt;td>Event Hubs (Kafka compatibility)&lt;/td>
 &lt;td>Kafka 相容性、partition 數量、跨區複製&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>物件儲存&lt;/td>
 &lt;td>S3&lt;/td>
 &lt;td>Cloud Storage&lt;/td>
 &lt;td>Blob Storage&lt;/td>
 &lt;td>一致性模型、跨區複製、lifecycle policy&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>容器執行平台&lt;/td>
 &lt;td>ECS / EKS / Fargate&lt;/td>
 &lt;td>GKE / Cloud Run&lt;/td>
 &lt;td>AKS / Container Apps&lt;/td>
 &lt;td>managed 程度、cold start、計價單位&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Serverless 函式&lt;/td>
 &lt;td>Lambda&lt;/td>
 &lt;td>Cloud Functions / Cloud Run&lt;/td>
 &lt;td>Azure Functions&lt;/td>
 &lt;td>最大執行時間、cold start、整合方式&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Load Balancer&lt;/td>
 &lt;td>ELB（ALB / NLB / CLB）&lt;/td>
 &lt;td>Cloud Load Balancing&lt;/td>
 &lt;td>Azure Load Balancer / App Gateway&lt;/td>
 &lt;td>L4 vs L7、跨區 LB、TLS termination&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>API Gateway&lt;/td>
 &lt;td>API Gateway&lt;/td>
 &lt;td>API Gateway / Apigee&lt;/td>
 &lt;td>API Management&lt;/td>
 &lt;td>rate limit、auth 整合、計價&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>CDN / 邊緣&lt;/td>
 &lt;td>CloudFront&lt;/td>
 &lt;td>Cloud CDN / Media CDN&lt;/td>
 &lt;td>Azure Front Door / CDN&lt;/td>
 &lt;td>edge POP 數、purge API、cache key 彈性&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>監控&lt;/td>
 &lt;td>CloudWatch&lt;/td>
 &lt;td>Cloud Monitoring&lt;/td>
 &lt;td>Azure Monitor&lt;/td>
 &lt;td>metric retention、dashboard 表達力、整合範圍&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Log 聚合&lt;/td>
 &lt;td>CloudWatch Logs&lt;/td>
 &lt;td>Cloud Logging&lt;/td>
 &lt;td>Log Analytics&lt;/td>
 &lt;td>ingestion 成本、query 語言、retention&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Tracing&lt;/td>
 &lt;td>X-Ray&lt;/td>
 &lt;td>Cloud Trace&lt;/td>
 &lt;td>Application Insights&lt;/td>
 &lt;td>sampling 策略、跨服務 trace、整合 SDK&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Secret Management&lt;/td>
 &lt;td>Secrets Manager / SSM Parameter&lt;/td>
 &lt;td>Secret Manager&lt;/td>
 &lt;td>Key Vault&lt;/td>
 &lt;td>旋轉支援、整合 IAM、稽核 log&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Identity / IAM&lt;/td>
 &lt;td>IAM&lt;/td>
 &lt;td>IAM&lt;/td>
 &lt;td>Entra ID（前 AAD） + Azure RBAC&lt;/td>
 &lt;td>跨服務 policy、token lifetime、federation&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>CI/CD&lt;/td>
 &lt;td>CodePipeline / CodeBuild&lt;/td>
 &lt;td>Cloud Build / Cloud Deploy&lt;/td>
 &lt;td>Azure Pipelines&lt;/td>
 &lt;td>整合 Git 平台、執行環境彈性、計價單位&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>這張表以全球 hyperscaler 三巨頭為主、不是市場全貌。&lt;strong>Oracle Cloud (OCI)&lt;/strong> 在 enterprise / Java workload 跟金融受監管環境有顯著市佔；&lt;strong>Alibaba Cloud&lt;/strong> 在亞太 / 跨境電商是主流；&lt;strong>IBM Cloud&lt;/strong> 在金融 / 受監管環境仍存在；&lt;strong>Hetzner / DigitalOcean / Vultr&lt;/strong> 在 cost-leader 區段提供完全不同的計價模型；&lt;strong>Sovereign cloud&lt;/strong>（GDPR Schrems II 後在歐洲、JEDI / JWCC 在美國政府）是另一條獨立軸、跟資料主權合規綁定、比較對象不在這張表內。對照判讀邏輯（「對應 ≠ 等價」）可以同樣套用、但具體 vendor 名稱與差異維度要按目標廠商各自查證。&lt;/p></description><content:encoded><![CDATA[<p>面對「我該選 AWS 還是 GCP？」這類問題、第一步是把後端能力分類對應到三家雲廠商的具體服務名稱、技術細節放後面。本章提供這份對照地圖、同時警告一件事：AWS、GCP、Azure 在大部分能力上都有對應產品，但「對應」不等於「等價」— 同樣是 managed SQL、AWS RDS、GCP Cloud SQL、Azure SQL 在備份頻率、replica 行為、failover 時間、跨區複製成本上都有差異。對照表是入口、不是決策本身。</p>
<h2 id="為什麼需要這張對照地圖">為什麼需要這張對照地圖</h2>
<p>兩種使用情境會需要這張表。第一是初次選型時，讀者已經選定主要雲廠商，要對照各能力分類找出 vendor 名稱。第二是跨雲遷移評估，讀者要對照源端跟目標端的能力 gap。沒有這張表，每次都要重新查文件、容易漏掉某個能力。</p>
<p>但這張表不能取代深入評估。每個 vendor 都有不在表格內的差異，例如配額、區域可用性、跨服務整合、計價模型。表格是路由起點，後續判讀要進到該 vendor 的 deep article。</p>
<h2 id="能力--雲廠商對照表">能力 × 雲廠商對照表</h2>
<table>
  <thead>
      <tr>
          <th>能力分類</th>
          <th>AWS</th>
          <th>GCP</th>
          <th>Azure</th>
          <th>對照判讀重點</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>關聯式 DB（OLTP）</td>
          <td>RDS / Aurora</td>
          <td>Cloud SQL / AlloyDB</td>
          <td>Azure SQL / Azure Database for Postgres</td>
          <td>failover 時間、跨區 replica、IOPS 計價</td>
      </tr>
      <tr>
          <td>全球分散式 DB</td>
          <td>Aurora DSQL / DynamoDB Global Tables</td>
          <td>Spanner</td>
          <td>Cosmos DB</td>
          <td>一致性模型、寫入延遲、計價單位</td>
      </tr>
      <tr>
          <td>KV / Document DB</td>
          <td>DynamoDB</td>
          <td>Firestore / Bigtable</td>
          <td>Cosmos DB</td>
          <td>partition key 設計、capacity mode、跨區一致性</td>
      </tr>
      <tr>
          <td>快取</td>
          <td>ElastiCache（Redis / Memcached）</td>
          <td>Memorystore</td>
          <td>Azure Cache for Redis</td>
          <td>跨區複製、persistence、容量上限</td>
      </tr>
      <tr>
          <td>訊息佇列</td>
          <td>SQS / SNS / Kinesis</td>
          <td>Pub/Sub</td>
          <td>Service Bus / Event Hubs</td>
          <td>delivery guarantee、ordering、retention 期</td>
      </tr>
      <tr>
          <td>事件流（Kafka）</td>
          <td>MSK / Kinesis</td>
          <td>Pub/Sub</td>
          <td>Event Hubs (Kafka compatibility)</td>
          <td>Kafka 相容性、partition 數量、跨區複製</td>
      </tr>
      <tr>
          <td>物件儲存</td>
          <td>S3</td>
          <td>Cloud Storage</td>
          <td>Blob Storage</td>
          <td>一致性模型、跨區複製、lifecycle policy</td>
      </tr>
      <tr>
          <td>容器執行平台</td>
          <td>ECS / EKS / Fargate</td>
          <td>GKE / Cloud Run</td>
          <td>AKS / Container Apps</td>
          <td>managed 程度、cold start、計價單位</td>
      </tr>
      <tr>
          <td>Serverless 函式</td>
          <td>Lambda</td>
          <td>Cloud Functions / Cloud Run</td>
          <td>Azure Functions</td>
          <td>最大執行時間、cold start、整合方式</td>
      </tr>
      <tr>
          <td>Load Balancer</td>
          <td>ELB（ALB / NLB / CLB）</td>
          <td>Cloud Load Balancing</td>
          <td>Azure Load Balancer / App Gateway</td>
          <td>L4 vs L7、跨區 LB、TLS termination</td>
      </tr>
      <tr>
          <td>API Gateway</td>
          <td>API Gateway</td>
          <td>API Gateway / Apigee</td>
          <td>API Management</td>
          <td>rate limit、auth 整合、計價</td>
      </tr>
      <tr>
          <td>CDN / 邊緣</td>
          <td>CloudFront</td>
          <td>Cloud CDN / Media CDN</td>
          <td>Azure Front Door / CDN</td>
          <td>edge POP 數、purge API、cache key 彈性</td>
      </tr>
      <tr>
          <td>監控</td>
          <td>CloudWatch</td>
          <td>Cloud Monitoring</td>
          <td>Azure Monitor</td>
          <td>metric retention、dashboard 表達力、整合範圍</td>
      </tr>
      <tr>
          <td>Log 聚合</td>
          <td>CloudWatch Logs</td>
          <td>Cloud Logging</td>
          <td>Log Analytics</td>
          <td>ingestion 成本、query 語言、retention</td>
      </tr>
      <tr>
          <td>Tracing</td>
          <td>X-Ray</td>
          <td>Cloud Trace</td>
          <td>Application Insights</td>
          <td>sampling 策略、跨服務 trace、整合 SDK</td>
      </tr>
      <tr>
          <td>Secret Management</td>
          <td>Secrets Manager / SSM Parameter</td>
          <td>Secret Manager</td>
          <td>Key Vault</td>
          <td>旋轉支援、整合 IAM、稽核 log</td>
      </tr>
      <tr>
          <td>Identity / IAM</td>
          <td>IAM</td>
          <td>IAM</td>
          <td>Entra ID（前 AAD） + Azure RBAC</td>
          <td>跨服務 policy、token lifetime、federation</td>
      </tr>
      <tr>
          <td>CI/CD</td>
          <td>CodePipeline / CodeBuild</td>
          <td>Cloud Build / Cloud Deploy</td>
          <td>Azure Pipelines</td>
          <td>整合 Git 平台、執行環境彈性、計價單位</td>
      </tr>
  </tbody>
</table>
<p>這張表以全球 hyperscaler 三巨頭為主、不是市場全貌。<strong>Oracle Cloud (OCI)</strong> 在 enterprise / Java workload 跟金融受監管環境有顯著市佔；<strong>Alibaba Cloud</strong> 在亞太 / 跨境電商是主流；<strong>IBM Cloud</strong> 在金融 / 受監管環境仍存在；<strong>Hetzner / DigitalOcean / Vultr</strong> 在 cost-leader 區段提供完全不同的計價模型；<strong>Sovereign cloud</strong>（GDPR Schrems II 後在歐洲、JEDI / JWCC 在美國政府）是另一條獨立軸、跟資料主權合規綁定、比較對象不在這張表內。對照判讀邏輯（「對應 ≠ 等價」）可以同樣套用、但具體 vendor 名稱與差異維度要按目標廠商各自查證。</p>
<h2 id="三家雲共同缺的能力分類">三家雲共同缺的能力分類</h2>
<p>對照表覆蓋的能力都有 vendor 直接對應，但有兩類能力三家雲廠商都沒有提供等價的原生服務，要靠第三方工具補完。把這兩類獨立成段，避免在對照表中用「（無原生）」填空造成模板化。</p>
<p><strong>壓測 / 流量重放</strong>：三家雲都沒有像 RDS 對 PostgreSQL 那樣的「managed 壓測服務」。團隊要從 k6、JMeter、Gatling、Locust、Vegeta、AWS Distributed Load Testing（這是 reference architecture 而非 managed service）這類第三方工具選擇。選型考量在於：是否支援該團隊熟悉的腳本語言（k6 用 JS / Gatling 用 Scala / Locust 用 Python）、能否分散執行、能否在 CI 整合、能否重放 production traffic（GoReplay、AWS VPC Traffic Mirroring）。各工具的選型細節見 <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>
<p><strong>事故管理 / on-call 通知</strong>：三家雲都沒有原生的 incident management 平台。CloudWatch / Cloud Monitoring / Azure Monitor 只到 alert 層、不負責 escalation、on-call rotation、incident timeline 與 retrospective。這層責任目前由 PagerDuty、Opsgenie、Splunk On-Call（前 VictorOps）、Grafana OnCall 等第三方平台承擔。三家雲提供的 alert 可以 webhook 到這些平台，但 incident workflow 本身不在 cloud vendor scope 內。事故管理流程見 <a href="/blog/backend/08-incident-response/" data-link-title="模組八：事故處理與復盤" data-link-desc="用 IR 領域詞彙建問題節點、以服務級案例庫累積事故脈絡，先建概念與案例庫再進實作交接">08 事故處理模組</a>。</p>
<p>辨識這兩類「跨雲共缺」能力的價值在於：跨雲遷移時這兩層不會增加 vendor lock-in，可以保留現有第三方工具直接接到新雲；反之，cloud-native incident management 或 cloud-native 壓測這類規劃要在採購前確認是否真實存在，避免被命名類似的工具誤導。</p>
<h2 id="對應--等價的具體差異範例">「對應 ≠ 等價」的具體差異範例</h2>
<p>對照表只給名稱對應，實際選型要看差異細節。下面四個常見的差異維度示範如何把名稱對應翻成選型判讀。</p>
<h3 id="失效切換時間差異rds-vs-cloud-sql-vs-azure-sql">失效切換時間差異（RDS vs Cloud SQL vs Azure SQL）</h3>
<p>同樣是 managed PostgreSQL，三家 vendor 文件給的 failover 時間參考值差距明顯。下列數字以各雲廠商公開文件為基準、實測長尾可能拖到更長：</p>
<ul>
<li>AWS RDS Multi-AZ：vendor 文件寫「typically 60–120 seconds」、P99 實測可達數分鐘</li>
<li>AWS Aurora：vendor 文件寫「typically less than 30 seconds」、實測 30–90 秒常見</li>
<li>GCP Cloud SQL HA：vendor 文件寫「1–2 minutes」</li>
<li>Azure SQL Business Critical：vendor 文件寫「around 30 seconds」、實測 30–60 秒</li>
</ul>
<p>選擇關鍵不是「哪個快」、而是「業務能容忍多少 downtime」。30 秒對 banking、ticketing 是不能接受的；對內部後台是無感的。失效切換時間直接影響 SLO 設定跟業務連續性 — 數字以 vendor 公開文件為參考、實際決策時要用該 vendor 自己的 SLA 條款跟 incident report 驗證。</p>
<h3 id="一致性模型差異dynamodb-vs-firestore-vs-cosmos-db">一致性模型差異（DynamoDB vs Firestore vs Cosmos DB）</h3>
<p>三家的 NoSQL 在一致性語意上分歧：</p>
<ul>
<li>DynamoDB：預設 eventual consistent read、可選 strongly consistent read（成本 2 倍）</li>
<li>Firestore：strongly consistent read 是預設、跨 region 用 multi-region 配置</li>
<li>Cosmos DB：五種一致性等級可選（strong / bounded staleness / session / consistent prefix / eventual）</li>
</ul>
<p>如果應用程式假設「寫完馬上能讀到」（read-after-write），在 DynamoDB 預設模式下會撞牆。在 Cosmos DB 選 session consistency 可以保證單一 client 內 read-after-write、跨 client 仍是 eventual。這類差異要在選型階段對齊，不是事後改 code。</p>
<h3 id="計價模型差異lambda-vs-cloud-functions-vs-azure-functions">計價模型差異（Lambda vs Cloud Functions vs Azure Functions）</h3>
<p>三家的 <a href="/blog/backend/knowledge-cards/serverless/" data-link-title="Serverless" data-link-desc="說明按請求 / 按用量計費、由平台管理執行環境與擴縮的運算交付模型、與其冷啟動與計價邊界">serverless</a> 在計價單位有差異：</p>
<ul>
<li>Lambda：請求數 + 執行時間 (GB-秒)</li>
<li>Cloud Functions：請求數 + 執行時間 + 網路流量</li>
<li>Azure Functions：執行次數 + 執行時間 + 記憶體（Consumption Plan）或固定費用（Premium / Dedicated Plan）</li>
</ul>
<p>對於低流量服務、三家差異不大；對於高頻率短時間函式、計價差異可能放大數倍（具體倍數視 memory size / 執行時間 / 流量分布、用 vendor calculator 算）。選型時要用實際 workload 估算、不能看單位價格表面數字。</p>
<h3 id="跨服務整合差異消息佇列-vs-觸發器">跨服務整合差異（消息佇列 vs 觸發器）</h3>
<p>AWS SQS + Lambda 整合非常成熟、有 native trigger；GCP Pub/Sub + Cloud Functions 同樣 native；Azure Service Bus + Functions 也有 trigger，但細節（dead-letter 處理、retry 策略、batch size）跟前兩家有差異。</p>
<p>跨服務的整合成熟度通常會在事故時放大差異。同樣的事件處理流程，在 AWS 上 90% 用 native 路徑、在另一家可能需要 30% 自己寫 glue code。</p>
<h2 id="跨雲遷移的判讀重點">跨雲遷移的判讀重點</h2>
<p>把這張對照表反過來讀，就是跨雲遷移的 gap 分析起點。但實際遷移要看四類風險：</p>
<table>
  <thead>
      <tr>
          <th>風險類型</th>
          <th>判讀重點</th>
          <th>對應緩解</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>語意差異</td>
          <td>兩家「對應」服務的一致性 / 失效 / 順序語意是否一致</td>
          <td>在抽象層（repository、queue adapter）封裝差異</td>
      </tr>
      <tr>
          <td>配額差異</td>
          <td>限制（每秒請求數、partition 上限、batch size）是否相當</td>
          <td>對照新平台配額重新設計批次大小</td>
      </tr>
      <tr>
          <td>計價差異</td>
          <td>計價單位不同，舊有 cost model 在新平台失準</td>
          <td>用新平台計價重做 cost engineering</td>
      </tr>
      <tr>
          <td>生態差異</td>
          <td>周邊工具（監控、log、IAM）整合不對等</td>
          <td>預估遷移成本要含「重建 observability / IAM」</td>
      </tr>
      <tr>
          <td>Data gravity / egress lock-in</td>
          <td>PB 級資料的 egress fee 跟一致性轉移時程</td>
          <td>決定資料「同步轉移 / 漸進複製 / 保留在原雲、運算跨雲」</td>
      </tr>
  </tbody>
</table>
<p>第五類風險常被低估：以 AWS S3 為例、egress 約 $0.09/GB、PB 級資料即 $90k 帶寬費；GCP / Azure 同等級。跨雲遷移最大單筆成本經常是 data gravity、需要先決策資料拓樸再算其他三類風險。</p>
<p>跨雲遷移不是把服務名稱換掉就完成。每一個對應都要做 deep audit，這是 <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 流程 — 從實戰案例提煉的工程做法">01 大規模 DB 遷移實戰</a> 等模組的責任。</p>
<h2 id="混合雲與多雲的情境">混合雲與多雲的情境</h2>
<p>常見的混合或多雲組合：</p>
<ul>
<li><strong>資料留 AWS、ML 跑 GCP</strong>：因為 BigQuery、Vertex AI 在資料分析優勢</li>
<li><strong>主要 Azure、ML 跑 AWS</strong>：因為 SageMaker 跟 Bedrock 提供的選項</li>
<li><strong>DR 在另一家雲</strong>：主要在 AWS、DR 站在 Azure 避免單一雲廠商故障</li>
</ul>
<p>混合 / 多雲要解的核心問題是跨雲流量成本（egress）跟身分聯邦（cross-cloud IAM）。這兩個成本通常被低估，要在規劃階段就做進 cost model。</p>
<h2 id="對照表使用的判讀順序">對照表使用的判讀順序</h2>
<p>讀這張表時，避免以下兩種誤用：</p>
<p>第一是「看完表格就決定 vendor」。表格只給名稱對應，沒給選型理由。先確認自己的能力需求（容量、一致性、failover 時間、計價型態），再用表格找候選 vendor，再進該 vendor 的 deep article 驗證細節。</p>
<p>第二是「把『對應』當作可互換」。已經提到的失效時間、一致性語意、計價模型差異會直接影響業務。在做技術選型時不能假設「換家雲就行」，要驗證每一條差異。</p>
<p>正確的使用順序：能力需求 → 對照表找候選 → vendor deep article 驗證 → cost / failure / consistency 驗算 → 決策。</p>
<h2 id="判讀訊號">判讀訊號</h2>
<table>
  <thead>
      <tr>
          <th>訊號</th>
          <th>判讀重點</th>
          <th>對應動作</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>同樣 workload 在新雲上 cost 翻倍</td>
          <td>計價模型差異未被估到</td>
          <td>重做 cost engineering、用實際 traffic 估算</td>
      </tr>
      <tr>
          <td>遷移後 latency 升高</td>
          <td>區域、跨服務整合或一致性模式不同</td>
          <td>確認 region 選擇、跨服務整合方式</td>
      </tr>
      <tr>
          <td>跨雲 egress 成本失控</td>
          <td>流量設計沒考慮 inter-cloud transfer</td>
          <td>重新設計流量拓樸、考慮 cache 或聚合</td>
      </tr>
      <tr>
          <td>跨雲 IAM 設定爆炸</td>
          <td>身分聯邦設計不足、每個服務各管各的</td>
          <td>引入統一身分平台或 federation</td>
      </tr>
      <tr>
          <td>新雲服務功能對應不上</td>
          <td>「對應 ≠ 等價」的 gap 出現</td>
          <td>抽象層封裝差異、或評估是否值得換</td>
      </tr>
  </tbody>
</table>
<h2 id="常見誤區">常見誤區</h2>
<p>把 vendor 對照表當「採購清單」，看完直接照表選。選型必須回到需求，不是看哪家有對應名稱就選。</p>
<p>把雲廠商當「commodity 商品」，假設換家就好。三家的整合生態、配額限制、計價單位都有差異、遷移成本經常被嚴重低估（特別是 data gravity / IAM / 監控重建這三類隱性成本）。</p>
<p>把單一雲廠商當「永遠不會變」。雲廠商會調整定價、棄用服務、改 API。設計時要有抽象邊界，避免直接綁定 vendor SDK 到業務邏輯，方便未來換家或多雲。</p>
<h2 id="定位邊界">定位邊界</h2>
<p>本章預設「自建於雲端基礎設施」已成立；讀者若在對照表看到 Firestore 而想問「乾脆整個用 Firebase？」、那是 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>。</p>
<p>本章專注「能力分類到 vendor 名稱的翻譯與對應差異」。當問題進入具體 vendor 配置（例如 RDS 怎麼設 backup）、跨 vendor 遷移流程（例如從 MySQL 遷到 Aurora），分別交給各模組的 <code>vendors/</code> 目錄跟 migration playbook。當問題進入需求分類（這個業務需要強一致還是最終一致？）回到 <a href="/blog/backend/00-service-selection/backend-demand-taxonomy/" data-link-title="0.0 後端需求分類地圖" data-link-desc="先從需求形狀辨識狀態、讀取、非同步、即時、診斷、交付與可靠性問題">0.0 後端需求分類地圖</a>。</p>
<h2 id="案例回寫">案例回寫</h2>
<p>雲端服務選型可用以下案例回寫：</p>
<ul>
<li><a href="/blog/backend/00-service-selection/enterprise-selection-case-atlas/" data-link-title="0.14 企業選型案例圖譜" data-link-desc="蒐集不同類型與不同規模企業的技術選型案例，作為後端選型判讀的跨情境補充。">0.14 企業選型案例圖譜</a> — 0.14 收錄不同產業、不同規模階段企業的雲端選型決策；對照本章「跨雲遷移的判讀重點」段：合規、計價、IAM 整合是三家雲決策的主要分歧軸。</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：TiDB 遷到 DynamoDB</a> — Zomato 把 SQL 介面（TiDB）換成 KV 介面（DynamoDB）、用一致性語意差異換取 4 倍吞吐 + 50% 成本；對照本章「對應 ≠ 等價」段中的一致性模型差異子段。</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：Aurora consolidation</a> — 案例是 AWS 內 DB 種類整併（多 RDB → Aurora），可對照本章「對應 ≠ 等價」段中的計價模型與整合成熟度差異。雖然不涉及跨雲，但在同一家雲廠商內整併服務、跟跨雲整併共用同一條決策邏輯：權衡 vendor lock-in 代價 vs 運維碎片化代價。</li>
<li><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 K8s → EKS</a> — Tradeshift 從自管 K8s control plane 遷到 EKS managed control plane、運維責任邊界從「整套 cluster」收斂到「workload + worker node」。對照本章「容器執行平台」對照行：managed 程度是同一能力分類下的主要分歧軸。</li>
</ul>
<p>這些案例回答的是不同問題、不是同一個問題的不同切面。對照表本身只回答「叫什麼名字」；Zomato / Tradeshift 補「換掉名字後實際差多少」（介面 / 計價 / 一致性差異）；Netflix Aurora 補「同一雲內怎麼收斂」；0.14 補「真實企業在什麼壓力下選什麼」。讀者按手邊的問題進入對應案例、不需要也不適合串成同一條 narrative。</p>
<h2 id="跨模組路由">跨模組路由</h2>
<ol>
<li>與 <a href="/blog/backend/00-service-selection/service-capability-map/" data-link-title="0.1 後端服務能力地圖" data-link-desc="用需求類型判斷應先評估資料庫、快取、訊息佇列、觀測平台或部署平台">0.1 後端服務能力地圖</a> 的交接：先確認能力分類，再用本章找 vendor 對應。</li>
<li>與 <a href="/blog/backend/00-service-selection/cost-risk-tradeoffs/" data-link-title="0.6 成本、風險與選型取捨" data-link-desc="用人力成本、雲端成本、操作成本與失敗代價判斷後端能力投入順序">0.6 成本、風險與選型取捨</a> 的交接：cost model 是 vendor 選型的關鍵維度。</li>
<li>與各模組的 <code>vendors/</code> 目錄的交接：對照表只給名稱、deep article 給配置與運維。</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 流程 — 從實戰案例提煉的工程做法">01 大規模 DB 遷移實戰</a> 的交接：跨 vendor 遷移的具體流程。</li>
</ol>
<h2 id="下一步路由">下一步路由</h2>
<p>對照表是查 vendor 名稱的第一層、進入細節要走 deep article：</p>
<ul>
<li>實際企業選型案例 → <a href="/blog/backend/00-service-selection/enterprise-selection-case-atlas/" data-link-title="0.14 企業選型案例圖譜" data-link-desc="蒐集不同類型與不同規模企業的技術選型案例，作為後端選型判讀的跨情境補充。">0.14 企業選型案例圖譜</a></li>
<li>資料庫 vendor 細節對比 → <a href="/blog/backend/01-database/vendors/" data-link-title="資料庫 Vendor 清單" data-link-desc="規劃 SQL、managed SQL、document、KV 與 distributed SQL 的服務頁撰寫順序與教學大綱">01 模組 vendors/</a></li>
<li>部署平台 vendor 細節對比 → <a href="/blog/backend/05-deployment-platform/vendors/" data-link-title="部署平台 Vendor 清單" data-link-desc="規劃 workload runtime、orchestration、traffic、IaC 與 discovery 的服務頁撰寫順序與判準">05 模組 vendors/</a></li>
</ul>
<p>本章不在規模成長路線上、是 sibling 工具型入口。要進規模成長路線、從 <a href="/blog/backend/10-system-evolution/service-decomposition-boundaries/" data-link-title="10.1 服務拆分與邊界判讀" data-link-desc="整理 monolith vs microservice 取捨、服務邊界判讀訊號、拆分時機與回退路徑">10.1 服務拆分</a> 或 <a href="/blog/backend/09-performance-capacity/scaling-axes/" data-link-title="9.13 擴展軸與 Stateless 前提" data-link-desc="整理垂直 / 水平擴展取捨、stateless vs stateful 前提、auto scaling 操作模型與兩種擴展的 hidden cost">9.13 擴展軸</a> 開始。</p>
]]></content:encoded></item><item><title>Storm-0558 2023:雲端簽章金鑰壓力</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/blue-team/materials/field-cases/storm-0558-2023-cloud-signing-key-pressure/</link><pubDate>Thu, 30 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/blue-team/materials/field-cases/storm-0558-2023-cloud-signing-key-pressure/</guid><description>&lt;p>本案例的責任是提供雲端簽章金鑰壓力素材。Storm-0558 顯示,當一把過期 MSA consumer signing key 結合 token validation 缺陷時,一個身份信任根可以被用來偽造跨 tenant 的 access token。&lt;/p>
&lt;h2 id="來源">來源&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>&lt;a href="https://msrc.microsoft.com/blog/2023/07/microsoft-mitigates-china-based-threat-actor-storm-0558-targeting-of-customer-email/">Microsoft MSRC:Storm-0558 mitigation&lt;/a>&lt;/td>
 &lt;td>initial mitigation、affected scope、key revocation&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://www.microsoft.com/en-us/security/blog/2023/07/14/analysis-of-storm-0558-techniques-for-unauthorized-email-access/">Microsoft Security Blog:Analysis of Storm-0558&lt;/a>&lt;/td>
 &lt;td>token forgery、OWA 與 Outlook.com 路徑、IOC&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://www.cisa.gov/news-events/cybersecurity-advisories/aa23-193a">CISA:Enhanced Monitoring (AA23-193A)&lt;/a>&lt;/td>
 &lt;td>M365 audit log 監控建議、detection guidance&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://www.helpnetsecurity.com/2024/04/03/microsoft-storm-0558-key/">CSRB report (Help Net Security 摘要)&lt;/a>&lt;/td>
 &lt;td>key rotation 流程缺口、cascade of errors、治理檢討&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="defender-pressure">Defender Pressure&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>Signing key trust pressure&lt;/td>
 &lt;td>一把長期金鑰可以影響大量 tenant 的身份信任&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Key rotation pressure&lt;/td>
 &lt;td>自動化輪替與退役流程需要可觀測&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Tenant boundary pressure&lt;/td>
 &lt;td>consumer 與 enterprise token 邊界要明確分離&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Detection coverage pressure&lt;/td>
 &lt;td>受影響客戶常需依賴雲端供應商提供 audit log 才能查證&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="control-gap">Control Gap&lt;/h2>
&lt;p>控制缺口的核心是身份信任根的生命週期管理。當 signing key 缺少自動輪替與退役監控,且 token validator 接受跨類型金鑰時,單一遺留金鑰會升級成跨租戶風險。&lt;/p>
&lt;h2 id="detection-route">Detection Route&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>雲端 mailbox 出現未預期的 OWA token 使用&lt;/td>
 &lt;td>判斷 token forgery 可能性&lt;/td>
 &lt;td>啟動雲端身份事件回應&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>audit log 缺少 token issuer 與 key id&lt;/td>
 &lt;td>判斷 detection coverage gap&lt;/td>
 &lt;td>補強 logging 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/token-revocation/" data-link-title="Token Revocation" data-link-desc="說明事件中如何撤銷 token，縮短可利用窗口">token revocation&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>供應商 advisory 指出簽章金鑰受影響&lt;/td>
 &lt;td>判斷 key rotation 與 session 收斂優先序&lt;/td>
 &lt;td>啟動 vulnerability response state&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="exercise-hook">Exercise Hook&lt;/h2>
&lt;p>本案例可支撐 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/blue-team/materials/scenarios/identity-support-token-tabletop/" data-link-title="Identity Support Token Tabletop" data-link-desc="以支援流程與 session token 風險設計身份接管 tabletop 情境">Identity support token tabletop&lt;/a> 的雲端變體。演練重點是確認團隊能在雲端供應商通報後,快速判讀受影響 tenant、收集 audit log 並協調金鑰相關 session 收斂。&lt;/p>
&lt;h2 id="write-back-target">Write-back Target&lt;/h2>
&lt;ul>
&lt;li>&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;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/blue-team/vulnerability-response-state-machine/" data-link-title="7.B11 Vulnerability Response State Machine" data-link-desc="把漏洞回應拆成狀態機，建立 observed 到 closed 的可交接流程">7.B11 Vulnerability Response State Machine&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/blue-team/materials/control-patterns/control-owner-pattern/" data-link-title="Control Owner Pattern" data-link-desc="定義高風險控制面如何配置 owner、協作角色、決策角色與升級路徑">Control owner pattern&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/blue-team/materials/control-patterns/evidence-chain-pattern/" data-link-title="Evidence Chain Pattern" data-link-desc="定義事故與演練需要保存的訊號、決策、artifact、timeline 與 retention 證據">Evidence chain pattern&lt;/a>&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>本案例的責任是提供雲端簽章金鑰壓力素材。Storm-0558 顯示,當一把過期 MSA consumer signing key 結合 token validation 缺陷時,一個身份信任根可以被用來偽造跨 tenant 的 access token。</p>
<h2 id="來源">來源</h2>
<table>
  <thead>
      <tr>
          <th>來源</th>
          <th>可引用範圍</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="https://msrc.microsoft.com/blog/2023/07/microsoft-mitigates-china-based-threat-actor-storm-0558-targeting-of-customer-email/">Microsoft MSRC:Storm-0558 mitigation</a></td>
          <td>initial mitigation、affected scope、key revocation</td>
      </tr>
      <tr>
          <td><a href="https://www.microsoft.com/en-us/security/blog/2023/07/14/analysis-of-storm-0558-techniques-for-unauthorized-email-access/">Microsoft Security Blog:Analysis of Storm-0558</a></td>
          <td>token forgery、OWA 與 Outlook.com 路徑、IOC</td>
      </tr>
      <tr>
          <td><a href="https://www.cisa.gov/news-events/cybersecurity-advisories/aa23-193a">CISA:Enhanced Monitoring (AA23-193A)</a></td>
          <td>M365 audit log 監控建議、detection guidance</td>
      </tr>
      <tr>
          <td><a href="https://www.helpnetsecurity.com/2024/04/03/microsoft-storm-0558-key/">CSRB report (Help Net Security 摘要)</a></td>
          <td>key rotation 流程缺口、cascade of errors、治理檢討</td>
      </tr>
  </tbody>
</table>
<h2 id="defender-pressure">Defender Pressure</h2>
<table>
  <thead>
      <tr>
          <th>壓力</th>
          <th>服務判讀</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Signing key trust pressure</td>
          <td>一把長期金鑰可以影響大量 tenant 的身份信任</td>
      </tr>
      <tr>
          <td>Key rotation pressure</td>
          <td>自動化輪替與退役流程需要可觀測</td>
      </tr>
      <tr>
          <td>Tenant boundary pressure</td>
          <td>consumer 與 enterprise token 邊界要明確分離</td>
      </tr>
      <tr>
          <td>Detection coverage pressure</td>
          <td>受影響客戶常需依賴雲端供應商提供 audit log 才能查證</td>
      </tr>
  </tbody>
</table>
<h2 id="control-gap">Control Gap</h2>
<p>控制缺口的核心是身份信任根的生命週期管理。當 signing key 缺少自動輪替與退役監控,且 token validator 接受跨類型金鑰時,單一遺留金鑰會升級成跨租戶風險。</p>
<h2 id="detection-route">Detection Route</h2>
<table>
  <thead>
      <tr>
          <th>訊號</th>
          <th>判讀用途</th>
          <th>下一步</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>雲端 mailbox 出現未預期的 OWA token 使用</td>
          <td>判斷 token forgery 可能性</td>
          <td>啟動雲端身份事件回應</td>
      </tr>
      <tr>
          <td>audit log 缺少 token issuer 與 key id</td>
          <td>判斷 detection coverage gap</td>
          <td>補強 logging 與 <a href="/blog/backend/knowledge-cards/token-revocation/" data-link-title="Token Revocation" data-link-desc="說明事件中如何撤銷 token，縮短可利用窗口">token revocation</a></td>
      </tr>
      <tr>
          <td>供應商 advisory 指出簽章金鑰受影響</td>
          <td>判斷 key rotation 與 session 收斂優先序</td>
          <td>啟動 vulnerability response state</td>
      </tr>
  </tbody>
</table>
<h2 id="exercise-hook">Exercise Hook</h2>
<p>本案例可支撐 <a href="/blog/backend/07-security-data-protection/blue-team/materials/scenarios/identity-support-token-tabletop/" data-link-title="Identity Support Token Tabletop" data-link-desc="以支援流程與 session token 風險設計身份接管 tabletop 情境">Identity support token tabletop</a> 的雲端變體。演練重點是確認團隊能在雲端供應商通報後,快速判讀受影響 tenant、收集 audit log 並協調金鑰相關 session 收斂。</p>
<h2 id="write-back-target">Write-back Target</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/blue-team/vulnerability-response-state-machine/" data-link-title="7.B11 Vulnerability Response State Machine" data-link-desc="把漏洞回應拆成狀態機，建立 observed 到 closed 的可交接流程">7.B11 Vulnerability Response State Machine</a></li>
<li><a href="/blog/backend/07-security-data-protection/blue-team/materials/control-patterns/control-owner-pattern/" data-link-title="Control Owner Pattern" data-link-desc="定義高風險控制面如何配置 owner、協作角色、決策角色與升級路徑">Control owner pattern</a></li>
<li><a href="/blog/backend/07-security-data-protection/blue-team/materials/control-patterns/evidence-chain-pattern/" data-link-title="Evidence Chain Pattern" data-link-desc="定義事故與演練需要保存的訊號、決策、artifact、timeline 與 retention 證據">Evidence chain pattern</a></li>
</ul>
]]></content:encoded></item></channel></rss>