

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# App Mesh 应用程序入门
<a name="getting-started"></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)。

您可以将 App Mesh 与部署到亚马逊 ECS、Kubernetes（部署到自己的亚马逊 EC2 实例或在 Amazon EKS 上运行）和亚马逊 EC2 的应用程序一起使用。要开始使用 App Mesh，请选择一个已部署应用程序的服务，然后将其与 App Mesh 一起使用。完成其中一个入门指南后，您随时可以让其他服务中的应用程序也能与 App Mesh 配合使用。

**Topics**
+ [开始使用 AWS App Mesh 和 Amazon ECS](getting-started-ecs.md)
+ [入门 AWS App Mesh 和 Kubernetes](getting-started-kubernetes.md)
+ [开始使用 AWS App Mesh 和 Amazon EC2](getting-started-ec2.md)
+ [App Mesh 示例](examples.md)

# 开始使用 AWS App Mesh 和 Amazon ECS
<a name="getting-started-ecs"></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 ECS 上运行的实际服务。本教程介绍了多种 App Mesh 资源类型的基本功能。

## 场景
<a name="scenario"></a>

为了说明如何配合使用 App Mesh，假定您有一个具有以下功能的应用程序：
+ 由名为 `serviceA` 和 `serviceB` 的两项服务组成。
+ 这两项服务均注册到名为 `apps.local` 的命名空间。
+ `ServiceA` 通过 HTTP/2 和端口 80 与 `serviceB` 通信。
+  您已部署 `serviceB` 的版本 2，并采用名称 `serviceBv2` 在 `apps.local` 命名空间中注册了该服务。

您的要求如下：
+ 您想将 75% 的流量从发送`serviceA`到`serviceB`，将 25% 的流量发送到`serviceBv2`第一个。通过仅向发送25％的流量`serviceBv2`，您就可以在发送来自的100％的流量之前验证它是否没有错误`serviceA`。
+ 您希望能够轻松调整流量权重，以便一旦证明 `serviceBv2` 可靠便可将 100% 的流量发送到该服务。将所有流量发送到 `serviceBv2` 后，您希望弃用 `serviceB`。
+ 您不想为了满足之前的要求而更改实际服务的任何现有应用程序代码或服务发现注册。

为了满足您的要求，您决定创建包含虚拟服务、虚拟节点、虚拟路由器和路由的 App Mesh 服务网格。实施您的网格后，更新使用 Envoy 代理的服务。更新后，您的服务将通过 Envoy 代理相互通信，而不是直接相互通信。

## 先决条件
<a name="prerequisites"></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)。
+ 已了解 App Mesh 概念。有关更多信息，请参阅 [什么是 AWS App Mesh？](what-is-app-mesh.md)。
+ 对 Amazon ECSs 概念的现有理解。有关更多信息，请参阅《Amazon Elastic Container Service 开发人员指南》中的 [Amazon ECS 的定义](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/Welcome.html)。
+ App Mesh 支持在 DNS 中注册的 Linux 服务 AWS Cloud Map，或者两者兼而有之。要使用此入门指南，我们建议您提供三项已注册到 DNS 的现有服务。该主题的剩余步骤假定现有服务命名为 `serviceA`、`serviceB` 和 `serviceBv2`，并且可以在名为 `apps.local` 的命名空间中发现所有服务。

  即使服务不存在，您也可以创建服务网格及其资源，但在部署实际服务之前，您无法使用网格。有关 Amazon ECS 上服务发现的更多信息，请参阅[服务发现](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/service-discovery.html)。要使用服务发现创建 Amazon ECS 服务，请参阅[教程：使用服务发现创建服务](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/create-service-discovery.html)。如果您尚未运行服务，则可以[创建带有服务发现功能的 Amazon ECS 服务](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/create-service-discovery.html)。

## 步骤 1：创建网格和虚拟服务
<a name="create-mesh-and-virtual-service2"></a>

服务网格是一种用于驻留在其内的服务之间的网络流量的逻辑边界。有关更多信息，请参阅 [服务网格](meshes.md)。虚拟服务是实际服务的抽象。有关更多信息，请参阅 [虚拟服务](virtual_services.md)。

创建以下 资源：
+ 名为 `apps` 的网格，因为此场景中的所有服务均注册到 `apps.local` 命名空间。
+ 名为 `serviceb.apps.local` 的虚拟服务，因为虚拟服务表示可以使用该名称发现的服务，并且您不希望更改代码以引用其他名称。稍后的步骤中将添加名为 `servicea.apps.local` 的虚拟服务。

您可以使用或 1.18.116 AWS 管理控制台 或更高 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. 在开始时打开 App Mesh 控制台的首次运行向导[https://console.aws.amazon.com/appmesh/。](https://console.aws.amazon.com/appmesh/get-started)

1. 对于**网格名称**，输入 **apps**。

1. 对于**虚拟服务名称**，输入 **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-node2"></a>

虚拟节点充当实际服务的逻辑指针。有关更多信息，请参阅 [虚拟节点](virtual_nodes.md)。

创建名为 `serviceB` 的虚拟节点，因为某个虚拟节点表示名为 `serviceB` 的实际服务。可使用主机名 `serviceb.apps.local`，通过 `DNS` 发现虚拟节点所表示的实际服务。或者，您可以使用发现实际的服务。 AWS Cloud Map虚拟节点将采用 HTTP/2 协议在端口 80 上侦听流量。此外，还支持其他协议和运行状况检查。您将在后面的步骤中为 `serviceBv2` 和 `serviceA` 创建虚拟节点。

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

1. 对于**虚拟节点名称**，输入 **serviceB**。

1. 对于**服务发现方法**，选择 **DNS**，并为**DNS 主机名**输入 **serviceb.apps.local**。

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](routes.md)。

创建以下 资源：
+ 名为 `serviceB` 的虚拟路由器，因为 `serviceB.apps.local` 虚拟服务不会启动与任何其他服务的出站通信。请记住，您之前创建的虚拟服务是实际 `serviceb.apps.local` 服务的抽象。虚拟服务将流量发送到虚拟路由器。虚拟路由器采用 HTTP/2 协议在端口 80 上侦听流量。此外，还支持其他协议。
+ 名为 `serviceB` 的路由。它将 100% 的流量路由到`serviceB`虚拟节点。添加 `serviceBv2` 虚拟节点后，在稍后的步骤中出现权重。虽然本指南中未作介绍，但您可以为路由添加额外的筛选条件，并添加重试策略，从而使 Envoy 代理在遇到通信问题时会多次尝试将流量发送到虚拟节点。

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

1. 对于**虚拟路由器名称**，输入 **serviceB**。

1. 在**侦听器配置**下，为**协议**选择 **http2**，并为**端口**指定 **80**。

1. 对于**路由名称**，输入 **serviceB**。

1. 对于**路由类型**，选择 **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 管理控制台 ]

如果需要对任何部分进行任何更改，请选择**编辑**。在您对设置感到满意后，选择**创建网格**。

**状态**屏幕将显示已创建的所有网格资源。您可以通过选择**查看网格**来在控制台中查看创建的资源。

------
#### [ 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. 在左侧导航窗格中，选择**网格**。

1. 选择在上一步中创建的 `apps` 网格。

1. 在左侧导航窗格中，选择**虚拟节点**。

1. 选择**创建虚拟节点**。

1. 为**虚拟节点名称**输入 **serviceBv2**，为**服务发现方法**选择 **DNS**，并为 **DNS 主机名**输入 **servicebv2.apps.local**。

1. 对于**侦听器配置**，为**协议**选择 **http2**，并在**端口**中，输入 **80**。

1. 选择**创建虚拟节点**。

1. 再次选择**创建虚拟节点**。对于**虚拟节点名称**，输入 **serviceA**。对于**服务发现方法**，选择 **DNS**，并为 **DNS 主机名**输入 **servicea.apps.local**。

1. 在**新后端**下的**输入虚拟服务名称**中，输入 **serviceb.apps.local**。

1. 在**侦听器配置**下，为**协议**选择 **http2**，并在**端口**中输入 **80**，然后选择**创建虚拟节点**。

1. 在左侧导航窗格中，选择**虚拟路由器**，然后从列表中选择 `serviceB` 虚拟路由器。

1. 在**路由**下，选择在上一步中创建的名为 `ServiceB` 的路由，然后选择**编辑**。

1. 在**目标**、**虚拟节点名称**下，将 `serviceB` 的**权重**值更改为 **75**。

1. 选择**添加目标**，从下拉列表中选择 `serviceBv2`，然后将**权重**值设置为 **25**。

1. 选择**保存**。

1. 在左侧导航窗格中，选择**虚拟服务**，然后选择**创建虚拟服务**。

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>

创建网格后，您需要完成以下任务：
+ 授予随每项 Amazon ECS 任务服务部署的 Envoy 代理读取一个或多个虚拟节点配置的权限。有关如何向代理授权的更多信息，请参阅[代理授权](https://docs.aws.amazon.com/app-mesh/latest/userguide/proxy-authorization.html)。
+ 更新每个现有 Amazon ECS 任务定义服务，以使用 Envoy 代理。

**凭据**  
Envoy 容器需要 AWS Identity and Access Management 凭据才能对发送到 App Mesh 服务的请求进行签名。对于使用 Amazon EC2 启动类型部署的 Amazon ECS 任务，凭证可以来自[实例角色](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/instance_IAM_role.html)或[任务 IAM 角色](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html)。在 Linux 容器上使用 Fargate 部署的 Amazon ECS 任务无法访问提供实例 IAM 配置凭证的 Amazon EC2 元数据服务器。要提供凭证，您必须将 IAM 任务角色附加到在 Linux 容器类型上使用 Fargate 启动类型部署的任何任务。

如果任务以 Amazon EC2 启动类型部署，并且无法访问 Amazon EC2 元数据服务器（如 [IAM 任务角色中的*重要*注释中所述），则还必须为该任务附加任务](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html) IAM 角色。您分配给实例或任务的角色必须附加一个 IAM 策略，如[代理授权](https://docs.aws.amazon.com/app-mesh/latest/userguide/proxy-authorization.html)中所述。



**要更新任务定义，请使用 AWS CLI**  
你使用 Amazon ECS AWS CLI 命令[https://docs.aws.amazon.com/cli/latest/reference/ecs/register-task-definition.html](https://docs.aws.amazon.com/cli/latest/reference/ecs/register-task-definition.html)。下面的示例任务定义显示了如何为您的服务配置 App Mesh。

**注意**  
无法通过控制台为 Amazon ECS 配置 App Mesh。

### 任务定义 json
<a name="getting-started-ecs-json"></a>

**代理配置**  
要将您的 Amazon ECS 服务配置为使用 App Mesh，您的服务的任务定义必须具有以下代理配置部分。将代理配置 `type` 设置为 `APPMESH`，并 `containerName` 配置为 `envoy`。相应地设置以下属性值。

`IgnoredUID`  
Envoy 代理不会路由来自使用此用户 ID 的进程的流量。您可以为此属性值选择所需的任何用户 ID，但此 ID 必须与任务定义中的 Envoy 容器的 `user` ID 相同。此匹配允许 Envoy 忽略其自己的流量，而无需使用代理。出于历史原因，我们的示例使用 `1337`。

`ProxyIngressPort`  
这是 Envoy 代理容器的入站端口。将此值设置为 `15000`。

`ProxyEgressPort`  
这是 Envoy 代理容器的出口端口。将此值设置为 `15001`。

`AppPorts`  
指定您的应用程序容器监听的所有入站端口。在此示例中，应用程序容器在端口 `9080` 上侦听。您指定的端口必须与虚拟节点侦听器上配置的端口匹配。

`EgressIgnoredIPs`  
Envoy 不会将流量代理至这些 IP 地址。将此值设置为 `169.254.170.2,169.254.169.254`，这会忽略 Amazon EC2 元数据服务器和 Amazon ECS 任务元数据端点。元数据端点为任务凭证提供 IAM 角色。您可以添加其他地址。

`EgressIgnoredPorts`  
您可以添加以逗号分隔的端口列表。Envoy 不会将流量转发至这些端口。即使您没有列出任何端口，端口 22 也会被忽略。  
可以忽略的最大出站端口数为 15。

```
"proxyConfiguration": {
	"type": "APPMESH",
	"containerName": "envoy",
	"properties": [{
			"name": "IgnoredUID",
			"value": "1337"
		},
		{
			"name": "ProxyIngressPort",
			"value": "15000"
		},
		{
			"name": "ProxyEgressPort",
			"value": "15001"
		},
		{
			"name": "AppPorts",
			"value": "9080"
		},
		{
			"name": "EgressIgnoredIPs",
			"value": "169.254.170.2,169.254.169.254"
		},
		{
			"name": "EgressIgnoredPorts",
			"value": "22"
		}
	]
}
```

**应用程序容器 Envoy 依赖项**  
您的任务定义中的应用程序容器必须等待 Envoy 代理来引导和启动之后才能启动。为了确保这种情况发生，你需要在每个应用程序容器定义中设置一个`dependsOn`部分，等待 Envoy 容器报告为`HEALTHY`。以下代码显示了包含此依赖项的应用程序容器定义示例。以下示例中的所有属性都是必需的。有些属性值也是必填的，但有些则是必填的*replaceable*。

```
{
	"name": "appName",
	"image": "appImage",
	"portMappings": [{
		"containerPort": 9080,
		"hostPort": 9080,
		"protocol": "tcp"
	}],
	"essential": true,
	"dependsOn": [{
		"containerName": "envoy",
		"condition": "HEALTHY"
	}]
}
```

**Envoy 容器定义**

您的 Amazon ECS 任务定义必须包含 App Mesh Envoy 容器镜像。

所有[支持的](https://docs.aws.amazon.com/general/latest/gr/appmesh.html)区域都可以*Region-code*替换为`me-south-1`、、、`ap-east-1``ap-southeast-3``eu-south-1``il-central-1`、和以外的任何区域`af-south-1`。  
标准  

```
840364872350.dkr.ecr.region-code.amazonaws.com/aws-appmesh-envoy:v1.34.13.0-prod
```
符合 FIPS 标准  

```
840364872350.dkr.ecr.region-code.amazonaws.com/aws-appmesh-envoy:v1.34.13.0-prod-fips
```

`me-south-1`  
标准  

```
772975370895.dkr.ecr.me-south-1.amazonaws.com/aws-appmesh-envoy:v1.34.13.0-prod
```

`ap-east-1`  
标准  

```
856666278305.dkr.ecr.ap-east-1.amazonaws.com/aws-appmesh-envoy:v1.34.13.0-prod
```

`ap-southeast-3`  
标准  

```
909464085924.dkr.ecr.ap-southeast-3.amazonaws.com/aws-appmesh-envoy:v1.34.13.0-prod
```

`eu-south-1`  
标准  

```
422531588944.dkr.ecr.eu-south-1.amazonaws.com/aws-appmesh-envoy:v1.34.13.0-prod
```

`il-central-1`  
标准  

```
564877687649.dkr.ecr.il-central-1.amazonaws.com/aws-appmesh-envoy:v1.34.13.0-prod
```

`af-south-1`  
标准  

```
924023996002.dkr.ecr.af-south-1.amazonaws.com/aws-appmesh-envoy:v1.34.13.0-prod
```

`Public repository`  
标准  

```
public.ecr.aws/appmesh/aws-appmesh-envoy:v1.34.13.0-prod
```
符合 FIPS 标准  

```
public.ecr.aws/appmesh/aws-appmesh-envoy:v1.34.13.0-prod-fips
```

**重要**  
仅支持将版本 v1.9.0.0-prod 或更高版本与 App Mesh 一起使用。

在 Envoy 项目团队合并支持 App Mesh 的更改之前，您必须使用 App Mesh Envoy 容器镜像。有关更多详细信息，请参阅[GitHub 路线图问题](https://github.com/aws/aws-app-mesh-roadmap/issues/10)。

以下示例中的所有属性都是必需的。有些属性值也是必填的，但有些则是必填的*replaceable*。

**注意**  
Envoy 容器定义必须标记为 `essential`。
我们建议为 Envoy 容器分配 `512` 个 CPU 单元及至少 `64` MiB 的内存。在 Fargate 上，您可以设置的最低内存为 `1024`MiB。
Amazon ECS 服务的虚拟节点名称必须设置为 `APPMESH_RESOURCE_ARN` 属性的值。此属性需要版本`1.15.0`或更高版本的 Envoy 镜像。有关更多信息，请参阅 [Envoy 镜像](envoy.md)。
`user` 设置的值必须与任务定义代理配置中的 `IgnoredUID` 值匹配。在此示例中，我们使用的是 `1337`。
此处显示的运行状况检查等待 Envoy 容器正确引导，然后再向 Amazon ECS报告其运行状况良好且已准备好启动应用程序容器。
默认情况下，当 Envoy 在指标和跟踪中引用自身时，App Mesh 使用您在 `APPMESH_RESOURCE_ARN` 中指定的资源的名称。您可以通过使用自己的名称设置 `APPMESH_RESOURCE_CLUSTER` 环境变量来覆盖此行为。此属性需要版本 `1.15.0` 或更高版本的 Envoy 镜像。有关更多信息，请参阅 [Envoy 镜像](envoy.md)。

以下代码显示 Envoy 容器定义示例。

```
{
	"name": "envoy",
	"image": "840364872350.dkr.ecr.us-west-2.amazonaws.com/aws-appmesh-envoy:v1.34.13.0-prod",
	"essential": true,
	"environment": [{
		"name": "APPMESH_RESOURCE_ARN",
		"value": "arn:aws:appmesh:us-west-2:111122223333:mesh/apps/virtualNode/serviceB"
	}],
	"healthCheck": {
		"command": [
			"CMD-SHELL",
			"curl -s http://localhost:9901/server_info | grep state | grep -q LIVE"
		],
		"startPeriod": 10,
		"interval": 5,
		"timeout": 2,
		"retries": 3
	},
	"user": "1337"
}
```

**示例任务定义**  
以下示例 Amazon ECS 任务定义显示如何将上述示例合并到 `taskB` 的任务定义中。本文分别提供了使用或不使用 AWS X-Ray为两种 Amazon ECS 启动类型创建任务的示例。根据需要更改这些*replaceable*值，以便为名为的任务`taskBv2`和场景`taskA`中的任务创建任务定义。用您的网格名称和虚拟节点名称替换 `APPMESH_RESOURCE_ARN` 值，并用您的应用程序侦听的端口列表替换代理配置 `AppPorts` 值。默认情况下，当 Envoy 在指标和跟踪中引用自身时，App Mesh 使用您在 `APPMESH_RESOURCE_ARN` 中指定的资源的名称。您可以通过使用自己的名称设置 `APPMESH_RESOURCE_CLUSTER` 环境变量来覆盖此行为。以下示例中的所有属性都是必需的。有些属性值也是必填的，但有些则是必填的*replaceable*。

如果按照“凭证”部分中所述运行 Amazon ECS 任务，那么需要将[现有任务 IAM 角色](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html)添加到示例中。

**重要**  
Fargate 必须使用大于 1024 的端口值。

**Example 亚马逊 ECS 任务定义的 JSON - Linux 容器上的 Fargate**  

```
{
   
   "family" : "taskB",
   "memory" : "1024",
   "cpu" : "0.5 vCPU",
   "proxyConfiguration" : {
      "containerName" : "envoy",
      "properties" : [
         {
            "name" : "ProxyIngressPort",
            "value" : "15000"
         },
         {
            "name" : "AppPorts",
            "value" : "9080"
         },
         {
            "name" : "EgressIgnoredIPs",
            "value" : "169.254.170.2,169.254.169.254"
         },
         {
            "name": "EgressIgnoredPorts",
            "value": "22"
         },
         {
            "name" : "IgnoredUID",
            "value" : "1337"
         },
         {
            "name" : "ProxyEgressPort",
            "value" : "15001"
         }
      ],
      "type" : "APPMESH"
   },
   "containerDefinitions" : [
      {
         "name" : "appName",
         "image" : "appImage",
         "portMappings" : [
            {
               "containerPort" : 9080,
               "protocol" : "tcp"
            }
         ],
         "essential" : true,
         "dependsOn" : [
            {
               "containerName" : "envoy",
               "condition" : "HEALTHY"
            }
         ]
      },
      {         
         "name" : "envoy",
         "image" : "840364872350.dkr.ecr.us-west-2.amazonaws.com/aws-appmesh-envoy:v1.34.13.0-prod",
         "essential" : true,
         "environment" : [
            {
               "name" : "APPMESH_VIRTUAL_NODE_NAME",
               "value" : "mesh/apps/virtualNode/serviceB"
            }
         ],
         "healthCheck" : {
            "command" : [
               "CMD-SHELL",
               "curl -s http://localhost:9901/server_info | grep state | grep -q LIVE"
            ],
            "interval" : 5,
            "retries" : 3,
            "startPeriod" : 10,
            "timeout" : 2
         },
         "memory" : 500,
         "user" : "1337"
      }
   ],
   "requiresCompatibilities" : [ "FARGATE" ],
   "taskRoleArn" : "arn:aws:iam::123456789012:role/ecsTaskRole",
   "executionRoleArn" : "arn:aws:iam::123456789012:role/ecsTaskExecutionRole",
   "networkMode" : "awsvpc"
}
```

**Example 适用于 Amazon ECS 的 JSON 任务定义使用 AWS X-Ray -Linux 容器上的 Fargate**  
X-Ray 允许您收集有关应用程序服务于的请求的数据，并提供可用于可视化流量的工具。使用适用于 Envoy 的 X-Ray 驱动程序，Envoy 能够向 X-Ray 报告跟踪信息。您可以使用 Envoy [配置启用 X-Ray](https://docs.aws.amazon.com/app-mesh/latest/userguide/envoy.html) 跟踪。根据配置，Envoy 将跟踪数据发送到作为 [sidecar](https://docs.aws.amazon.com/xray/latest/devguide/xray-daemon-ecs.html) 容器运行的 X-Ray 进程守护程序，该进程守护程序将跟踪转发给 X-Ray 服务。在将跟踪发布到 X-Ray 后，您可以使用 X-Ray 控制台来可视化服务调用图和请求跟踪详细信息。以下 JSON 表示用于启用 X-Ray 集成的任务定义。  

```
{
   
   
   "family" : "taskB",
   "memory" : "1024",
   "cpu" : "512",
   "proxyConfiguration" : {
      "containerName" : "envoy",
      "properties" : [
         {
            "name" : "ProxyIngressPort",
            "value" : "15000"
         },
         {
            "name" : "AppPorts",
            "value" : "9080"
         },
         {
            "name" : "EgressIgnoredIPs",
            "value" : "169.254.170.2,169.254.169.254"
         },
         {
            "name": "EgressIgnoredPorts",
            "value": "22"
         },
         {
            "name" : "IgnoredUID",
            "value" : "1337"
         },
         {
            "name" : "ProxyEgressPort",
            "value" : "15001"
         }
      ],
      "type" : "APPMESH"
   },
   "containerDefinitions" : [
      {
         "name" : "appName",
         "image" : "appImage",
         "portMappings" : [
            {
               "containerPort" : 9080,
               "protocol" : "tcp"
            }
         ],
         "essential" : true,
         "dependsOn" : [
            {
               "containerName" : "envoy",
               "condition" : "HEALTHY"
            }
         ]
      },
      {
         
         "name" : "envoy",
         "image" : "840364872350.dkr.ecr.us-west-2.amazonaws.com/aws-appmesh-envoy:v1.34.13.0-prod",
         "essential" : true,
         "environment" : [
            {
               "name" : "APPMESH_VIRTUAL_NODE_NAME",
               "value" : "mesh/apps/virtualNode/serviceB"
            },
            {
               "name": "ENABLE_ENVOY_XRAY_TRACING",
               "value": "1"
            }
         ],
         "healthCheck" : {
            "command" : [
               "CMD-SHELL",
               "curl -s http://localhost:9901/server_info | grep state | grep -q LIVE"
            ],
            "interval" : 5,
            "retries" : 3,
            "startPeriod" : 10,
            "timeout" : 2
         },
         "memory" : 500,
         "user" : "1337"
      },
      {
         "name" : "xray-daemon",
         "image" : "amazon/aws-xray-daemon",
         "user" : "1337",
         "essential" : true,
         "cpu" : "32",
         "memoryReservation" : "256",
         "portMappings" : [
            {
               "containerPort" : 2000,
               "protocol" : "udp"
            }
         ]
      }
   ],
   "requiresCompatibilities" : [ "FARGATE" ],
   "taskRoleArn" : "arn:aws:iam::123456789012:role/ecsTaskRole",
   "executionRoleArn" : "arn:aws:iam::123456789012:role/ecsTaskExecutionRole",
   "networkMode" : "awsvpc"
}
```

**Example Amazon ECS 任务定义的 JSON - EC2 启动类型**  

```
{
  "family": "taskB",
  "memory": "256",
  "proxyConfiguration": {
    "type": "APPMESH",
    "containerName": "envoy",
    "properties": [
      {
        "name": "IgnoredUID",
        "value": "1337"
      },
      {
        "name": "ProxyIngressPort",
        "value": "15000"
      },
      {
        "name": "ProxyEgressPort",
        "value": "15001"
      },
      {
        "name": "AppPorts",
        "value": "9080"
      },
      {
        "name": "EgressIgnoredIPs",
        "value": "169.254.170.2,169.254.169.254"
      },
      {
        "name": "EgressIgnoredPorts",
        "value": "22"
      }
    ]
  },
  "containerDefinitions": [
    {
      "name": "appName",
      "image": "appImage",
      "portMappings": [
        {
          "containerPort": 9080,
          "hostPort": 9080,
          "protocol": "tcp"
        }
      ],
      "essential": true,
      "dependsOn": [
        {
          "containerName": "envoy",
          "condition": "HEALTHY"
        }
      ]
    },
    {
      "name": "envoy",
      "image": "840364872350.dkr.ecr.us-west-2.amazonaws.com/aws-appmesh-envoy:v1.34.13.0-prod",
      "essential": true,
      "environment": [
        {
          "name": "APPMESH_VIRTUAL_NODE_NAME",
          "value": "mesh/apps/virtualNode/serviceB"
        }
      ],
      "healthCheck": {
        "command": [
          "CMD-SHELL",
          "curl -s http://localhost:9901/server_info | grep state | grep -q LIVE"
        ],
        "startPeriod": 10,
        "interval": 5,
        "timeout": 2,
        "retries": 3
      },
      "user": "1337"
    }
  ],
  "requiresCompatibilities" : [ "EC2" ],
  "taskRoleArn" : "arn:aws:iam::123456789012:role/ecsTaskRole",
  "executionRoleArn" : "arn:aws:iam::123456789012:role/ecsTaskExecutionRole",
  "networkMode": "awsvpc"
}
```

**Example 适用于 Amazon ECS 任务定义的 JSON AWS X-Ray -EC2 启动类型**  

```
{
  "family": "taskB",
  "memory": "256",
   "cpu" : "1024",
  "proxyConfiguration": {
    "type": "APPMESH",
    "containerName": "envoy",
    "properties": [
      {
        "name": "IgnoredUID",
        "value": "1337"
      },
      {
        "name": "ProxyIngressPort",
        "value": "15000"
      },
      {
        "name": "ProxyEgressPort",
        "value": "15001"
      },
      {
        "name": "AppPorts",
        "value": "9080"
      },
      {
        "name": "EgressIgnoredIPs",
        "value": "169.254.170.2,169.254.169.254"
      },
      {
        "name": "EgressIgnoredPorts",
        "value": "22"
      }
    ]
  },
  "containerDefinitions": [
    {
      "name": "appName",
      "image": "appImage",
      "portMappings": [
        {
          "containerPort": 9080,
          "hostPort": 9080,
          "protocol": "tcp"
        }
      ],
      "essential": true,
      "dependsOn": [
        {
          "containerName": "envoy",
          "condition": "HEALTHY"
        }
      ]
    },
    {
      "name": "envoy",
      "image": "840364872350.dkr.ecr.us-west-2.amazonaws.com/aws-appmesh-envoy:v1.34.13.0-prod",
      "essential": true,
      "environment": [
        {
          "name": "APPMESH_VIRTUAL_NODE_NAME",
          "value": "mesh/apps/virtualNode/serviceB"
        },
        {
         "name": "ENABLE_ENVOY_XRAY_TRACING",
         "value": "1"
        }
      ],
      "healthCheck": {
        "command": [
          "CMD-SHELL",
          "curl -s http://localhost:9901/server_info | grep state | grep -q LIVE"
        ],
        "startPeriod": 10,
        "interval": 5,
        "timeout": 2,
        "retries": 3
      },
      "user": "1337"
    },
    {
      "name": "xray-daemon",
      "image": "amazon/aws-xray-daemon",
      "user": "1337",
      "essential": true,
      "cpu": 32,
      "memoryReservation": 256,
      "portMappings": [
        {
          "containerPort": 2000,
          "protocol": "udp"
        }
      ]
    }
  ],
  "requiresCompatibilities" : [ "EC2" ],
  "taskRoleArn" : "arn:aws:iam::123456789012:role/ecsTaskRole",
  "executionRoleArn" : "arn:aws:iam::123456789012:role/ecsTaskExecutionRole",
  "networkMode": "awsvpc"
}
```

## 高级主题
<a name="advanced-topics-ecs"></a>

### 使用 App Mesh 进行金丝雀部署
<a name="canary-appmesh-ecs"></a>

金丝雀部署和版本可帮助您在应用程序的旧版本和新部署的版本之间切换流量。它还会监控新部署版本的运行状况。如果新版本有任何问题，金丝雀部署可以自动将流量切换回旧版本。利用金丝雀部署，能够更多地控制在应用程序版本之间切换流量。

有关如何使用 App Mesh 为 Amazon ECS 实施金丝雀部署的更多信息，请参阅使用 App Mesh [为亚马逊 ECS 创建带有金丝雀部署的管道](https://aws.amazon.com/blogs/containers/create-a-pipeline-with-canary-deployments-for-amazon-ecs-using-aws-app-mesh/)

**注意**  
有关 App Mesh 的更多示例和演练，请参阅 [App Mesh 示例存储库](https://github.com/aws/aws-app-mesh-examples)。

# 入门 AWS App Mesh 和 Kubernetes
<a name="getting-started-kubernetes"></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)。

当你使用适用于 Kubernetes 的 App Mesh 控制器 AWS App Mesh 与 Kubernetes 集成时，你可以管理应用网格资源，例如网格、虚拟服务、虚拟节点、虚拟路由器和通过 Kubernetes 的路由。您也可以自动向 Kubernetes 容器组 (pod) 规范中添加 App Mesh sidecar 容器映像。本教程指导您完成适用于 Kubernetes 的 App Mesh 控制器的安装，以便启用此集成。

以下 Kubernetes 自定义资源定义的部署附带了控制器：`meshes`、`virtual services`、`virtual nodes` 和 `virtual routers`。控制器密切注意自定义资源的创建、修改和删除，并通过 API 更改相应的 App Mesh [服务网格](meshes.md) [虚拟服务](virtual_services.md)、[虚拟节点](virtual_nodes.md)、[虚拟网关](virtual_gateways.md)、[网关路由](gateway-routes.md)、[虚拟路由器](virtual_routers.md)（包括 [Routes](routes.md)）资源。要了解更多信息或为控制器做出贡献，请参阅[GitHub项目](https://github.com/aws/aws-app-mesh-controller-for-k8s)。

控制器还会安装一个 Webhook，将以下容器注入标有您指定名称的 Kubernetes 容器组 (pod) 中。
+ **App Mesh Envoy 代理** - Envoy 使用在 App Mesh 控制面板中定义的配置来确定将应用程序流量发送到何处。
+ **App Mesh 代理路由管理器 **- 更新容器组 (pod) 网络命名空间中通过 Envoy 路由传入和传出流量的 `iptables` 规则。此容器作为 Kubernetes init 容器运行在容器组 (pod) 中。

## 先决条件
<a name="mesh-k8s-integration-prerequisites"></a>
+ 已了解 App Mesh 概念。有关更多信息，请参阅 [什么是 AWS App Mesh？](what-is-app-mesh.md)。
+ 已对 Kubernetes 概念有所了解。有关更多信息，请参阅 Kubernetes 文档中的 [什么是 Kubernetes](https://kubernetes.io/docs/concepts/overview/what-is-kubernetes/)。
+ 现有 Kubernetes 集群。如果您还没有集群，请参阅《Amazon EKS 用户指南》**中的 [Amazon EKS 入门](https://docs.aws.amazon.com/eks/latest/userguide/getting-started.html)。如果您在亚马逊 EC2 上运行自己的 Kubernetes 集群，请确保 Docker 已通过 Envoy 镜像所在的 Amazon ECR 存储库的身份验证。有关更多信息，请参阅 [ Envoy 镜像](https://docs.aws.amazon.com/app-mesh/latest/userguide/envoy.html)、《亚马逊弹性容器注册表用户指南》中的注册表[身份验证](https://docs.aws.amazon.com/AmazonECR/latest/userguide/Registries.html#registry_auth)和 Kubernetes 文档中的[从私有注册表中提取镜像](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/)。
+ App Mesh 支持在 DNS 中注册的 Linux 服务 AWS Cloud Map，或者两者兼而有之。要使用此入门指南，我们建议您提供三项已注册到 DNS 的现有服务。该主题的剩余步骤假定现有服务命名为 `serviceA`、`serviceB` 和 `serviceBv2`，并且可以在名为 `apps.local` 的命名空间中发现所有服务。

  即使服务不存在，您也可以创建服务网格及其资源，但在部署实际服务之前，您无法使用网格。
+ 已安装 AWS CLI 版本 1.18.116 或更高版本或 2.0.38 或更高版本。要安装或升级 AWS CLI，请参阅[安装 AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html)。
+ 配置为与您的 Kubernetes 集群通信的 `kubectl` 客户端。如果您正在使用 Amazon Elastic Kubernetes Service，则可以使用用于安装 `[kubectl](https://docs.aws.amazon.com/eks/latest/userguide/install-kubectl.html)` 和配置 `[kubeconfig](https://docs.aws.amazon.com/eks/latest/userguide/create-kubeconfig.html)` 文件的说明。
+ Helm 版本 3.0 或更高版本已安装。如果您没有安装 Helm，请参阅*《亚马逊 EKS 用户指南》*中的[将 Helm 与亚马逊 EKS 配合使用](https://docs.aws.amazon.com/eks/latest/userguide/helm.html)。
+ Amazon EKS 目前 `IPv6_ONLY` 仅支持 `IPv4_ONLY` 且仅支持 IP 首选项，因为 Amazon EKS 目前仅支持能够仅提供 `IPv4` 流量或仅 `IPv6` 流量的容器组 (pod)。

剩余步骤假定实际服务命名为 `serviceA`、`serviceB` 和 `serviceBv2`，并且可以在名为 `apps.local` 的命名空间中发现所有服务。

## 步骤 1：安装集成组件
<a name="install-controller"></a>

在要托管与 App Mesh 结合使用的容器组 (pod) 的每个集群中，安装一次集成组件。

**安装集成组件**

1. 此过程的剩余步骤需要一个没有安装预发行版控制器的集群。如果您已安装预发行版，或者不确定是否已安装，则可以下载并运行一个脚本，检查您的集群是否安装了预发行版。

   ```
   curl -o pre_upgrade_check.sh https://raw.githubusercontent.com/aws/eks-charts/master/stable/appmesh-controller/upgrade/pre_upgrade_check.sh
   sh ./pre_upgrade_check.sh
   ```

   如果脚本返回 `Your cluster is ready for upgrade. Please proceed to the installation instructions`，则可以继续执行下一步。如果返回不同的消息，则需要先完成升级步骤，然后再继续。有关升级预发行版本的更多信息，请参阅[升级](https://github.com/aws/eks-charts/blob/master/stable/appmesh-controller/README.md#upgrade)。 GitHub

1. 将 `eks-charts` 存储库添加到 Helm。

   ```
   helm repo add eks https://aws.github.io/eks-charts
   ```

1. 安装 App Mesh Kubernetes 自定义资源定义 (CRD)。

   ```
   kubectl apply -k "https://github.com/aws/eks-charts/stable/appmesh-controller/crds?ref=master"
   ```

1. 为控制器创建一个 Kubernetes 命名空间。

   ```
   kubectl create ns appmesh-system
   ```

1. 设置以下变量，以便在后续步骤中使用。将 `cluster-name` 和 `Region-code` 替换为现有集群的值。

   ```
   export CLUSTER_NAME=cluster-name
   export AWS_REGION=Region-code
   ```

1. （可选）如果您想在 Fargate 上运行控制器，则需要创建一个 Fargate 配置文件。如果您尚未 `eksctl` 安装，请参阅 *《Amazon EKS 用户指南》`eksctl`*中的[安装或升级](https://docs.aws.amazon.com/eks/latest/userguide/eksctl.html#installing-eksctl)。如果您希望使用控制台创建配置文件，请参阅*《Amazon EKS 用户指南》*中的[创建 Fargate 配置文件](https://docs.aws.amazon.com/eks/latest/userguide/fargate-profile.html#create-fargate-profile)。

   ```
   eksctl create fargateprofile --cluster $CLUSTER_NAME --name appmesh-system --namespace appmesh-system
   ```

1. 为您的集群创建 OpenID Connect (OIDC) 身份提供商。如果未安装 `eksctl`，则可以按照《Amazon EKS 用户指南》**中[安装或升级 `eksctl`](https://docs.aws.amazon.com/eks/latest/userguide/eksctl.html#installing-eksctl)上的说明安装它。如果您希望使用控制台创建提供商，请参阅 A *mazon EKS 用户指南*中的[为集群上的服务账户启用 IAM 角色](https://docs.aws.amazon.com/eks/latest/userguide/enable-iam-roles-for-service-accounts.html)。

   ```
   eksctl utils associate-iam-oidc-provider \
       --region=$AWS_REGION \
       --cluster $CLUSTER_NAME \
       --approve
   ```

1. 创建 IAM 角色，为其附加[https://console.aws.amazon.com/iam/home?#policies/arn:aws:iam::aws:policy/AWSAppMeshFullAccess$jsonEditor](https://console.aws.amazon.com/iam/home?#policies/arn:aws:iam::aws:policy/AWSAppMeshFullAccess$jsonEditor)和[https://console.aws.amazon.com/iam/home?#policies/arn:aws:iam::aws:policy/AWSCloudMapFullAccess$jsonEditor](https://console.aws.amazon.com/iam/home?#policies/arn:aws:iam::aws:policy/AWSCloudMapFullAccess$jsonEditor) AWS 托管策略，然后将其绑定到 `appmesh-controller` Kubernetes 服务账户。该角色使控制器能够添加、删除和更改 App Mesh 资源。
**注意**  
该命令使用自动生成的名称创建一个 AWS IAM 角色。您无法指定创建的 IAM 角色名称。

   ```
   eksctl create iamserviceaccount \
       --cluster $CLUSTER_NAME \
       --namespace appmesh-system \
       --name appmesh-controller \
       --attach-policy-arn  arn:aws:iam::aws:policy/AWSCloudMapFullAccess,arn:aws:iam::aws:policy/AWSAppMeshFullAccess \
       --override-existing-serviceaccounts \
       --approve
   ```

   如果您更喜欢使用 AWS 管理控制台 或创建服务账户 AWS CLI，请参阅 A *mazon EKS 用户指南*[中的为您的服务账户创建 IAM 角色和策略](https://docs.aws.amazon.com/eks/latest/userguide/create-service-account-iam-policy-and-role.html#create-service-account-iam-role)。如果您使用 AWS 管理控制台 或 AWS CLI 来创建账户，则还需要将该角色映射到 Kubernetes 服务账户。有关更多信息，请*参阅《Amazon EKS 用户指南》*中的[为集群上的服务账户指定 IAM 角色](https://docs.aws.amazon.com/eks/latest/userguide/specify-service-account-role.html)。

1. 

**部署 App Mesh 控制器。有关所有配置选项的列表，请参阅上的[配置](https://github.com/aws/eks-charts/blob/master/stable/appmesh-controller/README.md#configuration) GitHub。**

   1. 要为私有集群部署 App Mesh 控制器，必须先对链接的私有子网启用 App Mesh 和服务发现 Amazon VPC 端点。您还需要设置 `accountId`。

      ```
      --set accountId=$AWS_ACCOUNT_ID
      ```

      要在私有集群中启用 X-Ray 跟踪，请启用 X-Ray 和 Amazon ECR Amazon VPC 端点。控制器默认使用 `public.ecr.aws/xray/aws-xray-daemon:latest`，因此请将此映像拉到本地并[将其推送到您的个人 ECR 存储库](https://docs.aws.amazon.com/AmazonECR/latest/userguide/docker-push-ecr-image.html)。
**注意**  
[Amazon VPC 端点](https://docs.aws.amazon.com/AmazonECR/latest/userguide/vpc-endpoints.html)目前不支持 Amazon ECR 公有存储库。

      以下示例显示如何使用 X-Ray 配置部署控制器。

      ```
      helm upgrade -i appmesh-controller eks/appmesh-controller \
          --namespace appmesh-system \
          --set region=$AWS_REGION \
          --set serviceAccount.create=false \
          --set serviceAccount.name=appmesh-controller \
          --set accountId=$AWS_ACCOUNT_ID \
          --set log.level=debug \
          --set tracing.enabled=true \
          --set tracing.provider=x-ray \
          --set xray.image.repository=your-account-id.dkr.ecr.your-region.amazonaws.com/your-repository \
          --set xray.image.tag=your-xray-daemon-image-tag
      ```

      在将应用程序部署与虚拟节点或网关绑定时，请验证 X-Ray 进程守护程序是否成功注入。

      有关更多信息，请参阅《Amazon EKS 用户指南》**中的[私有集群](https://docs.aws.amazon.com/eks/latest/userguide/private-clusters.html)。

   1. 为其他集群部署 App Mesh 控制器。有关所有配置选项的列表，请参阅上的[配置](https://github.com/aws/eks-charts/blob/master/stable/appmesh-controller/README.md#configuration) GitHub。

      ```
      helm upgrade -i appmesh-controller eks/appmesh-controller \
          --namespace appmesh-system \
          --set region=$AWS_REGION \
          --set serviceAccount.create=false \
          --set serviceAccount.name=appmesh-controller
      ```
**注意**  
如果您的 Amazon EKS 集群系列是 `IPv6`，请在部署 App Mesh 控制器时通过在前面的命令中添加以下选项来设置集群名称 `--set clusterName=$CLUSTER_NAME`。
**重要**  
如果您的集群位于`me-south-1`、`ap-east-1`、`ap-southeast-3`、`eu-south-1`、`il-central-1` 或 `af-south-1` 区域中，则需要在前面的命令中添加以下选项：  
*Region-code*用*account-id*一组相应的值替换和。  

       ```
        --set image.repository=account-id.dkr.ecr.Region-code.amazonaws.com/amazon/appmesh-controller
       ```
772975370895.dkr。ecr.me-south-1.amazonaws.com/: v1.34.13.0-prod aws-appmesh-envoy
856666278305.dkr。ecr.ap-east-1.amazonaws.com/: v1.34.13.0-prod aws-appmesh-envoy
909464085924.dkr。ecr.ap-southeast-3.amazonaws.com/: v1.34.13.0-prod aws-appmesh-envoy
422531588944.dkr。ecr.eu-south-1.amazonaws.com/: v1.34.13.0-prod aws-appmesh-envoy
564877687649.dkr。ecr.il-central-1.amazonaws.com/: v1.34.13.0-prod aws-appmesh-envoy
924023996002.dkr。ecr.af-south-1.amazonaws.com/: v1.34.13.0-prod aws-appmesh-envoy
 URIs 可以在[更改日志](https://github.com/aws/aws-app-mesh-controller-for-k8s/releases)中找到较旧的图像 GitHub。显示图像的 AWS 账户版本已更改`v1.5.0`。[旧版本的镜像托管在亚马逊 Elastic Kubernetes Service 亚马逊容器镜像注册表上的 AWS 账户中。](https://docs.aws.amazon.com/eks/latest/userguide/add-ons-images.html)

       ```
       --set sidecar.image.repository=account-id.dkr.ecr.Region-code.amazonaws.com/aws-appmesh-envoy
       ```
772975370895.dkr.ecr.me-south-1.amazonaws。 com/amazon/appmesh-控制器:v1.13.1
856666278305.dkr.ecr.ap-east-1.amazonaws。 com/amazon/appmesh-控制器:v1.13.1
909464085924.dkr.ecr.ap-southeast-3.amazonaws。 com/amazon/appmesh-控制器:v1.13.1
422531588944.dkr.ecr.eu-south-1.amazonaws。 com/amazon/appmesh-控制器:v1.13.1
56487768767649.dkr.ecr.il-central-1.amazonaws。 com/amazon/appmesh-控制器:v1.13.1
924023996002.dkr.ecr.acr.af-south-1.amazonaws。 com/amazon/appmesh-控制器:v1.13.1

       ```
       --set sidecar.image.repository=account-id.dkr.ecr.Region-code.amazonaws.com/aws-appmesh-envoy
       ```
772975370895.dkr。ecr.me-south-1.amazonaws.com /-manager: v7-prod aws-appmesh-proxy-route
856666278305.dkr。ecr.ap-east-1.amazonaws.com /-manager: v7-prod aws-appmesh-proxy-route
909464085924.dkr。ecr.ap-southeast-3.amazonaws.com /-manager: v7-prod aws-appmesh-proxy-route
422531588944.dkr。ecr.eu-south-1.amazonaws.com /-manager: v7-prod aws-appmesh-proxy-route
564877687649.dkr。ecr.il-central-1.amazonaws.com /-manager: v7-prod aws-appmesh-proxy-route
924023996002.dkr。ecr.af-south-1.amazonaws.com /-manager: v7-prod aws-appmesh-proxy-route
**重要**  
仅支持将版本 v1.9.0.0-prod 或更高版本与 App Mesh 一起使用。

1. 确认控制器版本为 `v1.4.0` 或更高版本。您可以登录查看[变更日志](https://github.com/aws/aws-app-mesh-controller-for-k8s/releases) GitHub。

   ```
   kubectl get deployment appmesh-controller \
       -n appmesh-system \
       -o json  | jq -r ".spec.template.spec.containers[].image" | cut -f2 -d ':'
   ```
**注意**  
如果您查看正在运行的容器的日志，您可能会看到有一行包含以下文本，这行文本可以安全地忽略。  

   ```
   Neither -kubeconfig nor -master was specified. Using the inClusterConfig. This might not work.
   ```

## 步骤 2：部署 App Mesh 资源
<a name="configure-app-mesh"></a>

当您在 Kubernetes 中部署应用程序时，您也会创建 Kubernetes 自定义资源，以便控制器可以创建相应的 App Mesh 资源。以下过程可帮助您部署具有某些功能的 App Mesh 资源。您可以在 App Mesh [演练中列出的许多功能文件夹的`v1beta2`子文件夹中找到部署其他 App Mesh](https://github.com/aws/aws-app-mesh-examples/tree/main/walkthroughs) 资源功能的示例清单。 GitHub

**重要**  
控制器创建了 App Mesh 资源后，建议您仅使用控制器对 App Mesh 资源进行更改或删除资源。如果您使用 App Mesh 对资源进行更改或删除，则默认情况下，控制器将在十小时内不会更改或重新创建所更改或删除的 App Mesh 资源。您可以将此持续时间配置为更短的时间。有关更多信息，请参阅上的[配置](https://github.com/aws/eks-charts/blob/master/stable/appmesh-controller/README.md#configuration) GitHub。

**部署 App Mesh 资源**

1. 创建要将 App Mesh 资源部署到的 Kubernetes 命名空间。

   1. 将以下内容保存到计算机上名为 `namespace.yaml` 的文件中。

      ```
      apiVersion: v1
      kind: Namespace
      metadata:
        name: my-apps
        labels:
          mesh: my-mesh
          appmesh.k8s.aws/sidecarInjectorWebhook: enabled
      ```

   1. 创建命名空间。

      ```
      kubectl apply -f namespace.yaml
      ```

1. 创建 App Mesh 服务网格

   1. 将以下内容保存到计算机上名为 `mesh.yaml` 的文件中。该文件用于创建名为 `my-mesh` 的网格资源。服务网格是一种用于驻留在其内的服务之间的网络流量的逻辑边界。

      ```
      apiVersion: appmesh.k8s.aws/v1beta2
      kind: Mesh
      metadata:
        name: my-mesh
      spec:
        namespaceSelector:
          matchLabels:
            mesh: my-mesh
      ```

   1. 创建网格。

      ```
      kubectl apply -f mesh.yaml
      ```

   1. 查看已创建的 Kubernetes 网格资源的详细信息。

      ```
      kubectl describe mesh my-mesh
      ```

      Output

      ```
      Name:         my-mesh
      Namespace:
      Labels:       <none>
      Annotations:  kubectl.kubernetes.io/last-applied-configuration:
                      {"apiVersion":"appmesh.k8s.aws/v1beta2","kind":"Mesh","metadata":{"annotations":{},"name":"my-mesh"},"spec":{"namespaceSelector":{"matchLa...
      API Version:  appmesh.k8s.aws/v1beta2
      Kind:         Mesh
      Metadata:
        Creation Timestamp:  2020-06-17T14:51:37Z
        Finalizers:
          finalizers.appmesh.k8s.aws/mesh-members
          finalizers.appmesh.k8s.aws/aws-appmesh-resources
        Generation:        1
        Resource Version:  6295
        Self Link:         /apis/appmesh.k8s.aws/v1beta2/meshes/my-mesh
        UID:               111a11b1-c11d-1e1f-gh1i-j11k1l111m711
      Spec:
        Aws Name:  my-mesh
        Namespace Selector:
          Match Labels:
            Mesh:  my-mesh
      Status:
        Conditions:
          Last Transition Time:  2020-06-17T14:51:37Z
          Status:                True
          Type:                  MeshActive
        Mesh ARN:                arn:aws:appmesh:us-west-2:111122223333:mesh/my-mesh
        Observed Generation:     1
      Events:                    <none>
      ```

   1. 查看有关控制器创建的 App Mesh 服务网格的详细信息。

      ```
      aws appmesh describe-mesh --mesh-name my-mesh
      ```

      Output

      ```
      {
          "mesh": {
              "meshName": "my-mesh",
              "metadata": {
                  "arn": "arn:aws:appmesh:us-west-2:111122223333:mesh/my-mesh",
                  "createdAt": "2020-06-17T09:51:37.920000-05:00",
                  "lastUpdatedAt": "2020-06-17T09:51:37.920000-05:00",
                  "meshOwner": "111122223333",
                  "resourceOwner": "111122223333",
                  "uid": "111a11b1-c11d-1e1f-gh1i-j11k1l111m711",
                  "version": 1
              },
              "spec": {},
              "status": {
                  "status": "ACTIVE"
              }
          }
      }
      ```

1. 创建 App Mesh 虚拟节点。虚拟节点充当指向 Kubernetes 部署的逻辑指针。

   1. 将以下内容保存到计算机上名为 `virtual-node.yaml` 的文件中。该文件用于创建命名*`my-apps`*空间 `my-service-a` 中命名的 App Mesh 虚拟节点。虚拟节点表示在后续步骤中创建的 Kubernetes 服务。`hostname` 的值是此虚拟节点所代表的实际服务的完全限定 DNS 主机名。

      ```
      apiVersion: appmesh.k8s.aws/v1beta2
      kind: VirtualNode
      metadata:
        name: my-service-a
        namespace: my-apps
      spec:
        podSelector:
          matchLabels:
            app: my-app-1
        listeners:
          - portMapping:
              port: 80
              protocol: http
        serviceDiscovery:
          dns:
            hostname: my-service-a.my-apps.svc.cluster.local
      ```

      虚拟节点具有本教程中未涉及的功能，例如 end-to-end加密和运行状况检查。有关更多信息，请参阅 [虚拟节点](virtual_nodes.md)。若要查看可在上述规范中设置的虚拟节点的所有可用设置，请运行以下命令。

      ```
      aws appmesh create-virtual-node --generate-cli-skeleton yaml-input
      ```

   1. 部署虚拟节点。

      ```
      kubectl apply -f virtual-node.yaml
      ```

   1. 查看已创建的 Kubernetes 虚拟节点资源的详细信息。

      ```
      kubectl describe virtualnode my-service-a -n my-apps
      ```

      Output

      ```
      Name:         my-service-a
      Namespace:    my-apps
      Labels:       <none>
      Annotations:  kubectl.kubernetes.io/last-applied-configuration:
                      {"apiVersion":"appmesh.k8s.aws/v1beta2","kind":"VirtualNode","metadata":{"annotations":{},"name":"my-service-a","namespace":"my-apps"},"s...
      API Version:  appmesh.k8s.aws/v1beta2
      Kind:         VirtualNode
      Metadata:
        Creation Timestamp:  2020-06-17T14:57:29Z
        Finalizers:
          finalizers.appmesh.k8s.aws/aws-appmesh-resources
        Generation:        2
        Resource Version:  22545
        Self Link:         /apis/appmesh.k8s.aws/v1beta2/namespaces/my-apps/virtualnodes/my-service-a
        UID:               111a11b1-c11d-1e1f-gh1i-j11k1l111m711
      Spec:
        Aws Name:  my-service-a_my-apps
        Listeners:
          Port Mapping:
            Port:      80
            Protocol:  http
        Mesh Ref:
          Name:  my-mesh
          UID:   111a11b1-c11d-1e1f-gh1i-j11k1l111m711
        Pod Selector:
          Match Labels:
            App:  nginx
        Service Discovery:
          Dns:
            Hostname:  my-service-a.my-apps.svc.cluster.local
      Status:
        Conditions:
          Last Transition Time:  2020-06-17T14:57:29Z
          Status:                True
          Type:                  VirtualNodeActive
        Observed Generation:     2
        Virtual Node ARN:        arn:aws:appmesh:us-west-2:111122223333:mesh/my-mesh/virtualNode/my-service-a_my-apps
      Events:                    <none>
      ```

   1. 查看控制器在 App Mesh 中创建的虚拟节点的详细信息。
**注意**  
尽管在 Kubernetes 中创建的虚拟节点的名称为 `my-service-a`，但在 App Mesh 中创建的虚拟节点的名称为 `my-service-a_my-apps`。控制器在创建 App Mesh 资源时，将 Kubernetes 命名空间名称附加到 App Mesh 虚拟节点名称。添加命名空间名称是因为在 Kubernetes 中，您可以在不同的命名空间中创建具有相同名称的虚拟节点，但在 App Mesh 中，虚拟节点名称在网格内必须唯一。

      ```
      aws appmesh describe-virtual-node --mesh-name my-mesh --virtual-node-name my-service-a_my-apps
      ```

      Output

      ```
      {
          "virtualNode": {
              "meshName": "my-mesh",
              "metadata": {
                  "arn": "arn:aws:appmesh:us-west-2:111122223333:mesh/my-mesh/virtualNode/my-service-a_my-apps",
                  "createdAt": "2020-06-17T09:57:29.840000-05:00",
                  "lastUpdatedAt": "2020-06-17T09:57:29.840000-05:00",
                  "meshOwner": "111122223333",
                  "resourceOwner": "111122223333",
                  "uid": "111a11b1-c11d-1e1f-gh1i-j11k1l111m711",
                  "version": 1
              },
              "spec": {
                  "backends": [],
                  "listeners": [
                      {
                          "portMapping": {
                              "port": 80,
                              "protocol": "http"
                          }
                      }
                  ],
                  "serviceDiscovery": {
                      "dns": {
                          "hostname": "my-service-a.my-apps.svc.cluster.local"
                      }
                  }
              },
              "status": {
                  "status": "ACTIVE"
              },
              "virtualNodeName": "my-service-a_my-apps"
          }
      }
      ```

1. 创建 App Mesh 虚拟路由器。虚拟路由器处理用于您的网格内一个或多个虚拟服务的流量。

   1. 将以下内容保存到计算机上名为 `virtual-router.yaml` 的文件中。该文件用于创建虚拟路由器，将流量路由到在上一步中创建的名为 `my-service-a` 的虚拟节点。控制器创建 App Mesh 虚拟路由器和路由资源。您可以为路由指定更多功能，以及使用 `http` 以外的协议。有关更多信息，请参阅[虚拟路由器](virtual_routers.md)和[Routes](routes.md)。请注意，引用的虚拟节点名称是 Kubernetes 虚拟节点名称，而不是控制器在 App Mesh 中创建的 App Mesh 虚拟节点名称。

      ```
      apiVersion: appmesh.k8s.aws/v1beta2
      kind: VirtualRouter
      metadata:
        namespace: my-apps
        name: my-service-a-virtual-router
      spec:
        listeners:
          - portMapping:
              port: 80
              protocol: http
        routes:
          - name: my-service-a-route
            httpRoute:
              match:
                prefix: /
              action:
                weightedTargets:
                  - virtualNodeRef:
                      name: my-service-a
                    weight: 1
      ```

      （可选）若要查看可在上述规范中设置的虚拟路由器的所有可用设置，请运行以下命令。

      ```
      aws appmesh create-virtual-router --generate-cli-skeleton yaml-input
      ```

      若要查看可在上述规范中设置的路由的所有可用设置，请运行以下命令。

      ```
      aws appmesh create-route --generate-cli-skeleton yaml-input
      ```

   1. 部署虚拟路由器。

      ```
      kubectl apply -f virtual-router.yaml
      ```

   1. 查看已创建的 Kubernetes 虚拟路由器资源。

      ```
      kubectl describe virtualrouter my-service-a-virtual-router -n my-apps
      ```

      缩减的输出

      ```
      Name:         my-service-a-virtual-router
      Namespace:    my-apps
      Labels:       <none>
      Annotations:  kubectl.kubernetes.io/last-applied-configuration:
                      {"apiVersion":"appmesh.k8s.aws/v1beta2","kind":"VirtualRouter","metadata":{"annotations":{},"name":"my-service-a-virtual-router","namespac...
      API Version:  appmesh.k8s.aws/v1beta2
      Kind:         VirtualRouter
      ...
      Spec:
        Aws Name:  my-service-a-virtual-router_my-apps
        Listeners:
          Port Mapping:
            Port:      80
            Protocol:  http
        Mesh Ref:
          Name:  my-mesh
          UID:   111a11b1-c11d-1e1f-gh1i-j11k1l111m711
        Routes:
          Http Route:
            Action:
              Weighted Targets:
                Virtual Node Ref:
                  Name:  my-service-a
                Weight:  1
            Match:
              Prefix:  /
          Name:        my-service-a-route
      Status:
        Conditions:
          Last Transition Time:  2020-06-17T15:14:01Z
          Status:                True
          Type:                  VirtualRouterActive
        Observed Generation:     1
        Route AR Ns:
          My - Service - A - Route:  arn:aws:appmesh:us-west-2:111122223333:mesh/my-mesh/virtualRouter/my-service-a-virtual-router_my-apps/route/my-service-a-route
        Virtual Router ARN:          arn:aws:appmesh:us-west-2:111122223333:mesh/my-mesh/virtualRouter/my-service-a-virtual-router_my-apps
      Events:                        <none>
      ```

   1. 查看控制器在 App Mesh 中创建的虚拟路由器资源。您可以为 `name` 指定 `my-service-a-virtual-router_my-apps`，因为当控制器在 App Mesh 中创建虚拟路由器时，它会在虚拟路由器的名称后附加 Kubernetes 命名空间名称。

      ```
      aws appmesh describe-virtual-router --virtual-router-name my-service-a-virtual-router_my-apps --mesh-name my-mesh
      ```

      Output

      ```
      {
          "virtualRouter": {
              "meshName": "my-mesh",
              "metadata": {
                  "arn": "arn:aws:appmesh:us-west-2:111122223333:mesh/my-mesh/virtualRouter/my-service-a-virtual-router_my-apps",
                  "createdAt": "2020-06-17T10:14:01.547000-05:00",
                  "lastUpdatedAt": "2020-06-17T10:14:01.547000-05:00",
                  "meshOwner": "111122223333",
                  "resourceOwner": "111122223333",
                  "uid": "111a11b1-c11d-1e1f-gh1i-j11k1l111m711",
                  "version": 1
              },
              "spec": {
                  "listeners": [
                      {
                          "portMapping": {
                              "port": 80,
                              "protocol": "http"
                          }
                      }
                  ]
              },
              "status": {
                  "status": "ACTIVE"
              },
              "virtualRouterName": "my-service-a-virtual-router_my-apps"
          }
      }
      ```

   1. 查看控制器在 App Mesh 中创建的路由资源。未在 Kubernetes 中创建路由资源，因为该路由是 Kubernetes 中虚拟路由器配置的一部分。路由信息显示在子步骤 `c` 的 Kubernetes 资源详细信息中。控制器在 App Mesh 中创建路由时，不将 Kubernetes 命名空间名称附加到 App Mesh 路由名称，因为路由名称对虚拟路由器唯一。

      ```
      aws appmesh describe-route \
          --route-name my-service-a-route \
          --virtual-router-name my-service-a-virtual-router_my-apps \
          --mesh-name my-mesh
      ```

      Output

      ```
      {
          "route": {
              "meshName": "my-mesh",
              "metadata": {
                  "arn": "arn:aws:appmesh:us-west-2:111122223333:mesh/my-mesh/virtualRouter/my-service-a-virtual-router_my-apps/route/my-service-a-route",
                  "createdAt": "2020-06-17T10:14:01.577000-05:00",
                  "lastUpdatedAt": "2020-06-17T10:14:01.577000-05:00",
                  "meshOwner": "111122223333",
                  "resourceOwner": "111122223333",
                  "uid": "111a11b1-c11d-1e1f-gh1i-j11k1l111m711",
                  "version": 1
              },
              "routeName": "my-service-a-route",
              "spec": {
                  "httpRoute": {
                      "action": {
                          "weightedTargets": [
                              {
                                  "virtualNode": "my-service-a_my-apps",
                                  "weight": 1
                              }
                          ]
                      },
                      "match": {
                          "prefix": "/"
                      }
                  }
              },
              "status": {
                  "status": "ACTIVE"
              },
              "virtualRouterName": "my-service-a-virtual-router_my-apps"
          }
      }
      ```

1. 创建 App Mesh 虚拟服务。虚拟服务是一种抽象的实际服务，由虚拟节点直接提供或通过虚拟路由器的方式间接提供。从属服务按名称调用您的虚拟服务。虽然名称对于 App Mesh 并不重要，但建议将虚拟服务命名为虚拟服务所代表的实际服务的完全限定域名。通过这种方式命名虚拟服务，您无需更改应用程序代码即可引用其他名称。请求路由到指定作为虚拟服务提供程序的虚拟节点或虚拟路由器。

   1. 将以下内容保存到计算机上名为 `virtual-service.yaml` 的文件中。该文件用于创建虚拟服务，使用虚拟路由器提供程序将流量路由到在上一步中创建的名为 `my-service-a` 的虚拟节点。`spec` 中 `awsName` 的值是此虚拟服务所提取的实际 Kubernetes 服务的完全限定域名 (FQDN)。Kubernetes 服务在 [步骤 3：创建或更新服务](#create-update-services) 中创建。有关更多信息，请参阅 [虚拟服务](virtual_services.md)。

      ```
      apiVersion: appmesh.k8s.aws/v1beta2
      kind: VirtualService
      metadata:
        name: my-service-a
        namespace: my-apps
      spec:
        awsName: my-service-a.my-apps.svc.cluster.local
        provider:
          virtualRouter:
            virtualRouterRef:
              name: my-service-a-virtual-router
      ```

      若要查看可在上述规范中设置的虚拟服务的所有可用设置，请运行以下命令。

      ```
      aws appmesh create-virtual-service --generate-cli-skeleton yaml-input
      ```

   1. 创建虚拟服务。

      ```
      kubectl apply -f virtual-service.yaml
      ```

   1. 查看已创建的 Kubernetes 虚拟服务资源的详细信息。

      ```
      kubectl describe virtualservice my-service-a -n my-apps
      ```

      Output

      ```
      Name:         my-service-a
      Namespace:    my-apps
      Labels:       <none>
      Annotations:  kubectl.kubernetes.io/last-applied-configuration:
                      {"apiVersion":"appmesh.k8s.aws/v1beta2","kind":"VirtualService","metadata":{"annotations":{},"name":"my-service-a","namespace":"my-apps"}...
      API Version:  appmesh.k8s.aws/v1beta2
      Kind:         VirtualService
      Metadata:
        Creation Timestamp:  2020-06-17T15:48:40Z
        Finalizers:
          finalizers.appmesh.k8s.aws/aws-appmesh-resources
        Generation:        1
        Resource Version:  13598
        Self Link:         /apis/appmesh.k8s.aws/v1beta2/namespaces/my-apps/virtualservices/my-service-a
        UID:               111a11b1-c11d-1e1f-gh1i-j11k1l111m711
      Spec:
        Aws Name:  my-service-a.my-apps.svc.cluster.local
        Mesh Ref:
          Name:  my-mesh
          UID:   111a11b1-c11d-1e1f-gh1i-j11k1l111m711
        Provider:
          Virtual Router:
            Virtual Router Ref:
              Name:  my-service-a-virtual-router
      Status:
        Conditions:
          Last Transition Time:  2020-06-17T15:48:40Z
          Status:                True
          Type:                  VirtualServiceActive
        Observed Generation:     1
        Virtual Service ARN:     arn:aws:appmesh:us-west-2:111122223333:mesh/my-mesh/virtualService/my-service-a.my-apps.svc.cluster.local
      Events:                    <none>
      ```

   1. 查看控制器在 App Mesh 中创建的虚拟服务资源的详细信息。Kubernetes 控制器在 App Mesh 中创建虚拟服务时，不将 Kubernetes 命名空间名称附加到 App Mesh 虚拟服务名称，因为虚拟服务的名称是唯一的 FQDN。

      ```
      aws appmesh describe-virtual-service --virtual-service-name my-service-a.my-apps.svc.cluster.local --mesh-name my-mesh
      ```

      Output

      ```
      {
          "virtualService": {
              "meshName": "my-mesh",
              "metadata": {
                  "arn": "arn:aws:appmesh:us-west-2:111122223333:mesh/my-mesh/virtualService/my-service-a.my-apps.svc.cluster.local",
                  "createdAt": "2020-06-17T10:48:40.182000-05:00",
                  "lastUpdatedAt": "2020-06-17T10:48:40.182000-05:00",
                  "meshOwner": "111122223333",
                  "resourceOwner": "111122223333",
                  "uid": "111a11b1-c11d-1e1f-gh1i-j11k1l111m711",
                  "version": 1
              },
              "spec": {
                  "provider": {
                      "virtualRouter": {
                          "virtualRouterName": "my-service-a-virtual-router_my-apps"
                      }
                  }
              },
              "status": {
                  "status": "ACTIVE"
              },
              "virtualServiceName": "my-service-a.my-apps.svc.cluster.local"
          }
      }
      ```

尽管本教程中没有介绍，但控制器也可以部署 App Mesh [虚拟网关](virtual_gateways.md) 和 [网关路由](gateway-routes.md)。有关使用控制器部署这些资源的演练，请参阅[配置入站网关](https://github.com/aws/aws-app-mesh-examples/tree/main/walkthroughs/howto-k8s-ingress-gateway)或包含上 GitHub资源的[示例清单](https://github.com/aws/aws-app-mesh-examples/blob/main/walkthroughs/howto-k8s-ingress-gateway/v1beta2/manifest.yaml.template)。

## 步骤 3：创建或更新服务
<a name="create-update-services"></a>

您想要和 App Mesh 配合使用的任何容器组 (pod) 必须已经添加了 App Mesh sidecar 容器。注入器会自动将 sidecar 容器添加到使用您指定的标签部署的任意容器组 (pod) 中。

1. 启用代理授权。我们建议您启用每个 Kubernetes 部署，以仅流式传输自己的 App Mesh 虚拟节点的配置。

   1. 将以下内容保存到计算机上名为 `proxy-auth.json` 的文件中。请务必*alternate-colored values*用自己的替换。

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

****  

      ```
      {
          "Version":"2012-10-17",		 	 	 
          "Statement": [
              {
                  "Effect": "Allow",
                  "Action": "appmesh:StreamAggregatedResources",
                  "Resource": [
                      "arn:aws:appmesh:us-east-1:111122223333:mesh/my-mesh/virtualNode/my-service-a_my-apps"
                  ]
              }
          ]
      }
      ```

------

   1. 创建策略。

      ```
      aws iam create-policy --policy-name my-policy --policy-document file://proxy-auth.json
      ```

   1. 创建 IAM 角色，将您在上一步中创建的策略附加到该角色，创建 Kubernetes 服务账户并将策略绑定到该 Kubernetes 服务账户。该角色使控制器能够添加、删除和更改 App Mesh 资源。

      ```
      eksctl create iamserviceaccount \
          --cluster $CLUSTER_NAME \
          --namespace my-apps \
          --name my-service-a \
          --attach-policy-arn  arn:aws:iam::111122223333:policy/my-policy \
          --override-existing-serviceaccounts \
          --approve
      ```

      如果您更喜欢使用 AWS 管理控制台 或创建服务账户 AWS CLI，请参阅 A *mazon EKS 用户指南*[中的为您的服务账户创建 IAM 角色和策略](https://docs.aws.amazon.com/eks/latest/userguide/create-service-account-iam-policy-and-role.html#create-service-account-iam-role)。如果您使用 AWS 管理控制台 或 AWS CLI 来创建账户，则还需要将该角色映射到 Kubernetes 服务账户。有关更多信息，请参阅*《Amazon EKS 用户指南》*中的[为集群上的服务账户指定 IAM 角色](https://docs.aws.amazon.com/eks/latest/userguide/specify-service-account-role.html)。

1. （可选）如果您的部署要部署到 Fargate 容器组 (pod)，则需要创建 Fargate 配置文件。如果未安装 `eksctl`，则可以按照《Amazon EKS 用户指南》**中[安装或升级 `eksctl`](https://docs.aws.amazon.com/eks/latest/userguide/eksctl.html#installing-eksctl)上的说明安装它。如果您希望使用控制台创建配置文件，请参阅*《Amazon EKS 用户指南》*中的创建[ Fargate 配置文件](https://docs.aws.amazon.com/eks/latest/userguide/fargate-profile.html#create-fargate-profile)。

   ```
   eksctl create fargateprofile --cluster my-cluster --region Region-code --name my-service-a --namespace my-apps
   ```

1. 创建 Kubernetes 服务和部署。如果您有要和 App Mesh 配合使用的现有部署，则需要部署一个虚拟节点，就像在 [步骤 2：部署 App Mesh 资源](#configure-app-mesh) 的子步骤 `3` 中所做的那样。更新您的部署，确保其标签与您在虚拟节点上设置的标签相匹配，这样 sidecar 容器就会自动添加到容器组 (pod) 中，并重新部署容器组 (pod)。

   1. 将以下内容保存到计算机上名为 `example-service.yaml` 的文件中。如果您更改命名空间名称并使用 Fargate 容器组 (pod)，请确保命名空间名称与您在 Fargate 配置文件中定义的命名空间名称匹配。

      ```
      apiVersion: v1
      kind: Service
      metadata:
        name: my-service-a
        namespace: my-apps
        labels:
          app: my-app-1
      spec:
        selector:
          app: my-app-1
        ports:
          - protocol: TCP
            port: 80
            targetPort: 80
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: my-service-a
        namespace: my-apps
        labels:
          app: my-app-1
      spec:
        replicas: 3
        selector:
          matchLabels:
            app: my-app-1
        template:
          metadata:
            labels:
              app: my-app-1
          spec:
            serviceAccountName: my-service-a
            containers:
            - name: nginx
              image: nginx:1.19.0
              ports:
              - containerPort: 80
      ```
**重要**  
规范中 `app` `matchLabels` `selector` 中的值必须与您在 [步骤 2：部署 App Mesh 资源](#configure-app-mesh) 的子步骤 `3` 中创建虚拟节点时指定的值相匹配，否则 sidecar 容器将不会注入到容器组 (pod)中。在前面的示例中，标签的值为 `my-app-1`。如果您部署的是虚拟网关而不是虚拟节点，则 `Deployment` 清单应仅包含 Envoy 容器。有关要使用的镜像的更多信息，请参阅 [Envoy 镜像](envoy.md)。如需查看样本 manfest，请参阅中的[部署示例](https://github.com/aws/aws-app-mesh-examples/blob/main/walkthroughs/howto-k8s-ingress-gateway/v1beta2/manifest.yaml.template#L585)。 GitHub

   1. 部署服务。

      ```
      kubectl apply -f example-service.yaml
      ```

   1. 查看服务和部署。

      ```
      kubectl -n my-apps get pods
      ```

      Output

      ```
      NAME                            READY   STATUS    RESTARTS   AGE
      my-service-a-54776556f6-2cxd9   2/2     Running   0          10s
      my-service-a-54776556f6-w26kf   2/2     Running   0          18s
      my-service-a-54776556f6-zw5kt   2/2     Running   0          26s
      ```

   1. 查看已部署的容器组 (pod) 之一的详细信息。

      ```
      kubectl -n my-apps describe pod my-service-a-54776556f6-2cxd9
      ```

      缩减的输出

      ```
      Name:         my-service-a-54776556f6-2cxd9
      Namespace:    my-app-1
      Priority:     0
      Node:         ip-192-168-44-157.us-west-2.compute.internal/192.168.44.157
      Start Time:   Wed, 17 Jun 2020 11:08:59 -0500
      Labels:       app=nginx
                    pod-template-hash=54776556f6
      Annotations:  kubernetes.io/psp: eks.privileged
      Status:       Running
      IP:           192.168.57.134
      IPs:
        IP:           192.168.57.134
      Controlled By:  ReplicaSet/my-service-a-54776556f6
      Init Containers:
        proxyinit:
          Container ID:   docker://e0c4810d584c21ae0cb6e40f6119d2508f029094d0e01c9411c6cf2a32d77a59
          Image:          111345817488.dkr.ecr.us-west-2.amazonaws.com/aws-appmesh-proxy-route-manager:v2
          Image ID:       docker-pullable://111345817488.dkr.ecr.us-west-2.amazonaws.com/aws-appmesh-proxy-route-manager
          Port:           <none>
          Host Port:      <none>
          State:          Terminated
            Reason:       Completed
            Exit Code:    0
            Started:      Fri, 26 Jun 2020 08:36:22 -0500
            Finished:     Fri, 26 Jun 2020 08:36:22 -0500
          Ready:          True
          Restart Count:  0
          Requests:
            cpu:     10m
            memory:  32Mi
          Environment:
            APPMESH_START_ENABLED:         1
            APPMESH_IGNORE_UID:            1337
            APPMESH_ENVOY_INGRESS_PORT:    15000
            APPMESH_ENVOY_EGRESS_PORT:     15001
            APPMESH_APP_PORTS:             80
            APPMESH_EGRESS_IGNORED_IP:     169.254.169.254
            APPMESH_EGRESS_IGNORED_PORTS:  22
            AWS_ROLE_ARN:                  arn:aws:iam::111122223333:role/eksctl-app-mesh-addon-iamserviceaccount-my-a-Role1-NMNCVWB6PL0N
            AWS_WEB_IDENTITY_TOKEN_FILE:   /var/run/secrets/eks.amazonaws.com/serviceaccount/token
          ...
      Containers:
        nginx:
          Container ID:   docker://be6359dc6ecd3f18a1c87df7b57c2093e1f9db17d5b3a77f22585ce3bcab137a
          Image:          nginx:1.19.0
          Image ID:       docker-pullable://nginx
          Port:           80/TCP
          Host Port:      0/TCP
          State:          Running
            Started:      Fri, 26 Jun 2020 08:36:28 -0500
          Ready:          True
          Restart Count:  0
          Environment:
            AWS_ROLE_ARN:                 arn:aws:iam::111122223333:role/eksctl-app-mesh-addon-iamserviceaccount-my-a-Role1-NMNCVWB6PL0N
            AWS_WEB_IDENTITY_TOKEN_FILE:  /var/run/secrets/eks.amazonaws.com/serviceaccount/token
          ...
        envoy:
          Container ID:   docker://905b55cbf33ef3b3debc51cb448401d24e2e7c2dbfc6a9754a2c49dd55a216b6
          Image:          840364872350.dkr.ecr.us-west-2.amazonaws.com/aws-appmesh-envoy:v1.12.4.0-prod
          Image ID:       docker-pullable://840364872350.dkr.ecr.us-west-2.amazonaws.com/aws-appmesh-envoy
          Port:           9901/TCP
          Host Port:      0/TCP
          State:          Running
            Started:      Fri, 26 Jun 2020 08:36:36 -0500
          Ready:          True
          Restart Count:  0
          Requests:
            cpu:     10m
            memory:  32Mi
          Environment:
            APPMESH_RESOURCE_ARN:         arn:aws:iam::111122223333:mesh/my-mesh/virtualNode/my-service-a_my-apps
            APPMESH_PREVIEW:              0
            ENVOY_LOG_LEVEL:              info
            AWS_REGION:                   us-west-2
            AWS_ROLE_ARN:                 arn:aws:iam::111122223333:role/eksctl-app-mesh-addon-iamserviceaccount-my-a-Role1-NMNCVWB6PL0N
            AWS_WEB_IDENTITY_TOKEN_FILE:  /var/run/secrets/eks.amazonaws.com/serviceaccount/token
      ...
      Events:
        Type    Reason     Age   From                                                   Message
        ----    ------     ----  ----                                                   -------
        Normal  Pulling    30s   kubelet, ip-192-168-44-157.us-west-2.compute.internal  Pulling image "111345817488.dkr.ecr.us-west-2.amazonaws.com/aws-appmesh-proxy-route-manager:v2"
        Normal  Pulled     23s   kubelet, ip-192-168-44-157.us-west-2.compute.internal  Successfully pulled image "111345817488.dkr.ecr.us-west-2.amazonaws.com/aws-appmesh-proxy-route-manager:v2"
        Normal  Created    21s   kubelet, ip-192-168-44-157.us-west-2.compute.internal  Created container proxyinit
        Normal  Started    21s   kubelet, ip-192-168-44-157.us-west-2.compute.internal  Started container proxyinit
        Normal  Pulling    20s   kubelet, ip-192-168-44-157.us-west-2.compute.internal  Pulling image "nginx:1.19.0"
        Normal  Pulled     16s   kubelet, ip-192-168-44-157.us-west-2.compute.internal  Successfully pulled image "nginx:1.19.0"
        Normal  Created    15s   kubelet, ip-192-168-44-157.us-west-2.compute.internal  Created container nginx
        Normal  Started    15s   kubelet, ip-192-168-44-157.us-west-2.compute.internal  Started container nginx
        Normal  Pulling    15s   kubelet, ip-192-168-44-157.us-west-2.compute.internal  Pulling image "840364872350.dkr.ecr.us-west-2.amazonaws.com/aws-appmesh-envoy:v1.12.4.0-prod"
        Normal  Pulled     8s    kubelet, ip-192-168-44-157.us-west-2.compute.internal  Successfully pulled image "840364872350.dkr.ecr.us-west-2.amazonaws.com/aws-appmesh-envoy:v1.12.4.0-prod"
        Normal  Created    7s    kubelet, ip-192-168-44-157.us-west-2.compute.internal  Created container envoy
        Normal  Started    7s    kubelet, ip-192-168-44-157.us-west-2.compute.internal  Started container envoy
      ```

      在前面的输出中，您可以看到控制器已将 `proxyinit` 和 `envoy` 容器添加到容器组 (pod)。如果您将示例服务部署到 Fargate，则控制器会将 `envoy` 容器添加到容器组 (pod) 中，但 `proxyinit` 容器不是。

1. （可选）安装插件，例如 Prometheus、Grafana、Jaeger 和 Datadog。 AWS X-Ray有关更多信息，请参阅 [App Mesh 插件](https://github.com/aws/eks-charts#app-mesh-add-ons) GitHub 和《App Mesh 用户指南》的 “[可观察性](https://docs.aws.amazon.com/app-mesh/latest/userguide/observability.html)” 部分。

**注意**  
有关 App Mesh 的更多示例和演练，请参阅[ App Mesh 示例存储库](https://github.com/aws/aws-app-mesh-examples)。

## 步骤 4：清除
<a name="remove-integration"></a>

删除本教程中创建的所有示例资源。控制器还会删除在 `my-mesh` App Mesh 服务网格中创建的资源。

```
kubectl delete namespace my-apps
```

如果您为示例服务创建了 Fargate 配置文件，请将其删除。

```
eksctl delete fargateprofile --name my-service-a --cluster my-cluster --region Region-code
```

删除网格。

```
kubectl delete mesh my-mesh
```

（可选）您可以删除 Kubernetes 集成组件。

```
helm delete appmesh-controller -n appmesh-system
```

（可选）如果您将 Kubernetes 集成组件部署到 Fargate，请删除 Fargate 配置文件。

```
eksctl delete fargateprofile --name appmesh-system --cluster my-cluster --region Region-code
```

# 开始使用 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` 通过 HTTP/2 和端口 80 与 `serviceB` 通信。
+  您已部署 `serviceB` 的版本 2，并采用名称 `serviceBv2` 在 `apps.local` 命名空间中注册了该服务。

您的要求如下：
+ 您想将 75% 的流量从发送`serviceA`到`serviceB`，将 25% 的流量发送到`serviceBv2`第一个。通过仅向发送25％的流量`serviceBv2`，您就可以在发送来自的100％的流量之前验证它是否没有错误`serviceA`。
+ 您希望能够轻松调整流量权重，以便一旦证明 `serviceBv2` 可靠便可将 100% 的流量发送到该服务。将所有流量发送到 `serviceBv2` 后，您希望弃用 `serviceB`。
+ 您不想为了满足之前的要求而更改实际服务的任何现有应用程序代码或服务发现注册。

为了满足您的要求，您决定创建包含虚拟服务、虚拟节点、虚拟路由器和路由的 App Mesh 服务网格。实施您的网格后，更新使用 Envoy 代理的服务。更新后，您的服务将通过 Envoy 代理相互通信，而不是直接相互通信。

## 先决条件
<a name="prerequisites"></a>

App Mesh 支持在 DNS 中注册的 Linux 服务 AWS Cloud Map，或者两者兼而有之。要使用此入门指南，我们建议您提供三项已注册到 DNS 的现有服务。即使服务不存在，您也可以创建服务网格及其资源，但在部署实际服务之前，您无法使用网格。

如果您尚未运行服务，则可以启动 Amazon EC2 实例并向其部署应用程序。有关更多信息，请参阅亚马逊 EC2 用户指南中的[教程：亚马逊 EC2 Linux 实例入门](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-lamp-amazon-linux-2.html)。剩余步骤假定实际服务命名为 `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` 的虚拟服务。

您可以使用或 1.18.116 AWS 管理控制台 或更高 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. 在开始时打开 App Mesh 控制台的首次运行向导[https://console.aws.amazon.com/appmesh/。](https://console.aws.amazon.com/appmesh/get-started)

1. 对于**网格名称**，输入 **apps**。

1. 对于**虚拟服务名称**，输入 **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` 的实际服务。可使用主机名 `serviceb.apps.local`，通过 `DNS` 发现虚拟节点所表示的实际服务。或者，也可以使用 AWS Cloud Map发现实际服务。虚拟节点在端口 80 上使用 HTTP/2 协议监听流量。此外，还支持其他协议和运行状况检查。您将在后面的步骤中为 `serviceA` 和 `serviceBv2` 创建虚拟节点。

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

1. 对于**虚拟节点名称**，输入 **serviceB**。

1. 对于**服务发现方法**，选择 **DNS**，并为**DNS 主机名**输入 **serviceb.apps.local**。

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](routes.md)。

创建以下 资源：
+ 名为 `serviceB` 的虚拟路由器，因为 `serviceB.apps.local` 虚拟服务不会启动与任何其他服务的出站通信。请记住，您之前创建的虚拟服务是实际 `serviceb.apps.local` 服务的抽象。虚拟服务将流量发送到虚拟路由器。虚拟路由器采用 HTTP/2 协议在端口 80 上侦听流量。此外，还支持其他协议。
+ 名为 `serviceB` 的路由。它将 100% 的流量路由到`serviceB`虚拟节点。添加 `serviceBv2` 虚拟节点后，在稍后的步骤中出现权重。虽然本指南中未作介绍，但您可以为路由添加额外的筛选条件，并添加重试策略，从而使 Envoy 代理在遇到通信问题时会多次尝试将流量发送到虚拟节点。

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

1. 对于**虚拟路由器名称**，输入 **serviceB**。

1. 在**侦听器配置**下，为**协议**选择 **http2**，并为**端口**指定 **80**。

1. 对于**路由名称**，输入 **serviceB**。

1. 对于**路由类型**，选择 **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 管理控制台 ]

如果需要对任何部分进行任何更改，请选择**编辑**。在您对设置感到满意后，选择**创建网格**。

**状态**屏幕将显示已创建的所有网格资源。您可以通过选择**查看网格**来在控制台中查看创建的资源。

------
#### [ 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. 在左侧导航窗格中，选择**网格**。

1. 选择在上一步中创建的 `apps` 网格。

1. 在左侧导航窗格中，选择**虚拟节点**。

1. 选择**创建虚拟节点**。

1. 为**虚拟节点名称**输入 **serviceBv2**，为**服务发现方法**选择 **DNS**，并为 **DNS 主机名**输入 **servicebv2.apps.local**。

1. 对于**侦听器配置**，为**协议**选择 **http2**，并在**端口**中，输入 **80**。

1. 选择**创建虚拟节点**。

1. 再次选择**创建虚拟节点**。对于**虚拟节点名称**，输入 **serviceA**。对于**服务发现方法**，选择 **DNS**，并为 **DNS 主机名**输入 **servicea.apps.local**。

1. 在**新后端**下的**输入虚拟服务名称**中，输入 **serviceb.apps.local**。

1. 在**侦听器配置**下，为**协议**选择 **http2**，并在**端口**中输入 **80**，然后选择**创建虚拟节点**。

1. 在左侧导航窗格中，选择**虚拟路由器**，然后从列表中选择 `serviceB` 虚拟路由器。

1. 在**路由**下，选择在上一步中创建的名为 `ServiceB` 的路由，然后选择**编辑**。

1. 在**目标**、**虚拟节点名称**下，将 `serviceB` 的**权重**值更改为 **75**。

1. 选择**添加目标**，从下拉列表中选择 `serviceBv2`，然后将**权重**值设置为 **25**。

1. 选择**保存**。

1. 在左侧导航窗格中，选择**虚拟服务**，然后选择**创建虚拟服务**。

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 角色](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html#launch-instance-with-role)的 Amazon EC2 实例。

1. 通过 SSH 连接到实例。

1. 根据您的操作系统文档， AWS CLI 在您的实例上安装 Docker 和。

1. 对您希望 Docker 客户端从中拉取镜像的区域中的 Envoy 存储库进行身份验证：
   + 除 `me-south-1`、`ap-east-1`、`ap-southeast-3`、`eu-south-1`、`il-central-1` 和 `af-south-1` 以外的所有区域。您可以*us-west-2*替换为除了`me-south-1`、、、`ap-east-1``ap-southeast-3``eu-south-1``il-central-1`、和之外的任何[受支持区域](https://docs.aws.amazon.com/general/latest/gr/appmesh.html)`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. 运行下列命令之一，在您的实例上启动 Envoy 容器，具体取决于要从中拉取映像的区域。*apps*和*serviceB*值是在场景中定义的网格和虚拟节点名称。此信息告知代理要从 App Mesh 中读取的虚拟节点配置。要完成该场景，您还需要针对托管 `serviceBv2` 和 `serviceA` 虚拟节点所表示服务的 Amazon EC2 实例，完成这些步骤。对于您自己的应用程序，请将这些值替换为您自己的值。
   + 除 `me-south-1`、`ap-east-1`、`ap-southeast-3`、`eu-south-1`、`il-central-1` 和 `af-south-1` 以外的所有区域。您可以*Region-code*替换为除了`me-south-1`、、、`ap-east-1``ap-southeast-3``eu-south-1``il-central-1`、和[区域之外的任何受支持](https://docs.aws.amazon.com/general/latest/gr/appmesh.html)`af-south-1`区域。您可以将 `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-prod 或更高版本与 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](https://github.com/aws/aws-app-mesh-examples) 的更多示例和演练，请参阅 App Mesh 示例存储库。

# App Mesh 示例
<a name="examples"></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 中显示的 end-to-end演练和与各种 AWS 服务集成的代码示例：

[App Mesh 示例](https://github.com/aws/aws-app-mesh-examples)