

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 進階遷移案例
<a name="dotnet-migrating-applications-advanced-scenarios"></a>

本節涵蓋複雜 IIS 部署的進階遷移案例。

## 使用應用程式請求路由 (ARR) 進行多站台遷移
<a name="dotnet-migrating-applications-advanced-scenarios-arr"></a>

**eb migrate** 命令會在遷移期間自動偵測並保留 ARR 組態。當識別 IIS 中的 ARR 設定時`applicationHost.config`，它會產生必要的 PowerShell 指令碼，以在目標 EC2 執行個體上重新安裝和設定 ARR。

### ARR 組態偵測
<a name="dotnet-migrating-applications-advanced-scenarios-arr-detection"></a>

遷移程序會檢查 IIS 中的三個金鑰組態區段：
+ `system.webServer/proxy`：核心 ARR 代理設定
+ `system.webServer/rewrite`：URL 重寫規則
+ `system.webServer/caching`：快取組態

例如，請考慮常見的 ARR 組態，其中`RouterSite`在連接埠 80 上執行的 會分別代理對連接埠 8081 和連接埠 8082 的請求`APIService`和`AdminPortal`執行：

```
<!-- Original IIS ARR Configuration -->
<rewrite>
    <rules>
        <rule name="Route to API" stopProcessing="true">
            <match url="^api/(.*)$" />
            <action type="Rewrite" url="http://backend:8081/api/{R:1}" />
        </rule>
        <rule name="Route to Admin" stopProcessing="true">
            <match url="^admin/(.*)$" />
            <action type="Rewrite" url="http://backend:8082/admin/{R:1}" />
        </rule>
    </rules>
</rewrite>
```

下圖說明這些規則如何在 IIS 伺服器的連接埠 80 後方隱藏，而不是透過 EC2 安全群組公開。只有連接埠 80 可供 Application Load Balancer 存取，而且來自它的所有流量都會路由到連接埠 80 的目標群組。

![具有應用程式請求路由 (ARR) 的 Elastic Beanstalk 架構](http://docs.aws.amazon.com/zh_tw/elasticbeanstalk/latest/dg/images/architecture-diagram-with-arr.png)


下列命令可以遷移此組態：

```
PS C:\migrations_workspace> eb migrate --sites "RouterSite,APIService,AdminPortal" `
    --copy-firewall-config
```

### ARR 遷移程序
<a name="dotnet-migrating-applications-advanced-scenarios-arr-process"></a>

遷移程序會透過數個步驟保留您的 ARR 組態。

組態匯出  
此工具會將您現有的 ARR 設定從三個金鑰組態區段匯出到存放在 `ebmigrateScripts`目錄中的個別 XML 檔案：  

```
ebmigrateScripts\
├── arr_config_proxy.xml
├── arr_config_rewrite.xml
└── arr_config_caching.xml
```

安裝指令碼  
會產生兩個 PowerShell 指令碼來處理 ARR 設定：  

1. `arr_msi_installer.ps1`：下載並安裝 ARR 模組

1. `arr_configuration_importer_script.ps1`：匯入匯出的 ARR 組態

部署資訊清單整合  
指令碼會透過 中的項目整合到部署程序中`aws-windows-deployment-manifest.json`：  

```
{
    "manifestVersion": 1,
    "deployments": {
        "custom": [
            {
                "name": "WindowsProxyFeatureEnabler",
                "scripts": {
                    "install": {
                        "file": "ebmigrateScripts\\windows_proxy_feature_enabler.ps1"
                    }
                }
            },
            {
                "name": "ArrConfigurationImporterScript",
                "scripts": {
                    "install": {
                        "file": "ebmigrateScripts\\arr_configuration_importer_script.ps1"
                    }
                }
            }
        ]
    }
}
```

### 負載平衡器整合
<a name="dotnet-migrating-applications-advanced-scenarios-arr-lb"></a>

遷移程序會盡可能將您的 ARR 規則轉譯為 Application Load Balancer (ALB) 接聽程式規則。例如，上述 ARR 組態會產生根據 URL 路徑模式路由流量的 ALB 規則，同時在 EC2 執行個體上維持內部路由。

產生的環境會維護您的 ARR 路由邏輯，同時利用 AWS的彈性基礎設施。您的應用程式會繼續像以前一樣運作，在 Application Load Balancer 管理外部流量分佈時，使用 ARR 處理內部路由。

## 使用主機型路由，不含 ARR 的多站台遷移
<a name="dotnet-migrating-applications-advanced-scenarios-no-arr"></a>

雖然 Application Request Routing (ARR) 是在 IIS 中管理多個站台的常見方法，但您也可以利用 Application Load Balancer 的主機型路由功能，直接將多站台部署遷移至 Elastic Beanstalk 而不需 ARR。這種方法可以透過消除額外的路由層來降低複雜性並改善效能。

### 主機型路由概觀
<a name="dotnet-migrating-applications-advanced-scenarios-no-arr-overview"></a>

在此方法中，每個 IIS 網站都會在 EC2 執行個體外公開，而 Application Load Balancer 會根據主機標頭，將流量直接路由至適當的連接埠。這消除了對 ARR 的需求，同時保持應用程式之間的區隔。

考慮具有三個站台的多站台 IIS 組態，每個站台都有自己的主機名稱繫結：

```
<sites>
    <site name="Default Web Site" id="1">
        <bindings>
            <binding protocol="http" bindingInformation="*:8081:www.example.com" />
        </bindings>
    </site>
    <site name="InternalAPI" id="2">
        <bindings>
            <binding protocol="http" bindingInformation="*:8082:api.internal" />
        </bindings>
    </site>
    <site name="ReportingPortal" id="3">
        <bindings>
            <binding protocol="http" bindingInformation="*:8083:reports.internal" />
        </bindings>
    </site>
</sites>
```

這些網站會透過 EC2 安全群組在連接埠 8081、8082 和 8083 公開。Application Load Balancer 會根據 Load Balancer 接聽程式規則組態路由至它們。

![Elastic Beanstalk 架構不含應用程式請求路由 (ARR)](http://docs.aws.amazon.com/zh_tw/elasticbeanstalk/latest/dg/images/architecture-diagram-without-arr.png)


### 遷移程序
<a name="dotnet-migrating-applications-advanced-scenarios-no-arr-migration"></a>

若要將此組態遷移至 Elastic Beanstalk，而不使用 ARR，請使用下列範例中的 **eb migrate**命令：

```
PS C:\migrations_workspace> eb migrate --sites "Default Web Site,InternalAPI,ReportingPortal"
```

遷移程序會使用主機型路由規則自動設定 Application Load Balancer，以根據主機標頭將流量導向適當的目標群組。每個目標群組都會將流量轉送至 EC2 執行個體上的對應連接埠：

1. 主機標頭 www.example.com → 連接埠 8081 上的目標群組

1. 連接埠 8082 上的主機標頭 api.internal → 目標群組

1. 主機標頭 report.internal → 連接埠 8083 上的目標群組

### SSL/TLS 組態
<a name="dotnet-migrating-applications-advanced-scenarios-no-arr-ssl"></a>

若要使用 SSL/TLS 保護您的應用程式，請執行下列步驟：

1. 透過 AWS Certificate Manager(ACM) 為您的網域請求憑證。

1. 使用這些憑證在 Application Load Balancer 上設定 HTTPS 接聽程式。

1. 更新您的環境組態，以使用下列組態選項設定包含 HTTPS 接聽程式。

   ```
   option_settings:
     aws:elb:listener:443:
       ListenerProtocol: HTTPS
       SSLCertificateId: arn:aws:acm:region:account-id:certificate/certificate-id
       InstancePort: 80
       InstanceProtocol: HTTP
   ```

使用此組態時，負載平衡器會發生 SSL 終止，而流量會透過 HTTP 轉送到您的執行個體。這可簡化憑證管理，同時維持與用戶端的安全連線。

### 最佳實務
<a name="dotnet-migrating-applications-advanced-scenarios-no-arr-best"></a>

Security groups (安全群組)  
設定安全群組以僅允許來自 Application Load Balancer 安全群組的 IIS 網站 （本範例中為 8081、8082、8083) 所使用的連接埠傳入流量。

運作狀態檢查  
為每個目標群組設定運作狀態檢查，以確保流量只會路由至運作狀態良好的執行個體。如果每個應用程式尚未存在，請為每個應用程式建立運作狀態檢查端點。

監控  
設定 CloudWatch 警示以分別監控每個目標群組的運作狀態和效能。這可讓您識別個別應用程式特有的問題。

擴展  
設定自動擴展政策時，請考慮所有應用程式的資源需求。如果一個應用程式有顯著不同的資源需求，請考慮將其遷移到不同的環境。

## 虛擬目錄管理
<a name="dotnet-migrating-applications-advanced-scenarios-vdir"></a>

**eb migrate** 命令會保留虛擬目錄結構，同時將 IIS 應用程式遷移至 Elastic Beanstalk。

### 預設許可組態
<a name="dotnet-migrating-applications-advanced-scenarios-vdir-default"></a>

遷移虛擬目錄時， 會授予 ReadAndExecute 存取權，以**eb migrate**建立一組基準許可：
+ IIS\_IUSRS
+ IUSR
+ 已驗證的使用者

例如，請考慮一般虛擬目錄結構：

```
<site name="CorporatePortal">
    <application path="/" applicationPool="CorporatePortalPool">
        <virtualDirectory path="/" physicalPath="C:\sites\portal" />
        <virtualDirectory path="/shared" physicalPath="C:\shared\content" />
        <virtualDirectory path="/reports" physicalPath="D:\reports" />
    </application>
</site>
```

### 受密碼保護的虛擬目錄
<a name="dotnet-migrating-applications-advanced-scenarios-vdir-password"></a>

當 **eb migrate**遇到受密碼保護的虛擬目錄時，它會發出警告並需要手動介入。

下列組態範例將導致遵循範例的警告回應。

```
<virtualDirectory path="/secure" 
                 physicalPath="C:\secure\content"
                 userName="DOMAIN\User"
                 password="[encrypted]" />
```

```
[WARNING] CorporatePortal/secure is hosted at C:\secure\content which is password-protected and won't be copied.
```

若要維護密碼保護，請建立自訂部署指令碼，如下所示：

```
# PS C:\migrations_workspace> cat secure_vdir_config.ps1

$vdirPath = "C:\secure\content"
$siteName = "CorporatePortal"
$vdirName = "secure"
$username = "DOMAIN\User"
$password = "SecurePassword"

# Ensure directory exists
if (-not (Test-Path $vdirPath)) {
    Write-Host "Creating directory: $vdirPath"
    New-Item -Path $vdirPath -ItemType Directory -Force
}

# Configure virtual directory with credentials
Write-Host "Configuring protected virtual directory: $vdirName"
New-WebVirtualDirectory -Site $siteName -Name $vdirName `
    -PhysicalPath $vdirPath -UserName $username -Password $password

# Set additional permissions as needed
$acl = Get-Acl $vdirPath
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule(
    $username, "ReadAndExecute", "ContainerInherit,ObjectInherit", "None", "Allow"
)
$acl.AddAccessRule($rule)
Set-Acl $vdirPath $acl
```

在資訊清單中包含此指令碼，以將此指令碼新增至您的部署：

```
{
    "manifestVersion": 1,
    "deployments": {
        "custom": [
            {
                "name": "SecureVirtualDirectory",
                "scripts": {
                    "install": {
                        "file": "secure_vdir_config.ps1"
                    }
                }
            }
        ]
    }
}
```

### 自訂許可管理
<a name="dotnet-migrating-applications-advanced-scenarios-vdir-custom"></a>

**eb migrate** 命令提供自訂許可指令碼的架構，以容納需要預設值以外許可的應用程式。



```
$paths = @(
    "C:\sites\portal\uploads",
    "C:\shared\content"
)

foreach ($path in $paths) {
    if (-not (Test-Path $path)) {
        Write-Host "Creating directory: $path"
        New-Item -Path $path -ItemType Directory -Force
    }

    $acl = Get-Acl $path

    # Add custom permissions
    $customRules = @(
        # Application Pool Identity - Full Control
        [System.Security.AccessControl.FileSystemAccessRule]::new(
            "IIS AppPool\CorporatePortalPool", 
            "FullControl", 
            "ContainerInherit,ObjectInherit", 
            "None", 
            "Allow"
        ),
        # Custom Service Account
        [System.Security.AccessControl.FileSystemAccessRule]::new(
            "NT SERVICE\CustomService", 
            "Modify", 
            "ContainerInherit,ObjectInherit", 
            "None", 
            "Allow"
        )
    )

    foreach ($rule in $customRules) {
        $acl.AddAccessRule($rule)
    }
    
    Set-Acl $path $acl
    Write-Host "Custom permissions applied to: $path"
}
```

### 最佳實務
<a name="dotnet-migrating-applications-advanced-scenarios-vdir-best"></a>

遵循這些最佳實務來規劃、執行、監控和驗證您的遷移。

遷移前規劃  
在遷移之前記錄現有的許可和身分驗證要求。在部署到生產環境之前，在開發環境中測試自訂許可指令碼。

共用內容管理  
對於共用內容目錄，請確定所有必要的檔案系統許可都已透過自訂指令碼正確設定。考慮將 [Amazon FSx for Windows File Server](https://aws.amazon.com/fsx/windows/) 用於共用儲存需求。

監控和驗證  
在遷移後監控應用程式日誌，以驗證對虛擬目錄的正確存取。請特別注意下列領域：  
+ 應用程式集區身分存取
+ 自訂服務帳戶許可
+ 網路共享連線
+ 身分驗證失敗

## 自訂應用程式集區設定
<a name="dotnet-migrating-applications-advanced-scenarios-apppool"></a>

根據預設， **eb migrate**命令不會透過自訂應用程式集區設定進行複製。若要保留自訂應用程式集區組態，請依照此程序建立和套用自訂資訊清單區段。

1. 建立遷移成品的封存。

   ```
   PS C:\migrations_workspace> eb migrate --archive
   ```

1. 建立自訂 PowerShell 指令碼來設定應用程式集區。

   ```
   # PS C:\migrations_workspace> cat .\migrations\latest\upload_target\customize_application_pool_config.ps1
   
   $configPath = "$env:windir\System32\inetsrv\config\applicationHost.config"
   
   [xml]$config = Get-Content -Path $configPath
   
   $newPoolXml = @"
   <!-- Original IIS Configuration -->
   <applicationPools>
       <add name="CustomPool" 
            managedRuntimeVersion="v4.0" 
            managedPipelineMode="Integrated">
           <processModel identityType="SpecificUser" 
                        userName="AppPoolUser" 
                        password="[encrypted]" />
           <recycling>
               <periodicRestart time="00:00:00">
                   <schedule>
                       <add value="02:00:00" />
                       <add value="14:00:00" />
                   </schedule>
               </periodicRestart>
           </recycling>
       </add>
   </applicationPools>
   "@
   $newPoolXmlNode = [xml]$newPoolXml
   
   # Find the applicationPools section
   $applicationPools = $config.SelectSingleNode("//configuration/system.applicationHost/applicationPools")
   
   # Import the new node into the document
   $importedNode = $config.ImportNode($newPoolXmlNode.DocumentElement, $true)
   $applicationPools.AppendChild($importedNode)
   
   # Save the changes
   $config.Save($configPath)
   
   Write-Host "ApplicationHost.config has been updated successfully."
   ```

1. 更新 `aws-windows-deployment-manifest.json` 檔案以包含您的自訂指令碼。

   ```
   {
       "manifestVersion": 1,
       "deployments": {
           ...
           "custom": [
               ...,
               {
                   "name": "ModifyApplicationPoolConfig",
                   "description": "Modify application pool configuration from source machine to remove",
                   "scripts": {
                       "install": {
                           "file": "customize_application_pool_config.ps1"
                       },
                       "restart": {
                           "file": "ebmigrateScripts\\noop.ps1"
                       },
                       "uninstall": {
                           "file": "ebmigrateScripts\\noop.ps1"
                       }
                   }
               }
           ]
       }
   }
   ```

1. 使用更新的封存目錄建立環境。

   ```
   PS C:\migrations_workspace> eb migrate `
       --archive-dir '.\migrations\latest\upload_target\'
   ```

`--archive-dir` 引數**eb migrate**會告知 使用先前建立的原始碼，避免建立新的封存。

## 部署舊版
<a name="dotnet-migrating-applications-advanced-scenarios-previous"></a>

會透過 Elastic Beanstalk 中的時間戳記目錄和應用程式版本來**eb migrate**維護遷移的歷史記錄。每次遷移都會建立唯一的 zip 檔案，可視需要部署。

```
PS C:\migrations_workspace> ls .\migrations\

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d----l        3/18/2025  10:34 PM                latest
d-----        3/16/2025   5:47 AM                migration_1742104049.479849
d-----        3/17/2025   9:18 PM                migration_1742246303.18056
d-----        3/17/2025   9:22 PM                migration_1742246546.565739
...
d-----        3/18/2025  10:34 PM                migration_1742337258.30742
```

`latest` 符號連結一律指向最近建立的遷移成品目錄。除了相關的應用程式和錯誤日誌，每個遷移成品目錄還包含一個`upload_target.zip`檔案，您可以部署到 Elastic Beanstalk。

```
PS C:\migrations_workspace> ls .\migrations\latest\

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----        3/18/2025  10:34 PM                upload_target
-a----        3/18/2025  10:34 PM          13137 application.log
-a----        3/18/2025  10:34 PM              0 error.log
-a----        3/18/2025  10:34 PM        1650642 upload_target.zip
```

您可以使用 部署 `upload_target.zip` 檔案**eb migrate**：

```
PS C:\migrations_workspace> eb migrate --zip .\migrations\latest\upload_target.zip
```