Amazon App Mesh 和 Amazon EC2 入门 - Amazon App Mesh
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

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

Amazon App Mesh 和 Amazon EC2 入门

本主题将帮助您配合使用 Amazon App Mesh 和在 Amazon EC2 上运行的实际服务。本教程介绍了多种 App Mesh 资源类型的基本功能。

情况

为了说明如何配合使用 App Mesh,假定您有一个具有以下功能的应用程序:

  • 由名为 serviceAserviceB 的两项服务组成。

  • 这两项服务均注册到名为 apps.local 的命名空间。

  • ServiceA 通过 HTTP/2 和端口 80 与 serviceB 通信。

  • 您已部署 serviceB 的版本 2,并采用名称 serviceBv2apps.local 命名空间中注册了该服务。

您的要求如下:

  • 您希望将 75% 的流量从 serviceA 发送到 serviceB,并将 25% 的流量发送到 serviceBv2,以验证在将 100% 的流量从 serviceA 发送到它之前,serviceBv2 没有错误。

  • 您希望能够轻松调整流量权重,以便一旦证明 serviceBv2 可靠便可将 100% 的流量发送到该服务。将所有流量发送到 serviceBv2 后,您希望不再使用 serviceB

  • 您不希望必须更改实际服务的任何现有应用程序代码或服务发现注册,才能满足以前的要求。

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

先决条件

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

如果还没有 Amazon EC2 实例,可以在上面部署应用程序。有关更多信息,请参阅适用于 Linux 实例的《Amazon EC2 用户指南》中的教程:Amazon EC2 Linux 实例入门。剩余步骤假定实际服务命名为 serviceAserviceBserviceBv2,并且可以在名为 apps.local 的命名空间中发现所有服务。

步骤 1:创建网格和虚拟服务

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

创建以下资源:

  • 名为 apps 的网格,因为此场景中的所有服务均注册到 apps.local 命名空间。

  • 名为 serviceb.apps.local 的虚拟服务,因为虚拟服务表示可以使用该名称发现的服务,并且您不希望更改代码以引用其他名称。稍后的步骤中将添加名为 servicea.apps.local 的虚拟服务。

您可以使用 Amazon Web Services Management Console 或 Amazon CLI 版本 1.18.116 或更高版本或者版本 2.0.38 或更高版本来完成以下步骤。如果使用 Amazon CLI,请使用 aws --version 命令检查已安装的 Amazon CLI 版本。如果您没有安装版本 1.18.116 或更高版本或者没有安装版本 2.0.38 或更高版本,则必须安装或更新 Amazon CLI。选择要使用的工具所对应的选项卡。

Amazon Web Services Management Console
  1. 打开 App Mesh 控制台首次运行向导,网址为 https://console.aws.amazon.com/appmesh/get-started

  2. 对于网格名称,输入 apps

  3. 对于虚拟服务名称,输入 serviceb.apps.local

  4. 要继续,请选择 Next

Amazon CLI
  1. 使用 create-mesh 命令创建网格。

    aws appmesh create-mesh --mesh-name apps
  2. 使用 create-virtual-service 命令创建虚拟服务。

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

步骤 2:创建虚拟节点

虚拟节点充当实际服务的逻辑指针。有关更多信息,请参阅 虚拟节点

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

Amazon Web Services Management Console
  1. 对于虚拟节点名称,输入 serviceB

  2. 对于服务发现方法,选择 DNS,并为 DNS 主机名输入 serviceb.apps.local

  3. 侦听器配置下,为协议选择 http2,并在端口中,输入 80

  4. 要继续,请选择 Next

Amazon CLI
  1. 使用以下内容创建名为 create-virtual-node-serviceb.json 的文件:

    { "meshName": "apps", "spec": { "listeners": [ { "portMapping": { "port": 80, "protocol": "http2" } } ], "serviceDiscovery": { "dns": { "hostname": "serviceB.apps.local" } } }, "virtualNodeName": "serviceB" }
  2. 采用 JSON 文件作为输入,使用 create-virtual-node 命令创建虚拟节点。

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

步骤 3:创建虚拟路由器和路由

虚拟路由器路由网格中一个或多个虚拟服务的流量。有关更多信息,请参阅 虚拟路由器路由

创建以下资源:

  • 名为 serviceB 的虚拟路由器,因为 serviceB.apps.local 虚拟服务不会启动与任何其他服务的出站通信。请记住,您之前创建的虚拟服务是实际 serviceb.apps.local 服务的抽象。虚拟服务将流量发送到虚拟路由器。虚拟路由器采用 HTTP/2 协议在端口 80 上侦听流量。此外,还支持其他协议。

  • 名为 serviceB 的路由。它将 100% 的流量路由到 serviceB 虚拟节点。添加 serviceBv2 虚拟节点后,您将在稍后的步骤中更改权重。虽然本指南中未作介绍,但您可以为路由添加额外的筛选条件,并添加重试策略,从而使 Envoy 代理在遇到通信问题时会多次尝试将流量发送到虚拟节点。

Amazon Web Services Management Console
  1. 对于虚拟路由器名称,输入 serviceB

  2. 侦听器配置下,为协议选择 http2,并为端口指定 80

  3. 对于路由名称,输入 serviceB

  4. 对于路由类型,选择 http2

  5. 目标配置下的虚拟节点名称中,选择 serviceB,并为权重输入 100

  6. 匹配配置下,选择一种方法

  7. 要继续,请选择 Next

Amazon CLI
  1. 创建虚拟路由器。

    1. 使用以下内容创建名为 create-virtual-router.json 的文件:

      { "meshName": "apps", "spec": { "listeners": [ { "portMapping": { "port": 80, "protocol": "http2" } } ] }, "virtualRouterName": "serviceB" }
    2. 采用 JSON 文件作为输入,使用 create-virtual-router 命令创建虚拟路由器。

      aws appmesh create-virtual-router --cli-input-json file://create-virtual-router.json
  2. 创建路由。

    1. 使用以下内容创建名为 create-route.json 的文件:

      { "meshName" : "apps", "routeName" : "serviceB", "spec" : { "httpRoute" : { "action" : { "weightedTargets" : [ { "virtualNode" : "serviceB", "weight" : 100 } ] }, "match" : { "prefix" : "/" } } }, "virtualRouterName" : "serviceB" }
    2. 采用 JSON 文件作为输入,使用 create-route 命令创建路由。

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

步骤 4:审核并创建

根据之前的说明审核设置。

Amazon Web Services Management Console

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

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

Amazon CLI

使用 describe-mesh 命令查看所创建网格的设置。

aws appmesh describe-mesh --mesh-name apps

使用 describe-virtual-service 命令查看所创建的虚拟服务的设置。

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

使用 describe-virtual-node 命令查看所创建的虚拟节点的设置。

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

使用 describe-virtual-router 命令查看所创建的虚拟路由器的设置。

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

使用 describe-route 命令查看所创建路由的设置。

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

步骤 5:创建其他资源

要完成此场景,您需要执行以下操作:

  • 创建名为 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 虚拟服务将流量发送到虚拟路由器,该路由器将流量路由到虚拟节点。虚拟节点的服务发现名称可以随时更改。

Amazon Web Services Management Console
  1. 在左侧导航窗格中,选择网格

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

  3. 在左侧导航窗格中,选择虚拟节点

  4. 选择创建虚拟节点

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

  6. 对于侦听器配置,为协议中选择 http2,并在端口中,输入 80

  7. 选择创建虚拟节点

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

  9. 新后端下的输入虚拟服务名称中,输入 serviceb.apps.local

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

  11. 在左侧导航窗格中,选择虚拟路由器,然后从列表中选择 serviceB 虚拟路由器。

  12. 路由下,选择在上一步中创建的名为 ServiceB 的路由,然后选择编辑

  13. 目标虚拟节点名称下,将 serviceB权重值更改为 75

  14. 选择添加目标,从下拉列表中选择 serviceBv2,然后将权重值设置为 25

  15. 选择保存

  16. 在左侧导航窗格中,选择虚拟服务,然后选择创建虚拟服务

  17. 针对虚拟服务名称输入 servicea.apps.local,为提供者选择虚拟节点,为虚拟节点选择 serviceA,然后选择创建虚拟服务。

Amazon 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" }
    2. 创建虚拟节点。

      aws appmesh create-virtual-node --cli-input-json file://create-virtual-node-servicebv2.json
  2. 创建 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" }
    2. 创建虚拟节点。

      aws appmesh create-virtual-node --cli-input-json file://create-virtual-node-servicea.json
  3. 更新在上一步中创建的 serviceb.apps.local 虚拟服务,以将其流量发送到 serviceB 虚拟路由器。最初创建虚拟服务时,它不会向任何位置发送流量,因为尚未创建 serviceB 虚拟路由器。

    1. 使用以下内容创建名为 update-virtual-service.json 的文件:

      { "meshName" : "apps", "spec" : { "provider" : { "virtualRouter" : { "virtualRouterName" : "serviceB" } } }, "virtualServiceName" : "serviceb.apps.local" }
    2. 使用 update-virtual-service 命令更新虚拟服务。

      aws appmesh update-virtual-service --cli-input-json file://update-virtual-service.json
  4. 更新在上一步中创建的 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" }
    2. 使用 update-route 命令更新路由。

      aws appmesh update-route --cli-input-json file://update-route.json
  5. 创建 serviceA 虚拟服务。

    1. 使用以下内容创建名为 create-virtual-servicea.json 的文件:

      { "meshName" : "apps", "spec" : { "provider" : { "virtualNode" : { "virtualNodeName" : "serviceA" } } }, "virtualServiceName" : "servicea.apps.local" }
    2. 创建虚拟服务。

      aws appmesh create-virtual-service --cli-input-json file://create-virtual-servicea.json
网格摘要

在创建服务网格之前,您具有三个名为 servicea.apps.localserviceb.apps.localservicebv2.apps.local 的实际服务。除实际服务之外,现在您还具有一个服务网格,其中包含用以表示实际服务的以下资源:

  • 两个虚拟服务。代理通过虚拟路由器将所有流量从 servicea.apps.local 虚拟服务发送到 serviceb.apps.local 虚拟服务。

  • 三个名为 serviceAserviceBserviceBv2 的虚拟节点。Envoy 代理使用为虚拟节点配置的服务发现信息来查找实际服务的 IP 地址。

  • 一个虚拟路由器,其路由指示 Envoy 代理将 75% 的入站流量路由到 serviceB 虚拟节点,将 25% 的流量路由到 serviceBv2 虚拟节点。

步骤 6:更新服务

创建网格后,您需要完成以下任务:

  • 授予随每项服务部署的 Envoy 代理读取一个或多个虚拟节点配置的权限。有关如何向代理授权的更多信息,请参阅 Envoy Proxy 授权

  • 要更新现有服务,请完成以下步骤。

将 Amazon EC2 实例配置为虚拟节点成员
  1. 创建一个 IAM 角色。

    1. 使用以下内容创建名为 ec2-trust-relationship.json 的文件。

      { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "ec2.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }
    2. 使用以下命令创建 IAM 角色。

      aws iam create-role --role-name mesh-virtual-node-service-b --assume-role-policy-document file://ec2-trust-relationship.json
  2. 将 IAM 策略附加到该角色,这将允许它仅从 Amazon ECR 中读取特定 App Mesh 虚拟节点的配置。

    1. 使用以下内容创建名为 virtual-node-policy.json 的文件。apps 是您在 步骤 1:创建网格和虚拟服务 中创建的网格的名称,serviceB 是您在 步骤 2:创建虚拟节点 中创建的虚拟节点的名称。将 111122223333 替换为您的账户 ID,并将 us-west-2 替换为已在其中创建网格的区域。

      { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "appmesh:StreamAggregatedResources", "Resource": [ "arn:aws:appmesh:us-west-2:111122223333:mesh/apps/virtualNode/serviceB" ] } ] }
    2. 使用以下命令创建策略。

      aws iam create-policy --policy-name virtual-node-policy --policy-document file://virtual-node-policy.json
    3. 将您在上一步中创建的策略附加到角色,以便角色仅从 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
    4. AmazonEC2ContainerRegistryReadOnly 托管策略附加到角色,以便它可以从 Amazon ECR 中提取 Envoy 容器映像。

      aws iam attach-role-policy --policy-arn arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly --role-name mesh-virtual-node-service-b
  3. 启动带创建的 IAM 角色的 Amazon EC2 实例。

  4. 通过 SSH 连接到实例。

  5. 按照操作系统文档,在实例上安装 Docker 和 Amazon CLI。

  6. 对您希望 Docker 客户端从中拉取镜像的区域中的 Envoy 存储库进行身份验证:

    • me-south-1ap-east-1ap-southeast-3eu-south-1il-central-1af-south-1 以外的所有区域。您可以用任何受支持区域替换us-west-2,但me-south-1ap-east-1ap-southeast-3eu-south-1il-central-1af-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
  7. 运行下列命令之一,在您的实例上启动 Envoy 容器,具体取决于要从中拉取映像的区域。appsserviceB 值是场景中定义的网格和虚拟节点名称。此信息告知代理要从 App Mesh 中读取的虚拟节点配置。要完成该场景,您还需要针对托管 serviceBv2serviceA 虚拟节点所表示服务的 Amazon EC2 实例,完成这些步骤。对于您自己的应用程序,请将这些值替换为您自己的值。

    • me-south-1ap-east-1ap-southeast-3eu-south-1il-central-1af-south-1 以外的所有区域。您可以将 Region-code 替换为除me-south-1ap-east-1ap-southeast-3eu-south-1il-central-1af-south-1 区域之外的任何受支持区域。您可以将 1337 替换为介于 02147483647 之间的任何值。

      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.27.2.0-prod
    • me-south-1 区域。您可以将 1337 替换为介于 02147483647 之间的任何值。

      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.27.2.0-prod
    • ap-east-1 区域。您可以将 1337 替换为介于 02147483647 之间的任何值。

      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.27.2.0-prod
    注意

    APPMESH_RESOURCE_ARN 属性需要版本 1.15.0 或更高版本的 Envoy 映像。有关更多信息,请参阅Envoy 镜像

    重要

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

  8. 在下面选择 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
  9. 要配置 iptables 规则以将应用程序流量路由到 Envoy 代理,请运行您在上一步中创建的脚本。

    sudo ./envoy-networking.sh
  10. 启动虚拟节点应用程序代码。

注意

有关 App Mesh 的更多示例和演练,请参阅 App Mesh 示例存储库。