

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

# AWS App Mesh 和 Amazon EC2 入門
<a name="getting-started-ec2"></a>

**重要**  
支援終止通知：在 2026 年 9 月 30 日， AWS 將停止對 的支援 AWS App Mesh。2026 年 9 月 30 日之後，您將無法再存取 AWS App Mesh 主控台或 AWS App Mesh 資源。如需詳細資訊，請參閱此部落格文章[從 遷移 AWS App Mesh 至 Amazon ECS Service Connect](https://aws.amazon.com/blogs/containers/migrating-from-aws-app-mesh-to-amazon-ecs-service-connect)。

本主題可協助您將 AWS App Mesh 與在 Amazon EC2 上執行的實際服務搭配使用。本教學課程涵蓋數種 App Mesh 資源類型的基本功能。

## 案例
<a name="scenario"></a>

若要說明如何使用 App Mesh，請假設您擁有具有下列特性的應用程式：
+ 包含兩個名為 `serviceA`和 的服務`serviceB`。
+ 這兩個服務都註冊到名稱為 `apps.local` 的命名空間。
+ `ServiceA` 與 `serviceB` 透過 HTTP/2，連接埠 80 進行通訊。
+  您已部署 `serviceB` 第 2 版，並在 `apps.local` 命名空間中將其註冊為名稱 `serviceBv2`。

您有以下要求：
+ 您想要將 75% 的流量從 `serviceA` 傳送到 ，`serviceB`並將 25% 的流量傳送到 `serviceBv2` 。透過僅將 25% 傳送到 `serviceBv2`，您可以在從 傳送 100% 的流量之前驗證其是否沒有錯誤`serviceA`。
+ 您希望能夠輕鬆地調整流量權重，以便證實流量可靠之後，能夠 100% 流入 `serviceBv2`。將所有流量傳送到 後`serviceBv2`，您想要停止 `serviceB`。
+ 您不想變更實際服務的任何現有應用程式碼或服務探索註冊，以符合先前的要求。

為了滿足您的需求，您決定建立具有虛擬服務、虛擬節點、虛擬路由器和路由的 App Mesh 服務網格。實作網格後，您會更新您的服務以使用 Envoy 代理。一旦更新，您的服務會透過 Envoy 代理彼此通訊，而非直接相互通訊。

## 先決條件
<a name="prerequisites"></a>

App Mesh 支援向 DNS AWS Cloud Map或兩者註冊的 Linux 服務。若要使用此入門指南，建議您擁有三個已向 DNS 註冊的現有服務。即使服務不存在，您也可以建立服務網格及其資源，但在部署實際服務之前，您無法使用網格。

如果您還沒有執行中的服務，您可以啟動 Amazon EC2 執行個體並將應用程式部署到這些執行個體。如需詳細資訊，請參閱《[Amazon EC2 使用者指南》中的教學課程：Amazon EC2 Linux 執行個體入門](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-lamp-amazon-linux-2.html)。 Amazon EC2 其餘步驟假設實際服務名稱為 `serviceA`、`serviceB` 和 `serviceBv2`，而且所有服務皆可透過名稱為 `apps.local` 的命名空間探索。

## 步驟 1：建立網格和虛擬服務
<a name="create-mesh-and-virtual-service"></a>

服務網格是在它之內各服務之間網路流量的邏輯邊界。如需詳細資訊，請參閱[服務網格](meshes.md)。虛擬服務是實際服務的抽象化。如需詳細資訊，請參閱[虛擬服務](virtual_services.md)。

建立下列資源：
+ 名稱為 `apps` 的網格，因為案例中的所有服務皆註冊到 `apps.local` 命名空間。
+ 名稱為 `serviceb.apps.local` 的虛擬服務，因為虛擬服務代表可使用該名稱探索的服務，而且您不想將程式碼變更為參照其他名稱。稍後的步驟會新增名稱為 `servicea.apps.local` 的虛擬服務。

您可以使用 AWS 管理主控台 或 1.18.116 AWS CLI 版或更新版本，或 2.0.38 版或更新版本來完成下列步驟。如果使用 AWS CLI，請使用 `aws --version`命令來檢查已安裝的 AWS CLI 版本。如果您沒有安裝 1.18.116 或更新版本或 2.0.38 或更新版本，則必須[安裝或更新 AWS CLI](https://docs.aws.amazon.com/cli/latest/reference/appmesh/cli-chap-install.html)。為您要使用的工具選取索引標籤。

------
#### [ AWS 管理主控台 ]

1. 在 https：//[https://console.aws.amazon.com/appmesh/get-started](https://console.aws.amazon.com/appmesh/get-started) 開啟 App Mesh 主控台初次執行精靈。

1. 對於 **Mesh name (網格名稱)**，輸入 **apps**。

1. 對於 **Virtual service name (虛擬服務名稱)**，輸入 **serviceb.apps.local**。

1. 若要繼續，請選擇 **Next (下一步)**。

------
#### [ AWS CLI ]

1. 使用 `[create-mesh](https://docs.aws.amazon.com/cli/latest/reference/appmesh/create-mesh.html)` 命令建立網格。

   ```
   aws appmesh create-mesh --mesh-name apps
   ```

1. 使用 `[create-virtual-service](https://docs.aws.amazon.com/cli/latest/reference/appmesh/create-virtual-service.html)` 命令建立虛擬服務。

   ```
   aws appmesh create-virtual-service --mesh-name apps --virtual-service-name serviceb.apps.local --spec {}
   ```

------

## 步驟 2：建立虛擬節點
<a name="create-virtual-node"></a>

虛擬節點可做為實際服務的邏輯指標。如需詳細資訊，請參閱[虛擬節點](virtual_nodes.md)。

建立名稱為 `serviceB` 的虛擬節點，因為其中一個虛擬節點代表名稱為 `serviceB` 的實際服務。虛擬節點代表的實際服務可透過 `DNS` (主機名稱為 `serviceb.apps.local`) 探索。或者，您可以使用 AWS Cloud Map探索實際服務。虛擬節點會使用連接埠 80 上的 HTTP/2 通訊協定接聽流量。也支援其他通訊協定，以及運作狀態檢查。您可以在後續步驟`serviceBv2`中為 `serviceA`和 建立虛擬節點。

------
#### [ AWS 管理主控台 ]

1. 對於 **Virtual node name (虛擬節點名稱)**，輸入 **serviceB**。

1. 針對**服務探索方法**，選擇 **DNS**，然後輸入 **serviceb.apps.local** **DNS 主機名稱**。

1. 在**接聽程式組態**下，為**通訊協定**選擇 **http2**，並為**連接埠**輸入 **80** 。

1. 若要繼續，請選擇 **Next (下一步)**。

------
#### [ AWS CLI ]

1. 使用下列內容建立名為 `create-virtual-node-serviceb.json` 的檔案：

   ```
   {
       "meshName": "apps",
       "spec": {
           "listeners": [
               {
                   "portMapping": {
                       "port": 80,
                       "protocol": "http2"
                   }
               }
           ],
           "serviceDiscovery": {
               "dns": {
                   "hostname": "serviceB.apps.local"
               }
           }
       },
       "virtualNodeName": "serviceB"
   }
   ```

1. 使用 JSON 檔案做為輸入，搭配 [create-virtual-node](https://docs.aws.amazon.com/cli/latest/reference/appmesh/create-virtual-node.html) 命令建立虛擬節點。

   ```
   aws appmesh create-virtual-node --cli-input-json file://create-virtual-node-serviceb.json
   ```

------

## 步驟 3：建立虛擬路由器和路由
<a name="create-virtual-router-and-route"></a>

虛擬路由器會路由網格內一或多個虛擬服務的流量。如需詳細資訊，請參閱[虛擬路由器](virtual_routers.md)及[路由](routes.md)。

建立下列資源：
+ 名為 `serviceB` 的虛擬路由器，因為 `serviceB.apps.local` 虛擬服務不會啟動與任何其他服務的對外通訊。請記住，您先前建立的虛擬服務是實際 `serviceb.apps.local` 服務的抽象。虛擬服務會將流量傳送至虛擬路由器。虛擬路由器會使用連接埠 80 上的 HTTP/2 通訊協定接聽流量。也支援其他通訊協定。
+ 名為 `serviceB` 的路由。它將 100% 的流量路由到`serviceB`虛擬節點。新增`serviceBv2`虛擬節點後，權重會進入後續步驟。雖然未涵蓋在本指南中，但您可以為路由新增其他篩選條件，並新增重試政策，使 Envoy 代理在遇到通訊問題時多次嘗試將流量傳送至虛擬節點。

------
#### [ AWS 管理主控台 ]

1. 對於 **Virtual router name (虛擬路由器名稱)**，輸入 **serviceB**。

1. 在**接聽程式組態**下，為**通訊協定**選擇 **http2**，並為**連接埠**指定 **80** 。

1. 對於 **Route name (路由名稱)**，輸入 **serviceB**。

1. 對於 **Route type (路由類型)**，選擇 **http2**。

1. 針對**目標組態**下的**虛擬節點名稱**，選取 `serviceB`並輸入 **100**表示**權重**。

1. 在**相符組態**下，選擇**方法**。

1. 若要繼續，請選擇 **Next (下一步)**。

------
#### [ AWS CLI ]

1. 建立虛擬路由器。

   1. 使用下列內容建立名為 `create-virtual-router.json` 的檔案：

      ```
      {
          "meshName": "apps",
          "spec": {
              "listeners": [
                  {
                      "portMapping": {
                          "port": 80,
                          "protocol": "http2"
                      }
                  }
              ]
          },
          "virtualRouterName": "serviceB"
      }
      ```

   1. 使用 JSON 檔案做為輸入，搭配 [create-virtual-router](https://docs.aws.amazon.com/cli/latest/reference/appmesh/create-virtual-router.html) 命令建立虛擬路由器。

      ```
      aws appmesh create-virtual-router --cli-input-json file://create-virtual-router.json
      ```

1. 建立路由。

   1. 使用下列內容建立名為 `create-route.json` 的檔案：

      ```
      {
          "meshName" : "apps",
          "routeName" : "serviceB",
          "spec" : {
              "httpRoute" : {
                  "action" : {
                      "weightedTargets" : [
                          {
                              "virtualNode" : "serviceB",
                              "weight" : 100
                          }
                      ]
                  },
                  "match" : {
                      "prefix" : "/"
                  }
              }
          },
          "virtualRouterName" : "serviceB"
      }
      ```

   1. 使用 JSON 做為輸入，搭配 [create-route](https://docs.aws.amazon.com/cli/latest/reference/appmesh/create-route.html) 命令建立路由。

      ```
      aws appmesh create-route --cli-input-json file://create-route.json
      ```

------

## 步驟 4：檢閱和建立
<a name="review-create"></a>

依照先前的指示檢閱設定。

------
#### [ AWS 管理主控台 ]

如果您需要在任何區段中進行變更，請選擇 **Edit (編輯)**。對這些設定感到滿意後，請選擇 **Create mesh (建立網格)**。

**Status (狀態)** 畫面會顯示所有已建立的網格資源。選取 **View mesh (檢視網格)** 即可在主控台中檢視建立的資源。

------
#### [ AWS CLI ]

檢閱您使用 [describe-mesh](https://docs.aws.amazon.com/cli/latest/reference/appmesh/describe-mesh.html) 命令建立的網格設定。

```
aws appmesh describe-mesh --mesh-name apps
```

檢閱您使用 [describe-virtual-service](https://docs.aws.amazon.com/cli/latest/reference/appmesh/describe-virtual-service.html) 命令建立的虛擬服務設定。

```
aws appmesh describe-virtual-service --mesh-name apps --virtual-service-name serviceb.apps.local
```

檢閱您使用 [describe-virtual-node](https://docs.aws.amazon.com/cli/latest/reference/appmesh/describe-virtual-node.html) 命令建立的虛擬節點設定。

```
aws appmesh describe-virtual-node --mesh-name apps --virtual-node-name serviceB
```

檢閱您使用 [describe-virtual-router](https://docs.aws.amazon.com/cli/latest/reference/appmesh/describe-virtual-router.html) 命令建立的虛擬路由器設定。

```
aws appmesh describe-virtual-router --mesh-name apps --virtual-router-name serviceB
```

檢閱您使用 [describe-route](https://docs.aws.amazon.com/cli/latest/reference/appmesh/describe-route.html) 命令建立的路由設定。

```
aws appmesh describe-route --mesh-name apps \
    --virtual-router-name serviceB  --route-name serviceB
```

------

## 步驟 5：建立其他資源
<a name="create-additional-resources"></a>

若要完成案例，您必須：
+ 建立一個名為 `serviceBv2` 的虛擬節點，以及另一個名為 `serviceA` 的虛擬節點。這兩個虛擬節點都會透過 HTTP/2 連接埠 80 接聽請求。針對`serviceA`虛擬節點，設定 的後端`serviceb.apps.local`。來自`serviceA`虛擬節點的所有傳出流量都會傳送至名為 的虛擬服務`serviceb.apps.local`。雖然未涵蓋在本指南中，但您也可以指定將虛擬節點的存取日誌寫入其中的檔案路徑。
+ 建立名為 的額外虛擬服務`servicea.apps.local`，將所有流量直接傳送至`serviceA`虛擬節點。
+ 更新您在上一個步驟中建立的 `serviceB` 路由，將 75% 的流量傳送到 `serviceB` 虛擬節點，以及 25% 的流量傳送到 `serviceBv2` 虛擬節點。隨著時間的推移，您可以繼續修改權重，直到 `serviceBv2` 收到 100% 的流量為止。將所有流量傳送到 後`serviceBv2`，您可以關閉並停止`serviceB`虛擬節點和實際服務。當您更改權重時，您的程式碼不需要任何修改，因為 `serviceb.apps.local` 虛擬和實際服務名稱不會變更。記住，`serviceb.apps.local` 虛擬服務會將流量傳送至虛擬路由器，接著虛擬路由器會將流量路由至虛擬節點。虛擬節點的服務探索名稱可以隨時變更。

------
#### [ AWS 管理主控台 ]

1. 在左側導覽窗格中，選取 **Meshes (網格)**。

1. 選取您在上一個步驟中建立的 `apps` 網格。

1. 在左側導覽窗格中，選取 **Virtual nodes (虛擬節點)**。

1. 選擇 **Create virtual node (建立虛擬節點)**。

1. 對於 **Virtual node name (虛擬節點名稱)** 輸入 **serviceBv2**、對於 **Service discovery method (服務探索方法)** 選擇 **DNS**，然後對於 **DNS hostname (DNS 主機名稱)** 輸入 **servicebv2.apps.local**。

1. 針對**接聽程式組態**，選取**通訊協定**的 **http2**，然後**80**針對**連接埠**輸入 。

1. 選擇 **Create virtual node (建立虛擬節點)**。

1. 再次選擇 **Create virtual node (建立虛擬節點)**。輸入 **serviceA** 做為**虛擬節點名稱**。對於 **Service discovery method (服務探索方法)**，選擇 **DNS**，並針對 **DNS hostname (DNS 主機名稱)** 輸入 **servicea.apps.local**。

1. 在**新增後端**下**輸入虛擬服務名稱**，輸入 **serviceb.apps.local**。

1. 在**接聽程式組態**下，針對**通訊協定**選擇 **http2**，**80**針對**連接埠**輸入 ，然後選擇**建立虛擬節點**。

1. 在左側導覽窗格中，選取 **Virtual routers (虛擬路由器)**，然後從清單中選取 `serviceB` 虛擬路由器。

1. 在 **Routes (路由)** 下方，選取您在上一個步驟中建立的路由 (名為 `ServiceB`)，然後選擇 **Edit (編輯)**。

1. 在**目標**、**虛擬節點名稱**下，將 的**權重**值`serviceB`變更為 **75**。

1. 選擇**新增目標**，`serviceBv2`從下拉式清單中選擇，並將**權重**的值設定為 **25**。

1. 選擇**儲存**。

1. 在左側瀏覽窗格中，選取 **Virtual services (虛擬服務)**，然後選擇 **Create virtual service (建立虛擬服務)**。

1. **servicea.apps.local** 為**虛擬服務名稱**輸入 ，為**提供者**選取**虛擬節點**，`serviceA`為**虛擬節點**選取 ，然後選擇**建立虛擬服務。**

------
#### [ AWS CLI ]

1. 建立 `serviceBv2` 虛擬節點。

   1. 使用下列內容建立名為 `create-virtual-node-servicebv2.json` 的檔案：

      ```
      {
          "meshName": "apps",
          "spec": {
              "listeners": [
                  {
                      "portMapping": {
                          "port": 80,
                          "protocol": "http2"
                      }
                  }
              ],
              "serviceDiscovery": {
                  "dns": {
                      "hostname": "serviceBv2.apps.local"
                  }
              }
          },
          "virtualNodeName": "serviceBv2"
      }
      ```

   1. 建立虛擬節點。

      ```
      aws appmesh create-virtual-node --cli-input-json file://create-virtual-node-servicebv2.json
      ```

1. 建立 `serviceA` 虛擬節點。

   1. 使用下列內容建立名為 `create-virtual-node-servicea.json` 的檔案：

      ```
      {
         "meshName" : "apps",
         "spec" : {
            "backends" : [
               {
                  "virtualService" : {
                     "virtualServiceName" : "serviceb.apps.local"
                  }
               }
            ],
            "listeners" : [
               {
                  "portMapping" : {
                     "port" : 80,
                     "protocol" : "http2"
                  }
               }
            ],
            "serviceDiscovery" : {
               "dns" : {
                  "hostname" : "servicea.apps.local"
               }
            }
         },
         "virtualNodeName" : "serviceA"
      }
      ```

   1. 建立虛擬節點。

      ```
      aws appmesh create-virtual-node --cli-input-json file://create-virtual-node-servicea.json
      ```

1. 更新您在上一個步驟中建立的 `serviceb.apps.local` 虛擬服務，將其流量傳送至 `serviceB` 虛擬路由器。最初建立虛擬服務時，它不會傳送流量到任何地方，因為 `serviceB` 虛擬路由器尚未建立。

   1. 使用下列內容建立名為 `update-virtual-service.json` 的檔案：

      ```
      {
         "meshName" : "apps",
         "spec" : {
            "provider" : {
               "virtualRouter" : {
                  "virtualRouterName" : "serviceB"
               }
            }
         },
         "virtualServiceName" : "serviceb.apps.local"
      }
      ```

   1. 使用 [update-virtual-service](https://docs.aws.amazon.com/cli/latest/reference/appmesh/update-virtual-service.html) 命令更新虛擬服務。

      ```
      aws appmesh update-virtual-service --cli-input-json file://update-virtual-service.json
      ```

1. 更新您在上一個步驟中建立的 `serviceB` 路由。

   1. 使用下列內容建立名為 `update-route.json` 的檔案：

      ```
      {
         "meshName" : "apps",
         "routeName" : "serviceB",
         "spec" : {
            "http2Route" : {
               "action" : {
                  "weightedTargets" : [
                     {
                        "virtualNode" : "serviceB",
                        "weight" : 75
                     },
                     {
                        "virtualNode" : "serviceBv2",
                        "weight" : 25
                     }
                  ]
               },
               "match" : {
                  "prefix" : "/"
               }
            }
         },
         "virtualRouterName" : "serviceB"
      }
      ```

   1. 使用 [update-route](https://docs.aws.amazon.com/cli/latest/reference/appmesh/update-route.html) 命令更新路由。

      ```
      aws appmesh update-route --cli-input-json file://update-route.json
      ```

1. 建立 `serviceA` 虛擬服務。

   1. 使用下列內容建立名為 `create-virtual-servicea.json` 的檔案：

      ```
      {
         "meshName" : "apps",
         "spec" : {
            "provider" : {
               "virtualNode" : {
                  "virtualNodeName" : "serviceA"
               }
            }
         },
         "virtualServiceName" : "servicea.apps.local"
      }
      ```

   1. 建立虛擬服務。

      ```
      aws appmesh create-virtual-service --cli-input-json file://create-virtual-servicea.json
      ```

------

**網格摘要**  
在您建立服務網格之前，您有三個名稱為 `servicea.apps.local`、`serviceb.apps.local` 和 `servicebv2.apps.local` 的實際服務。除了實際服務以外，您目前擁有包含代表實際服務之下列資源的服務網格：
+ 兩個虛擬服務。代理會透過虛擬路由器將 `servicea.apps.local` 虛擬服務的所有流量傳送至 `serviceb.apps.local` 虛擬服務。
+ 名稱為 `serviceA`、`serviceB` 和 `serviceBv2` 的三個虛擬節點。Envoy 代理會使用針對虛擬節點設定的服務探索資訊，來查詢實際服務的 IP 地址。
+ 具有單一路由的虛擬路由器，其指示 Envoy 代理將 75% 的傳入流量路由到 `serviceB` 虛擬節點，將 25% 的流量路由到 `serviceBv2` 虛擬節點。

## 步驟 6：更新服務
<a name="update-services"></a>

在建立網格之後，您需要完成下列任務：
+ 授權您隨每個服務一起部署的 Envoy 代理，以讀取一或多個虛擬節點的組態。如需如何授權代理的詳細資訊，請參閱 [Envoy Proxy 授權](proxy-authorization.md)。
+ 若要更新現有的服務，請完成以下步驟。

**將 Amazon EC2 執行個體設定為虛擬節點成員**

1. 建立 IAM 角色。

   1. 使用下列內容建立名為 `ec2-trust-relationship.json` 的檔案。

------
#### [ JSON ]

****  

      ```
      {
        "Version":"2012-10-17",		 	 	 
        "Statement": [
          {
            "Effect": "Allow",
            "Principal": {
              "Service": "ec2.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
          }
        ]
      }
      ```

------

   1. 使用下列命令建立 IAM 角色。

      ```
      aws iam create-role --role-name mesh-virtual-node-service-b --assume-role-policy-document file://ec2-trust-relationship.json
      ```

1. 將 IAM 政策連接到角色，允許它從 Amazon ECR 讀取，並只讀取特定 App Mesh 虛擬節點的組態。

   1. 使用下列內容建立名為 `virtual-node-policy.json` 的檔案。`apps` 是您在 [步驟 1：建立網格和虛擬服務](#create-mesh-and-virtual-service) 建立的網格名稱，而 `serviceB` 是您在 [步驟 2：建立虛擬節點](#create-virtual-node) 建立的虛擬節點名稱。將 *111122223333* 取代為您的帳戶 ID，並將 *us-west-2* 取代為您建立網格的區域。

------
#### [ JSON ]

****  

      ```
      {
          "Version":"2012-10-17",		 	 	 
          "Statement": [
              {
                  "Effect": "Allow",
                  "Action": "appmesh:StreamAggregatedResources",
                  "Resource": [
                      "arn:aws:appmesh:us-west-2:111122223333:mesh/apps/virtualNode/serviceB"
                  ]
              }
          ]
      }
      ```

------

   1. 使用下列命令建立政策。

      ```
      aws iam create-policy --policy-name virtual-node-policy --policy-document file://virtual-node-policy.json
      ```

   1. 將您在上一個步驟中建立的政策連接至角色，讓角色只能從 App Mesh 讀取`serviceB`虛擬節點的組態。

      ```
      aws iam attach-role-policy --policy-arn arn:aws:iam::111122223333:policy/virtual-node-policy --role-name mesh-virtual-node-service-b
      ```

   1. 將 `AmazonEC2ContainerRegistryReadOnly`受管政策連接到角色，以便從 Amazon ECR 提取 Envoy 容器映像。

      ```
      aws iam attach-role-policy --policy-arn arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly --role-name mesh-virtual-node-service-b
      ```

1. 使用您建立[的 IAM 角色啟動 Amazon EC2 執行個體](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html#launch-instance-with-role)。

1. 透過 SSH 連線至您的執行個體。

1. 根據您的作業系統文件，在您的執行個體 AWS CLI 上安裝 Docker 和 。

1. 在您希望 Docker 用戶端從中提取映像的區域中，向 Envoy Amazon ECR 儲存庫進行身分驗證。
   + 除了 `me-south-1`、`ap-east-1`、、`il-central-1`、 `ap-southeast-3` `eu-south-1`和 以外的所有區域`af-south-1`。您可以將 *us-west-2* 取代為任何[支援的 區域](https://docs.aws.amazon.com/general/latest/gr/appmesh.html)，但 `me-south-1`、`ap-east-1`、`ap-southeast-3``eu-south-1`、、 `il-central-1`和 除外`af-south-1`。

     ```
     $aws ecr get-login-password \
         --region us-west-2 \
     | docker login \
         --username AWS \
         --password-stdin 840364872350.dkr.ecr.us-west-2.amazonaws.com
     ```
   + `me-south-1` 區域

     ```
     $aws ecr get-login-password \
         --region me-south-1 \
     | docker login \
         --username AWS \
         --password-stdin 772975370895.dkr.ecr.me-south-1.amazonaws.com
     ```
   + `ap-east-1` 區域

     ```
     $aws ecr get-login-password \
         --region ap-east-1 \
     | docker login \
         --username AWS \
         --password-stdin 856666278305.dkr.ecr.ap-east-1.amazonaws.com
     ```

1. 執行下列其中一個命令來啟動執行個體上的 App Mesh Envoy 容器，視您要從哪個區域提取映像而定。*apps* 和 *serviceB* 值是案例中定義的網格和虛擬節點名稱。此資訊會告知代理程式要從 App Mesh 讀取哪些虛擬節點組態。若要完成案例，您也需要為託管 `serviceBv2`和`serviceA`虛擬節點所代表服務的 Amazon EC2 執行個體完成這些步驟。對於您自己的應用程式，將這些值取代為您自己的值。
   + 除了 `me-south-1`、`ap-east-1`、、`il-central-1`、 `ap-southeast-3` `eu-south-1`和 以外的所有區域`af-south-1`。您可以將*區域碼*取代為 `me-south-1`、`ap-east-1`、、`il-central-1`、 `ap-southeast-3` `eu-south-1`和 `af-south-1`區域以外的任何[支援](https://docs.aws.amazon.com/general/latest/gr/appmesh.html)區域。您可以將 `1337` 換成 `0` 到 `2147483647` 之間的任何值。

     ```
     sudo docker run --detach --env APPMESH_RESOURCE_ARN=mesh/apps/virtualNode/serviceB  \
     -u 1337 --network host 840364872350.dkr.ecr.region-code.amazonaws.com/aws-appmesh-envoy:v1.34.13.0-prod
     ```
   + `me-south-1` 區域。您可以將 `1337` 換成 `0` 到 `2147483647` 之間的任何值。

     ```
     sudo docker run --detach --env APPMESH_RESOURCE_ARN=mesh/apps/virtualNode/serviceB  \
     -u 1337 --network host 772975370895.dkr.ecr.me-south-1.amazonaws.com/aws-appmesh-envoy:v1.34.13.0-prod
     ```
   + `ap-east-1` 區域。您可以將 `1337` 換成 `0` 到 `2147483647` 之間的任何值。

     ```
     sudo docker run --detach --env APPMESH_RESOURCE_ARN=mesh/apps/virtualNode/serviceB  \
     -u 1337 --network host 856666278305.dkr.ecr.ap-east-1.amazonaws.com/aws-appmesh-envoy:v1.34.13.0-prod
     ```
**注意**  
`APPMESH_RESOURCE_ARN` 屬性需要版本 `1.15.0`或更新版本的 Envoy 映像。如需詳細資訊，請參閱[Envoy 影像](envoy.md)。
**重要**  
只有 v1.9.0.0 版或更新版本支援與 App Mesh 搭配使用。

1. 請在下方選取 `Show more`。使用下列命令在您的執行個體上建立名為 `envoy-networking.sh` 的檔案。將 *8000* 取代為您的應用程式程式碼用於傳入流量的連接埠。您可以變更 `APPMESH_IGNORE_UID` 的值，但值必須與您在上一個步驟中指定的值相同；例如 `1337`。如有必要，您可以新增其他地址到 `APPMESH_EGRESS_IGNORED_IP`。請勿修改任何其他行。

   ```
   #!/bin/bash -e
   
   #
   # Start of configurable options
   #
   
   
   #APPMESH_START_ENABLED="0"
   APPMESH_IGNORE_UID="1337"
   APPMESH_APP_PORTS="8000"
   APPMESH_ENVOY_EGRESS_PORT="15001"
   APPMESH_ENVOY_INGRESS_PORT="15000"
   APPMESH_EGRESS_IGNORED_IP="169.254.169.254,169.254.170.2" 
   
   # Enable routing on the application start.
   [ -z "$APPMESH_START_ENABLED" ] && APPMESH_START_ENABLED="0"
   
   # Enable IPv6.
   [ -z "$APPMESH_ENABLE_IPV6" ] && APPMESH_ENABLE_IPV6="0"
   
   # Egress traffic from the processess owned by the following UID/GID will be ignored.
   if [ -z "$APPMESH_IGNORE_UID" ] && [ -z "$APPMESH_IGNORE_GID" ]; then
       echo "Variables APPMESH_IGNORE_UID and/or APPMESH_IGNORE_GID must be set."
       echo "Envoy must run under those IDs to be able to properly route it's egress traffic."
       exit 1
   fi
   
   # Port numbers Application and Envoy are listening on.
   if [ -z "$APPMESH_ENVOY_EGRESS_PORT" ]; then
       echo "APPMESH_ENVOY_EGRESS_PORT must be defined to forward traffic from the application to the proxy."
       exit 1
   fi
   
   # If an app port was specified, then we also need to enforce the proxies ingress port so we know where to forward traffic.
   if [ ! -z "$APPMESH_APP_PORTS" ] && [ -z "$APPMESH_ENVOY_INGRESS_PORT" ]; then
       echo "APPMESH_ENVOY_INGRESS_PORT must be defined to forward traffic from the APPMESH_APP_PORTS to the proxy."
       exit 1
   fi
   
   # Comma separated list of ports for which egress traffic will be ignored, we always refuse to route SSH traffic.
   if [ -z "$APPMESH_EGRESS_IGNORED_PORTS" ]; then
       APPMESH_EGRESS_IGNORED_PORTS="22"
   else
       APPMESH_EGRESS_IGNORED_PORTS="$APPMESH_EGRESS_IGNORED_PORTS,22"
   fi
   
   #
   # End of configurable options
   #
   
   function initialize() {
       echo "=== Initializing ==="
       if [ ! -z "$APPMESH_APP_PORTS" ]; then
           iptables -t nat -N APPMESH_INGRESS
           if [ "$APPMESH_ENABLE_IPV6" == "1" ]; then
               ip6tables -t nat -N APPMESH_INGRESS
           fi
       fi
       iptables -t nat -N APPMESH_EGRESS
       if [ "$APPMESH_ENABLE_IPV6" == "1" ]; then
           ip6tables -t nat -N APPMESH_EGRESS
       fi
   }
   
   function enable_egress_routing() {
       # Stuff to ignore
       [ ! -z "$APPMESH_IGNORE_UID" ] && \
           iptables -t nat -A APPMESH_EGRESS \
           -m owner --uid-owner $APPMESH_IGNORE_UID \
           -j RETURN
   
       [ ! -z "$APPMESH_IGNORE_GID" ] && \
           iptables -t nat -A APPMESH_EGRESS \
           -m owner --gid-owner $APPMESH_IGNORE_GID \
           -j RETURN
   
       [ ! -z "$APPMESH_EGRESS_IGNORED_PORTS" ] && \
           for IGNORED_PORT in $(echo "$APPMESH_EGRESS_IGNORED_PORTS" | tr "," "\n"); do
             iptables -t nat -A APPMESH_EGRESS \
             -p tcp \
             -m multiport --dports "$IGNORED_PORT" \
             -j RETURN
           done
   
       if [ "$APPMESH_ENABLE_IPV6" == "1" ]; then
         # Stuff to ignore ipv6
         [ ! -z "$APPMESH_IGNORE_UID" ] && \
             ip6tables -t nat -A APPMESH_EGRESS \
             -m owner --uid-owner $APPMESH_IGNORE_UID \
             -j RETURN
   
         [ ! -z "$APPMESH_IGNORE_GID" ] && \
             ip6tables -t nat -A APPMESH_EGRESS \
             -m owner --gid-owner $APPMESH_IGNORE_GID \
             -j RETURN
   
         [ ! -z "$APPMESH_EGRESS_IGNORED_PORTS" ] && \
           for IGNORED_PORT in $(echo "$APPMESH_EGRESS_IGNORED_PORTS" | tr "," "\n"); do
             ip6tables -t nat -A APPMESH_EGRESS \
             -p tcp \
             -m multiport --dports "$IGNORED_PORT" \
             -j RETURN
           done
       fi
   
       # The list can contain both IPv4 and IPv6 addresses. We will loop over this list
       # to add every IPv4 address into `iptables` and every IPv6 address into `ip6tables`.
       [ ! -z "$APPMESH_EGRESS_IGNORED_IP" ] && \
           for IP_ADDR in $(echo "$APPMESH_EGRESS_IGNORED_IP" | tr "," "\n"); do
               if [[ $IP_ADDR =~ .*:.* ]]
               then
                   [ "$APPMESH_ENABLE_IPV6" == "1" ] && \
                       ip6tables -t nat -A APPMESH_EGRESS \
                           -p tcp \
                           -d "$IP_ADDR" \
                           -j RETURN
               else
                   iptables -t nat -A APPMESH_EGRESS \
                       -p tcp \
                       -d "$IP_ADDR" \
                       -j RETURN
               fi
           done
   
       # Redirect everything that is not ignored
       iptables -t nat -A APPMESH_EGRESS \
           -p tcp \
           -j REDIRECT --to $APPMESH_ENVOY_EGRESS_PORT
   
       # Apply APPMESH_EGRESS chain to non local traffic
       iptables -t nat -A OUTPUT \
           -p tcp \
           -m addrtype ! --dst-type LOCAL \
           -j APPMESH_EGRESS
   
       if [ "$APPMESH_ENABLE_IPV6" == "1" ]; then
           # Redirect everything that is not ignored ipv6
           ip6tables -t nat -A APPMESH_EGRESS \
               -p tcp \
               -j REDIRECT --to $APPMESH_ENVOY_EGRESS_PORT
           # Apply APPMESH_EGRESS chain to non local traffic ipv6
           ip6tables -t nat -A OUTPUT \
               -p tcp \
               -m addrtype ! --dst-type LOCAL \
               -j APPMESH_EGRESS
       fi
   
   }
   
   function enable_ingress_redirect_routing() {
       # Route everything arriving at the application port to Envoy
       iptables -t nat -A APPMESH_INGRESS \
           -p tcp \
           -m multiport --dports "$APPMESH_APP_PORTS" \
           -j REDIRECT --to-port "$APPMESH_ENVOY_INGRESS_PORT"
   
       # Apply AppMesh ingress chain to everything non-local
       iptables -t nat -A PREROUTING \
           -p tcp \
           -m addrtype ! --src-type LOCAL \
           -j APPMESH_INGRESS
   
       if [ "$APPMESH_ENABLE_IPV6" == "1" ]; then
           # Route everything arriving at the application port to Envoy ipv6
           ip6tables -t nat -A APPMESH_INGRESS \
               -p tcp \
               -m multiport --dports "$APPMESH_APP_PORTS" \
               -j REDIRECT --to-port "$APPMESH_ENVOY_INGRESS_PORT"
   
           # Apply AppMesh ingress chain to everything non-local ipv6
           ip6tables -t nat -A PREROUTING \
               -p tcp \
               -m addrtype ! --src-type LOCAL \
               -j APPMESH_INGRESS
       fi
   }
   
   function enable_routing() {
       echo "=== Enabling routing ==="
       enable_egress_routing
       if [ ! -z "$APPMESH_APP_PORTS" ]; then
           enable_ingress_redirect_routing
       fi
   }
   
   function disable_routing() {
       echo "=== Disabling routing ==="
       iptables -t nat -F APPMESH_INGRESS
       iptables -t nat -F APPMESH_EGRESS
   
       if [ "$APPMESH_ENABLE_IPV6" == "1" ]; then
           ip6tables -t nat -F APPMESH_INGRESS
           ip6tables -t nat -F APPMESH_EGRESS
       fi
   }
   
   function dump_status() {
       echo "=== iptables FORWARD table ==="
       iptables -L -v -n
       echo "=== iptables NAT table ==="
       iptables -t nat -L -v -n
   
       if [ "$APPMESH_ENABLE_IPV6" == "1" ]; then
           echo "=== ip6tables FORWARD table ==="
           ip6tables -L -v -n
           echo "=== ip6tables NAT table ==="
           ip6tables -t nat -L -v -n
       fi
   }
   
   function clean_up() {
       disable_routing
       ruleNum=$(iptables -L PREROUTING -t nat --line-numbers | grep APPMESH_INGRESS | cut -d " " -f 1)
       iptables -t nat -D PREROUTING $ruleNum
   
       ruleNum=$(iptables -L OUTPUT -t nat --line-numbers | grep APPMESH_EGRESS | cut -d " " -f 1)
       iptables -t nat -D OUTPUT $ruleNum
   
       iptables -t nat -X APPMESH_INGRESS
       iptables -t nat -X APPMESH_EGRESS
   
       if [ "$APPMESH_ENABLE_IPV6" == "1" ]; then
           ruleNum=$(ip6tables -L PREROUTING -t nat --line-numbers | grep APPMESH_INGRESS | cut -d " " -f 1)
           ip6tables -t nat -D PREROUTING $ruleNum
   
           ruleNum=$(ip6tables -L OUTPUT -t nat --line-numbers | grep APPMESH_EGRESS | cut -d " " -f 1)
           ip6tables -t nat -D OUTPUT $ruleNum
   
           ip6tables -t nat -X APPMESH_INGRESS
           ip6tables -t nat -X APPMESH_EGRESS
       fi
   }
   
   function main_loop() {
       echo "=== Entering main loop ==="
       while read -p '> ' cmd; do
           case "$cmd" in
               "quit")
                   clean_up
                   break
                   ;;
               "status")
                   dump_status
                   ;;
               "enable")
                   enable_routing
                   ;;
               "disable")
                   disable_routing
                   ;;
               *)
                   echo "Available commands: quit, status, enable, disable"
                   ;;
           esac
       done
   }
   
   function print_config() {
       echo "=== Input configuration ==="
       env | grep APPMESH_ || true
   }
   
   print_config
   
   initialize
   
   if [ "$APPMESH_START_ENABLED" == "1" ]; then
       enable_routing
   fi
   
   main_loop
   ```

1. 若要設定 `iptables` 規則以將應用程式流量路由至 Envoy 代理，請執行您在上一個步驟中建立的指令碼。

   ```
   sudo ./envoy-networking.sh
   ```

1. 啟動您的虛擬節點應用程式程式碼。

**注意**  
如需 App Mesh 的更多範例和逐步解說，請參閱 [App Mesh 範例儲存庫](https://github.com/aws/aws-app-mesh-examples)。