

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

# App Mesh 시작하기
<a name="getting-started"></a>

**중요**  
지원 종료 공지: 2026년 9월 30일에 AWS 는에 대한 지원을 중단합니다 AWS App Mesh. 2026년 9월 30일 이후에는 AWS App Mesh 콘솔 또는 AWS App Mesh 리소스에 더 이상 액세스할 수 없습니다. 자세한 내용은이 블로그 게시물 [Migrating from to Amazon ECS Service Connect를 참조 AWS App Mesh 하세요](https://aws.amazon.com/blogs/containers/migrating-from-aws-app-mesh-to-amazon-ecs-service-connect).

Amazon ECS, Kubernetes(자체 Amazon EC2 인스턴스에 배포하거나 Amazon EKS에서 실행) 및 Amazon EC2에 배포하는 애플리케이션에서 App Mesh를 사용할 수 있습니다. 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 리소스에 더 이상 액세스할 수 없습니다. 자세한 내용은이 블로그 게시물 [Migrating from to Amazon ECS Service Connect를 참조 AWS App Mesh 하세요](https://aws.amazon.com/blogs/containers/migrating-from-aws-app-mesh-to-amazon-ecs-service-connect).

이 주제는 Amazon ECS에서 실행 중인 실제 서비스와 AWS App Mesh 함께를 사용하는 데 도움이 됩니다. 이 자습서에서는 몇 가지 App Mesh 리소스 유형의 기본 기능을 다룹니다.

## 시나리오
<a name="scenario"></a>

App Mesh를 사용하는 방법을 설명하기 위해 다음과 같은 특징을 가진 애플리케이션이 있다고 가정합니다.
+ `serviceA`및 `serviceB`라는 두 개의 서비스로 구성됩니다.
+ 두 서비스 모두 `apps.local`이라는 네임스페이스에 등록됩니다.
+ `ServiceA`는 HTTP/2, 포트 80을 통해 `serviceB`와 통신합니다.
+  `serviceB`의 버전 2를 이미 배포했고 `apps.local` 네임스페이스에 `serviceBv2` 이름으로 등록했습니다.

다음과 같은 요구 사항이 있습니다.
+ 에서 로 트래픽의 75%`serviceA`를 전송`serviceB`하고 트래픽의 25%를 `serviceBv2` 먼저 전송하려고 합니다. 에 25%만 전송하면에서 트래픽의 100%를 전송하기 전에 버그가 없는지 확인할 `serviceBv2`수 있습니다`serviceA`.
+ 트래픽이 신뢰할 수 있는 것으로 입증되면 해당 트래픽의 100%가 `serviceBv2`로 이동하도록 트래픽 가중치를 쉽게 조정할 수 있기를 원합니다. 모든 트래픽이 `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 리소스에 더 이상 액세스할 수 없습니다. 자세한 내용은이 블로그 게시물 [Migrating from to Amazon ECS Service Connect를 참조 AWS App Mesh 하세요](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 ECS 개념에 대한 기존의 이해. 자세한 내용을 알아보려면 Amazon Elastic Container Service 개발자 안내서의 [Amazon ECS란?](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/Welcome.html)을 참조하세요.
+ App Mesh는 DNS AWS Cloud Map또는 둘 다에 등록된 Linux 서비스를 지원합니다. 이 시작 안내서를 사용하려면 DNS에 등록된 기존 서비스 3개가 있으면 좋습니다. 이 주제의 절차에서는 기존 서비스의 이름이 `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.local` 네임스페이스에 등록되기 때문에 `apps`이라는 메시를 생성합니다.
+ 가상 서비스는 해당 이름으로 검색할 수 있는 서비스를 나타내며 다른 이름을 참조하도록 코드를 변경하고 싶지 않기 때문에 `serviceb.apps.local`이라는 이름의 가상 서비스를 생성합니다. `servicea.apps.local`이라는 이름의 가상 서비스는 이후 단계에서 추가됩니다.

 AWS Management Console 또는 AWS CLI 버전 1.18.116 이상 또는 2.0.38 이상을 사용하여 다음 단계를 완료할 수 있습니다. 를 사용하는 경우 `aws --version` 명령을 AWS CLI사용하여 설치된 AWS CLI 버전을 확인합니다. 버전 1.18.116 이상 또는 2.0.38 이상이 설치되어 있지 않으면 [AWS CLI를 설치하거나 업데이트](https://docs.aws.amazon.com/cli/latest/reference/appmesh/cli-chap-install.html)해야 합니다. 사용할 도구의 탭을 선택합니다.

------
#### [ AWS Management Console ]

1. [https://console.aws.amazon.com/appmesh/get-started](https://console.aws.amazon.com/appmesh/get-started)에서 App Mesh 콘솔 처음 실행 마법사를 엽니다.

1. **Mesh name(메시 이름)**에 **apps**를 입력합니다.

1. **Virtual service name(가상 서비스 이름)**에 **serviceb.apps.local**를 입력합니다.

1. 계속하려면 **다음**을 선택합니다.

------
#### [ 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. 가상 노드는 포트 80에서 HTTP/2 프로토콜을 사용하여 트래픽을 수신합니다. 상태 확인과 마찬가지로 다른 프로토콜도 지원됩니다. 이후 단계에서 `serviceA` 및 `serviceBv2`에 대한 가상 노드를 생성합니다.

------
#### [ AWS Management Console ]

1. **Virtual node name(가상 노드 이름)**에 **serviceB**를 입력합니다.

1. **서비스 검색 방법**에 대해 **DNS**를 선택하고 **DNS 호스트 이름**에 대해 **serviceb.apps.local**을 입력합니다.

1. **리스너 구성**에서 **프로토콜**로 **http2**를 선택하고 **포트**로 **80**을 입력합니다.

1. 계속하려면 **다음**을 선택합니다.

------
#### [ 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` 서비스를 추상화한 것입니다. 가상 서비스는 가상 라우터로 트래픽을 보냅니다. 가상 라우터는 포트 80에서 HTTP/2 프로토콜을 사용하여 트래픽을 수신합니다. 다른 프로토콜도 지원됩니다.
+ `serviceB`라는 이름의 라우팅. 트래픽을 100% `serviceB` 가상 노드로 라우팅합니다. `serviceBv2` 가상 노드를 추가한 후 이후 단계에서 가중치가 변경됩니다. 이 안내서에서는 다루지 않지만 해당 라우팅에 대한 필터 조건을 추가하고 재시도 정책을 추가하여 통신 문제가 발생할 경우 Envoy 프록시가 가상 노드에 트래픽을 여러 번 보내도록 할 수 있습니다.

------
#### [ AWS Management Console ]

1. **Virtual router name(가상 라우터 이름)**에 **serviceB**를 입력합니다.

1. **리스너 구성**에서 **프로토콜**로 **http2**를 선택하고 **포트**로 **80**을 지정합니다.

1. **Route Name(라우팅 이름)**에 **serviceB**를 입력합니다.

1. **루트 유형**에 대해 **http2**를 선택합니다.

1. **대상 구성**의 **가상 노드 이름**에 대해 `serviceB`를 선택하고 **가중치**로 **100**을 입력합니다.

1. **일치 구성**에서 **방법**을 선택합니다.

1. 계속하려면 **다음**을 선택합니다.

------
#### [ 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 Management Console ]

섹션에서 변경해야 할 경우 **편집**을 선택합니다. 설정에 만족하면 **메시 생성**을 선택합니다.

**상태** 화면에는 생성된 모든 메시 리소스가 표시됩니다. **메시 보기**를 선택하여 콘솔에서 생성된 리소스를 볼 수 있습니다.

------
#### [ 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` 가상 노드로 직접 전송됩니다.
+ 트래픽의 75%를 `serviceB` 가상 노드로 보내고 트래픽의 25%를 `serviceBv2` 가상 노드로 보내도록 이전 단계에서 생성한 `serviceB` 라우팅을 업데이트합니다. 시간이 지남에 따라 `serviceBv2`가 트래픽의 100%를 수신할 때까지 가중치를 계속 수정할 수 있습니다. 모든 트래픽이 `serviceBv2`로 전송되면 `serviceB` 가상 노드와 실제 서비스를 종료하고 중단할 수 있습니다. `serviceb.apps.local` 가상 및 실제 서비스 이름이 변경되지 않으므로 가중치를 변경할 때 코드를 수정할 필요가 없습니다. `serviceb.apps.local` 가상 서비스는 트래픽을 가상 라우터로 전송하여 트래픽을 가상 노드로 라우팅한다는 점을 기억하십시오. 가상 노드의 서비스 검색 이름은 언제든지 변경할 수 있습니다.

------
#### [ AWS Management Console ]

1. 왼쪽 탐색 창에서 **Meshes(메시)**를 선택합니다.

1. 이전 단계에서 생성한 `apps` 메시를 선택합니다.

1. 왼쪽 탐색 창에서 **Virtual node(가상 노드)**를 선택합니다.

1. **Create virtual node(가상 노드 생성)**를 선택합니다.

1. **가상 노드 이름**에 대해 **serviceBv2**를 입력하고, **서비스 검색 방법**에 대해 **DNS**를 선택하고 **DNS 호스트 이름**에 대해 **servicebv2.apps.local**을 입력합니다.

1. **리스너 구성**에서 **프로토콜**로 **http2**를 선택하고 **포트**로 **80**을 입력합니다.

1. **Create virtual node(가상 노드 생성)**를 선택합니다.

1. **가상 노드 생성**을 다시 선택합니다. **가상 노드 이름**에 **serviceA**를 입력합니다. **서비스 검색 방법**에 대해 **DNS**를 선택하고 **DNS 호스트 이름**에 대해 **servicea.apps.local**을 입력합니다.

1. **새 백엔드**에서 **가상 서비스 이름 입력**에 **serviceb.apps.local**을 입력합니다.

1. **리스너 구성**에서 **프로토콜**로 **http2**를 선택하고 **포트**에 **80**을 입력한 다음, **가상 노드 생성**을 선택합니다.

1. 왼쪽 탐색 창에서 **Virtual routers(가상 라우터)**를 선택한 다음 목록에서 `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)를 참조하십시오.
+ Envoy 프록시를 사용하도록 기존 Amazon ECS 태스크 정의를 각각 업데이트합니다.

**자격 증명**  
Envoy 컨테이너에는 App Mesh 서비스로 전송되는 요청에 서명하기 위한 AWS Identity and Access Management 자격 증명이 필요합니다. 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 메타데이터 서버에 액세스할 수 없습니다. 이러한 자격 증명을 제공하려면 Linux의 Fargate 컨테이너 유형으로 배포된 태스크에 IAM 태스크 역할을 연결해야 합니다.

태스크를 Amazon EC2 시작 유형으로 배포하고 Amazon EC2 메타데이터 서버에 대한 액세스가 차단된 경우 [태스크에 대한 IAM 역할](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html)의 *중요* 주석에 설명된 것처럼 태스크 IAM 역할도 태스크에 연결해야 합니다. 인스턴스 또는 태스크에 할당하는 역할에는 [프록시 권한 부여](https://docs.aws.amazon.com/app-mesh/latest/userguide/proxy-authorization.html)에 설명된 대로 IAM 정책이 연결되어 있어야 합니다.



**를 사용하여 작업 정의를 업데이트하려면 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를 구성할 수 없습니다.

### 태스크 정의 ARN
<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`로 보고될 때까지 기다립니다. 다음 코드는 이 종속성이 있는 애플리케이션 컨테이너 정의 예제를 보여줍니다. 다음 예제의 모든 속성이 필요합니다. 일부 속성 값도 필요하지만 일부는 *대체 가능*합니다.

```
{
	"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) 모든 리전은 *리전 코드를* `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 roadmap issue(GitHub 로드맵 문제)](https://github.com/aws/aws-app-mesh-roadmap/issues/10)를 참조하십시오.

다음 예제의 모든 속성이 필요합니다. 일부 속성 값도 필요하지만 일부는 *대체 가능*합니다.

**참고**  
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는 Envoy가 지표 및 트레이스에서 자신을 참조할 때 `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 시작 유형 모두에 대한 태스크를 생성하는 예제가 제공됩니다. *대체 가능* 값을 적절히 변경하여 시나리오에서 이름이 `taskA` 및 `taskBv2`인 태스크의 태스크 정의를 생성합니다. `APPMESH_RESOURCE_ARN` 값에 대한 메시 이름 및 가상 노드 이름과, 애플리케이션이 프록시 구성 `AppPorts` 값을 수신하는 포트 목록을 대체합니다. 기본적으로 App Mesh는 Envoy가 지표 및 트레이스에서 자신을 참조할 때 `APPMESH_RESOURCE_ARN`에서 지정한 리소스의 이름을 사용합니다. `APPMESH_RESOURCE_CLUSTER` 환경 변수를 사용자 고유의 이름으로 설정하여 이 동작을 재정의할 수 있습니다. 다음 예제의 모든 속성이 필요합니다. 일부 속성 값도 필요하지만 일부는 *대체 가능*합니다.

자격 증명 단원에 설명된 대로 Amazon ECS 태스크를 실행 중인 경우에는 기존 [태스크 IAM 역할](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html)을 예제에 추가해야 합니다.

**중요**  
Fargate는 1024보다 큰 포트 값을 사용해야 합니다.

**Example Amazonz 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 JSON for Amazon ECS 작업 정의 AWS X-Ray - Linux 컨테이너의 Fargate**  
X-Ray에서는 사용자가 트래픽 흐름을 시각화하는 데 사용할 수 있는 도구를 애플리케이션이 다루고 제공해야 한다는 요청에 대한 데이터를 수집할 수 있습니다. Envoy에 대한 X-Ray 드라이버를 사용하면 Envoy가 추적 정보를 X-Ray에 보고할 수 있습니다. [Envoy 구성](https://docs.aws.amazon.com/app-mesh/latest/userguide/envoy.html)을 사용하여 X-Ray 추적 기능을 활성화할 수 있습니다. 구성에 따라 Envoy는 [사이드카](https://docs.aws.amazon.com/xray/latest/devguide/xray-daemon-ecs.html) 컨테이너로 실행되는 X-Ray 대몬(daemon)에 추적 데이터를 보내고 대몬(daemon)은 추적을 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 JSON for Amazon ECS 작업 정의 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를 사용한 Canary 배포
<a name="canary-appmesh-ecs"></a>

Canary 배포 및 릴리스를 통해 애플리케이션의 이전 버전과 새로 배포된 버전 간에 트래픽을 전환할 수 있습니다. 또한 새로 배포된 버전의 상태도 모니터링됩니다. 새 버전에 문제가 있는 경우 Canary 배포는 자동으로 트래픽을 이전 버전으로 다시 전환할 수 있습니다. Canary 배포를 통해 보다 강력하게 애플리케이션 버전 간에 트래픽을 전환할 수 있습니다.

App Mesh를 사용하여 Amazon ECS용 Canary 배포를 구현하는 방법에 대한 자세한 내용은 [App Mesh를 사용하여 Amazon ECS용 Canary 배포를 포함하는 파이프라인 생성](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 리소스에 더 이상 액세스할 수 없습니다. 자세한 내용은이 블로그 게시물 [Migrating from to Amazon ECS Service Connect를 참조 AWS App Mesh 하세요](https://aws.amazon.com/blogs/containers/migrating-from-aws-app-mesh-to-amazon-ecs-service-connect).

Kubernetes용 App Mesh 컨트롤러를 사용하여 Kubernetes AWS App Mesh 와 통합하면 Kubernetes를 통해 메시, 가상 서비스, 가상 노드, 가상 라우터 및 경로와 같은 App Mesh 리소스를 관리합니다. 또한 App Mesh 사이드카 컨테이너 이미지를 Kubernetes 포드 사양에 자동으로 추가합니다. 이 자습서에서는 Kubernetes용 App Mesh 컨트롤러를 설치하여 이러한 통합을 활성화하는 방법을 안내합니다.

컨트롤러에는 Kubernetes 사용자 지정 리소스 정의(`meshes`, `virtual services`, `virtual nodes` 및 `virtual routers`)의 배포가 포함됩니다. 컨트롤러는 사용자 지정 리소스의 생성, 수정, 삭제를 감시하고 App Mesh 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)를 참조하십시오.

또한 컨트롤러는 사용자가 지정한 이름으로 레이블이 지정된 Kubernetes 포드에 다음 컨테이너를 삽입하는 웹훅을 설치합니다.
+ **App Mesh Envoy 프록시** - Envoy는 App Mesh 컨트롤 영역에 정의된 구성을 사용하여 애플리케이션 트래픽을 전송할 위치를 결정합니다.
+ **App Mesh 프록시 경로 관리자** - 포드의 네트워크 네임스페이스에서 Envoy를 통한 인바운드 및 아웃바운드 트래픽을 라우팅하는 `iptables` 규칙을 업데이트합니다. 이 컨테이너는 포드 내부의 Kubernetes 초기화 컨테이너로 실행됩니다.

## 사전 조건
<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)를 참조하세요.** Amazon EC2에서 자체 Kubernetes 클러스터를 실행하는 경우 Envoy 이미지가 있는 Amazon ECR 리포지토리에 Docker가 인증되었는지 확인합니다. 자세한 내용은 Amazon Elastic Container Registry 사용 설명서의 [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 AWS Cloud Map또는 둘 다에 등록된 Linux 서비스를 지원합니다. 이 시작 안내서를 사용하려면 DNS에 등록된 기존 서비스 3개가 있으면 좋습니다. 이 주제의 절차에서는 기존 서비스의 이름이 `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이 설치되어 있지 않은 경우 Amazon EKS 사용 설명서의 [Amazon EKS에서 Helm 사용](https://docs.aws.amazon.com/eks/latest/userguide/helm.html)을 참조하세요.**
+ Amazon EKS는 현재 `IPv4_ONLY` 및 `IPv6_ONLY` 전용 IP 기본 설정을 지원합니다. Amazon EKS는 현재 `IPv4` 트래픽만 또는 `IPv6` 트래픽만 처리할 수 있는 포드만 지원하기 때문입니다.

나머지 단계에서는 실제 서비스의 이름이 `serviceA`, `serviceB` 및 `serviceBv2`이고 `apps.local`이라는 네임스페이스를 통해 모든 서비스를 검색할 수 있다고 가정합니다.

## 1단계: 통합 구성 요소 설치
<a name="install-controller"></a>

App Mesh에 사용할 포드를 호스팅하는 각 클러스터에 통합 구성 요소를 한 번 설치합니다.

**통합 구성 요소를 설치하려면**

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`를 반환하면 다음 단계로 진행할 수 있습니다. 다른 메시지가 반환되면 계속하기 전에 업그레이드 단계를 완료해야 합니다. 시험판 버전 업그레이드에 대한 자세한 내용은 GitHub에서 [업그레이드](https://github.com/aws/eks-charts/blob/master/stable/appmesh-controller/README.md#upgrade)를 참조하십시오.

1. Helm에 `eks-charts` 리포지토리를 추가합니다.

   ```
   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)의 지침에 따라 설치할 수 있습니다.** 콘솔을 사용하여 공급자를 생성하려면 Amazon 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 Management Console 또는를 사용하여 서비스 계정을 생성하려면 *Amazon EKS 사용 설명서*의 서비스 계정에 대한 IAM 역할 및 정책 생성을 AWS CLI참조하세요. [https://docs.aws.amazon.com/eks/latest/userguide/create-service-account-iam-policy-and-role.html#create-service-account-iam-role](https://docs.aws.amazon.com/eks/latest/userguide/create-service-account-iam-policy-and-role.html#create-service-account-iam-role) AWS Management Console 또는를 사용하여 계정을 AWS CLI 생성하는 경우 역할을 Kubernetes 서비스 계정에 매핑해야 합니다. 자세한 내용을 알아보려면 Amazon EKS 사용 설명서의 [서비스 계정에 대한 IAM 역할 지정](https://docs.aws.amazon.com/eks/latest/userguide/specify-service-account-role.html)를 참조하세요.**

1. 

**App Mesh 컨트롤러를 배포합니다. 모든 구성 옵션 목록은 GitHub의 [Configuration](https://github.com/aws/eks-charts/blob/master/stable/appmesh-controller/README.md#configuration)을 참조하십시오.**

   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 대몬(daemon)이 성공적으로 삽입되었는지 확인합니다.

      자세한 내용은 *Amazon EKS 사용 설명서*의 [프라이빗 클러스터](https://docs.aws.amazon.com/eks/latest/userguide/private-clusters.html)를 참조하세요.

   1. 다른 클러스터용 App Mesh 컨트롤러를 배포합니다. 모든 구성 옵션 목록은 GitHub의 [Configuration](https://github.com/aws/eks-charts/blob/master/stable/appmesh-controller/README.md#configuration)을 참조하십시오.

      ```
      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` 리전에 있는 경우, 이전 명령에 다음 옵션을 추가해야 합니다.  
*account-id* 및 *Region-code*를 해당 값 세트 중 하나로 바꿉니다.  

       ```
        --set image.repository=account-id.dkr.ecr.Region-code.amazonaws.com/amazon/appmesh-controller
       ```
772975370895.dkr.ecr.me-south-1.amazonaws.com/aws-appmesh-envoy:v1.34.13.0-prod
856666278305.dkr.ecr.ap-east-1.amazonaws.com/aws-appmesh-envoy:v1.34.13.0-prod
909464085924.dkr.ecr.ap-southeast-3.amazonaws.com/aws-appmesh-envoy:v1.34.13.0-prod
422531588944.dkr.ecr.eu-south-1.amazonaws.com/aws-appmesh-envoy:v1.34.13.0-prod
564877687649.dkr.ecr.il-central-1.amazonaws.com/aws-appmesh-envoy:v1.34.13.0-prod
924023996002.dkr.ecr.af-south-1.amazonaws.com/aws-appmesh-envoy:v1.34.13.0-prod
이전 이미지 URI는 GitHub의 [변경 로그](https://github.com/aws/aws-app-mesh-controller-for-k8s/releases)에서 찾을 수 있습니다. 이미지가 있는 AWS 계정이 버전에서 변경되었습니다`v1.5.0`. 이전 버전의 이미지는 Amazon Elastic Kubernetes Service [Amazon 컨테이너 이미지 레지스트리](https://docs.aws.amazon.com/eks/latest/userguide/add-ons-images.html)에 있는 AWS 계정에 호스팅됩니다.

       ```
       --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-controller:v1.13.1
856666278305.dkr.ecr.ap-east-1.amazonaws.com/amazon/appmesh-controller:v1.13.1
909464085924.dkr.ecr.ap-southeast-3.amazonaws.com/amazon/appmesh-controller:v1.13.1
422531588944.dkr.ecr.eu-south-1.amazonaws.com/amazon/appmesh-controller:v1.13.1
564877687649.dkr.ecr.il-central-1.amazonaws.com/amazon/appmesh-controller:v1.13.1
924023996002.dkr.ecr.af-south-1.amazonaws.com/amazon/appmesh-controller: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/aws-appmesh-proxy-route-manager:v7-prod
856666278305.dkr.ecr.ap-east-1.amazonaws.com/aws-appmesh-proxy-route-manager:v7-prod
909464085924.dkr.ecr.ap-southeast-3.amazonaws.com/aws-appmesh-proxy-route-manager:v7-prod
422531588944.dkr.ecr.eu-south-1.amazonaws.com/aws-appmesh-proxy-route-manager:v7-prod
564877687649.dkr.ecr.il-central-1.amazonaws.com/aws-appmesh-proxy-route-manager:v7-prod
924023996002.dkr.ecr.af-south-1.amazonaws.com/aws-appmesh-proxy-route-manager:v7-prod
**중요**  
v1.9.0.0-prod 이상 버전만 App Mesh에서 사용할 수 있습니다.

1. 컨트롤러 버전이 `v1.4.0` 이상인지 확인합니다. GitHub에서 [변경 로그](https://github.com/aws/aws-app-mesh-controller-for-k8s/releases)를 검토할 수 있습니다.

   ```
   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 리소스를 배포하는 데 도움이 됩니다. GitHub의 [App Mesh 연습](https://github.com/aws/aws-app-mesh-examples/tree/main/walkthroughs)에 나열된 여러 기능 폴더의 `v1beta2` 하위 폴더에서 다른 App Mesh 리소스 기능을 배포하기 위한 예제 매니페스트를 찾을 수 있습니다.

**중요**  
컨트롤러가 App Mesh 리소스를 생성한 후에는 컨트롤러를 사용하여 해당 App Mesh 리소스만 변경하거나 삭제하는 것이 좋습니다. App Mesh를 사용하여 리소스를 변경하거나 삭제하면 컨트롤러는 기본적으로 10시간 동안 변경되거나 삭제된 App Mesh 리소스를 변경하거나 다시 생성하지 않습니다. 이 기간을 더 짧게 구성할 수 있습니다. 자세한 내용은 GitHub에서 [구성](https://github.com/aws/eks-charts/blob/master/stable/appmesh-controller/README.md#configuration)을 참조하십시오.

**앱 메시 리소스를 배포하려면**

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
      ```

      출력

      ```
      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
      ```

      출력

      ```
      {
          "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. 앱 메시 가상 노드를 만듭니다. 가상 노드는 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
      ```

      가상 노드에는 이 자습서에서는 다루지 않는 종단 간 암호화 및 상태 확인과 같은 기능이 있습니다. 자세한 내용은 [가상 노드](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
      ```

      출력

      ```
      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 리소스를 생성할 때 App Mesh 가상 노드 이름에 Kubernetes 네임스페이스 이름을 추가합니다. Kubernetes에서는 서로 다른 네임스페이스에 같은 이름의 가상 노드를 만들 수 있지만, App Mesh에서 가상 노드 이름은 메시 내에서 고유해야 하기 때문에 네임스페이스 이름이 추가됩니다.

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

      출력

      ```
      {
          "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) 섹션을 참조하세요. 참조된 가상 노드 이름은 컨트롤러에서 App Mesh에 생성한 App Mesh 가상 노드 이름이 아니라 Kubernetes 가상 노드 이름입니다.

      ```
      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에 생성한 가상 라우터 리소스를 봅니다. 컨트롤러가 App Mesh에서 가상 라우터를 생성할 때 Kubernetes 네임스페이스 이름을 가상 라우터의 이름에 추가했기 때문에 `name`에 대해 `my-service-a-virtual-router_my-apps`를 지정합니다.

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

      출력

      ```
      {
          "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에서 경로를 생성할 App Mesh 경로 이름에 Kubernetes 네임스페이스 이름을 추가하지 않았습니다.

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

      출력

      ```
      {
          "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
      ```

      출력

      ```
      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에 생성한 가상 서비스 리소스의 세부 정보를 봅니다. 가상 서비스의 이름이 고유한 FQDN이기 때문에 Kubernetes 컨트롤러가 App Mesh에 가상 서비스를 만들 때 App Mesh 가상 서비스 이름에 Kubernetes 네임스페이스 이름을 추가하지 않았습니다.

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

      출력

      ```
      {
          "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에서 사용할 모든 포드에는 App Mesh 사이드카 컨테이너가 추가되어 있어야 합니다. 인젝터는 사용자가 지정한 레이블에 배포된 모든 포드에 사이드카 컨테이너를 자동으로 추가합니다.

1. 프록시 권한 부여를 활성화합니다. 각 Kubernetes 배포를 활성화하여 자체 App Mesh 가상 노드에 대한 구성을 스트리밍하는 것이 좋습니다.

   1. 다음 콘텐츠를 컴퓨터에 `proxy-auth.json`이라는 파일에 저장합니다. *대체 색상 값*을 고유한 값으로 바꿔야 합니다.

------
#### [ 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 Management Console 또는를 사용하여 서비스 계정을 생성하려면 *Amazon EKS 사용 설명서*의 서비스 계정에 대한 IAM 역할 및 정책 생성을 AWS CLI참조하세요. [https://docs.aws.amazon.com/eks/latest/userguide/create-service-account-iam-policy-and-role.html#create-service-account-iam-role](https://docs.aws.amazon.com/eks/latest/userguide/create-service-account-iam-policy-and-role.html#create-service-account-iam-role) AWS Management Console 또는를 사용하여 계정을 AWS CLI 생성하는 경우 역할을 Kubernetes 서비스 계정에 매핑해야 합니다. 자세한 내용을 알아보려면 Amazon EKS 사용 설명서의 [서비스 계정에 대한 IAM 역할 지정](https://docs.aws.amazon.com/eks/latest/userguide/specify-service-account-role.html)를 참조하세요.**

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 my-cluster --region Region-code --name my-service-a --namespace my-apps
   ```

1. Kubernetes 서비스 및 배포를 만듭니다. App Mesh와 함께 사용하려는 기존 배포가 있는 경우 [2단계: App Mesh 리소스 배포](#configure-app-mesh)의 하위 단계 `3`에서 수행한 것처럼 가상 노드를 배포해야 합니다. 배포의 레이블이 가상 노드에 설정한 레이블과 일치하도록 배포를 업데이트하여 사이드카 컨테이너가 자동으로 포드에 추가되고 포드가 재배포되도록 합니다.

   1. 다음 콘텐츠를 컴퓨터에 `example-service.yaml`이라는 파일에 저장합니다. 네임스페이스 이름을 변경하고 Fargate 포드를 사용하는 경우 네임스페이스 이름이 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` 하위 단계에서 가상 노드를 생성할 때 지정한 값과 일치해야 합니다. 그렇지 않으면 사이드카 컨테이너가 포드에 삽입되지 않습니다. 앞의 예에서 레이블의 값은 `my-app-1`입니다. 가상 노드가 아닌 가상 게이트웨이를 배포하는 경우 `Deployment` 매니페스트에는 Envoy 컨테이너만 포함되어야 합니다. 사용할 이미지에 대한 자세한 내용은 [Envoy 이미지](envoy.md) 섹션을 참조하세요. 샘플 매니페스트는 GitHub의 [배포 예제](https://github.com/aws/aws-app-mesh-examples/blob/main/walkthroughs/howto-k8s-ingress-gateway/v1beta2/manifest.yaml.template#L585)를 참조하세요.

   1. 서비스를 배포합니다.

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

   1. 서비스 및 배포를 봅니다.

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

      출력

      ```
      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. 배포된 포드 중 하나에 대한 세부 정보를 봅니다.

      ```
      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` 컨테이너가 컨트롤러에 의해 포드에 추가되었는지 확인할 수 있습니다. 예제 서비스를 Fargate에 배포한 경우 컨트롤러에서 `envoy` 컨테이너를 포드에 추가했지만 `proxyinit` 컨테이너는 추가하지 않았습니다.

1. (선택 사항) Prometheus, Grafana, AWS X-Ray Jaeger 및 Datadog과 같은 추가 기능을 설치합니다. 자세한 내용은 GitHub의 [App Mesh 추가 기능](https://github.com/aws/eks-charts#app-mesh-add-ons) 및 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 리소스에 더 이상 액세스할 수 없습니다. 자세한 내용은이 블로그 게시물 [Migrating from to Amazon ECS Service Connect를 참조 AWS App Mesh 하세요](https://aws.amazon.com/blogs/containers/migrating-from-aws-app-mesh-to-amazon-ecs-service-connect).

이 주제는 Amazon EC2에서 실행 중인 실제 서비스와 AWS App Mesh 함께를 사용하는 데 도움이 됩니다. 이 자습서에서는 몇 가지 App Mesh 리소스 유형의 기본 기능을 다룹니다.

## 시나리오
<a name="scenario"></a>

App Mesh를 사용하는 방법을 설명하기 위해 다음과 같은 특징을 가진 애플리케이션이 있다고 가정합니다.
+ `serviceA`및 `serviceB`라는 두 개의 서비스로 구성됩니다.
+ 두 서비스 모두 `apps.local`이라는 네임스페이스에 등록됩니다.
+ `ServiceA`는 HTTP/2, 포트 80을 통해 `serviceB`와 통신합니다.
+  `serviceB`의 버전 2를 이미 배포했고 `apps.local` 네임스페이스에 `serviceBv2` 이름으로 등록했습니다.

다음과 같은 요구 사항이 있습니다.
+ 에서 로 트래픽의 75%`serviceA`를 전송`serviceB`하고 트래픽의 25%를 `serviceBv2` 먼저 전송하려고 합니다. 에 25%만 전송하면에서 트래픽의 100%를 전송하기 전에 버그가 없는지 확인할 `serviceBv2`수 있습니다`serviceA`.
+ 트래픽이 신뢰할 수 있는 것으로 입증되면 해당 트래픽의 100%가 `serviceBv2`로 이동하도록 트래픽 가중치를 쉽게 조정할 수 있기를 원합니다. 모든 트래픽이 `serviceBv2`로 전송되면 `serviceB`를 중단하려고 할 수 있습니다.
+ 이전 요구 사항을 충족하기 위해 실제 서비스에 대한 기존 애플리케이션 코드 또는 서비스 검색 등록을 변경할 필요가 없도록 하고 싶습니다.

요구 사항을 충족하기 위해 가상 서비스, 가상 노드, 가상 라우터 및 루트가 포함된 App Mesh 서비스 메시를 생성하기로 결정했습니다. 메시를 구현한 후 서비스가 Envoy 프록시를 사용하도록 서비스를 업데이트합니다. 업데이트된 서비스는 서로 직접 통신하지 않고 Envoy 프록시를 통해 서로 통신합니다.

## 사전 조건
<a name="prerequisites"></a>

App Mesh는 DNS AWS Cloud Map또는 둘 다에 등록된 Linux 서비스를 지원합니다. 이 시작 안내서를 사용하려면 DNS에 등록된 기존 서비스 3개가 있으면 좋습니다. 서비스가 존재하지 않더라도 서비스 메시 및 해당 리소스를 생성할 수 있지만 실제 서비스를 배포할 때까지 메시를 사용할 수 없습니다.

서비스를 아직 실행 중이지 않은 경우 Amazon EC2 인스턴스를 시작하고 애플리케이션을 배포할 수 있습니다. 자세한 내용은 [ Amazon EC2 사용 설명서의 자습서: Amazon EC2 Linux 인스턴스 시작하기](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-lamp-amazon-linux-2.html)를 참조하세요. Amazon EC2 나머지 단계에서는 실제 서비스의 이름이 `serviceA`, `serviceB` 및 `serviceBv2`이고 `apps.local`이라는 네임스페이스를 통해 모든 서비스를 검색할 수 있다고 가정합니다.

## 1단계: 메시 및 가상 서비스 생성
<a name="create-mesh-and-virtual-service"></a>

서비스 메시는 내부에 있는 서비스 간의 네트워크 트래픽에 대한 논리적 경계입니다. 자세한 내용은 [서비스 메시](meshes.md) 단원을 참조하십시오. 가상 서비스는 실제 서비스를 추상화한 것입니다. 자세한 내용은 [가상 서비스](virtual_services.md) 단원을 참조하십시오.

다음의 리소스를 생성합니다.
+ 시나리오의 모든 서비스가 `apps.local` 네임스페이스에 등록되기 때문에 `apps`이라는 메시를 생성합니다.
+ 가상 서비스는 해당 이름으로 검색할 수 있는 서비스를 나타내며 다른 이름을 참조하도록 코드를 변경하고 싶지 않기 때문에 `serviceb.apps.local`이라는 이름의 가상 서비스를 생성합니다. `servicea.apps.local`이라는 이름의 가상 서비스는 이후 단계에서 추가됩니다.

 AWS Management Console 또는 AWS CLI 버전 1.18.116 이상 또는 2.0.38 이상을 사용하여 다음 단계를 완료할 수 있습니다. 를 사용하는 경우 `aws --version` 명령을 AWS CLI사용하여 설치된 AWS CLI 버전을 확인합니다. 버전 1.18.116 이상 또는 2.0.38 이상이 설치되어 있지 않으면 [AWS CLI를 설치하거나 업데이트](https://docs.aws.amazon.com/cli/latest/reference/appmesh/cli-chap-install.html)해야 합니다. 사용할 도구의 탭을 선택합니다.

------
#### [ AWS Management Console ]

1. [https://console.aws.amazon.com/appmesh/get-started](https://console.aws.amazon.com/appmesh/get-started)에서 App Mesh 콘솔 처음 실행 마법사를 엽니다.

1. **Mesh name(메시 이름)**에 **apps**를 입력합니다.

1. **Virtual service name(가상 서비스 이름)**에 **serviceb.apps.local**를 입력합니다.

1. 계속하려면 **다음**을 선택합니다.

------
#### [ 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 Management Console ]

1. **Virtual node name(가상 노드 이름)**에 **serviceB**를 입력합니다.

1. **서비스 검색 방법**에 대해 **DNS**를 선택하고 **DNS 호스트 이름**에 대해 **serviceb.apps.local**을 입력합니다.

1. **리스너 구성**에서 **프로토콜**로 **http2**를 선택하고 **포트**로 **80**을 입력합니다.

1. 계속하려면 **다음**을 선택합니다.

------
#### [ 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` 서비스를 추상화한 것입니다. 가상 서비스는 가상 라우터로 트래픽을 보냅니다. 가상 라우터는 포트 80에서 HTTP/2 프로토콜을 사용하여 트래픽을 수신합니다. 다른 프로토콜도 지원됩니다.
+ `serviceB`라는 이름의 라우팅. 트래픽을 100% `serviceB` 가상 노드로 라우팅합니다. `serviceBv2` 가상 노드를 추가한 후 이후 단계에서 가중치가 변경됩니다. 이 안내서에서는 다루지 않지만 해당 라우팅에 대한 필터 조건을 추가하고 재시도 정책을 추가하여 통신 문제가 발생할 경우 Envoy 프록시가 가상 노드에 트래픽을 여러 번 보내도록 할 수 있습니다.

------
#### [ AWS Management Console ]

1. **Virtual router name(가상 라우터 이름)**에 **serviceB**를 입력합니다.

1. **리스너 구성**에서 **프로토콜**로 **http2**를 선택하고 **포트**로 **80**을 지정합니다.

1. **Route Name(라우팅 이름)**에 **serviceB**를 입력합니다.

1. **루트 유형**에 대해 **http2**를 선택합니다.

1. **대상 구성**의 **가상 노드 이름**에 대해 `serviceB`를 선택하고 **가중치**로 **100**을 입력합니다.

1. **일치 구성**에서 **방법**을 선택합니다.

1. 계속하려면 **다음**을 선택합니다.

------
#### [ 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 Management Console ]

섹션에서 변경해야 할 경우 **편집**을 선택합니다. 설정에 만족하면 **메시 생성**을 선택합니다.

**상태** 화면에는 생성된 모든 메시 리소스가 표시됩니다. **메시 보기**를 선택하여 콘솔에서 생성된 리소스를 볼 수 있습니다.

------
#### [ 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` 가상 노드로 직접 전송됩니다.
+ 트래픽의 75%를 `serviceB` 가상 노드로 보내고 트래픽의 25%를 `serviceBv2` 가상 노드로 보내도록 이전 단계에서 생성한 `serviceB` 라우팅을 업데이트합니다. 시간이 지남에 따라 `serviceBv2`가 트래픽의 100%를 수신할 때까지 가중치를 계속 수정할 수 있습니다. 모든 트래픽이 `serviceBv2`로 전송되면 `serviceB` 가상 노드와 실제 서비스를 종료하고 중단할 수 있습니다. `serviceb.apps.local` 가상 및 실제 서비스 이름이 변경되지 않으므로 가중치를 변경할 때 코드를 수정할 필요가 없습니다. `serviceb.apps.local` 가상 서비스는 트래픽을 가상 라우터로 전송하여 트래픽을 가상 노드로 라우팅한다는 점을 기억하십시오. 가상 노드의 서비스 검색 이름은 언제든지 변경할 수 있습니다.

------
#### [ AWS Management Console ]

1. 왼쪽 탐색 창에서 **Meshes(메시)**를 선택합니다.

1. 이전 단계에서 생성한 `apps` 메시를 선택합니다.

1. 왼쪽 탐색 창에서 **Virtual node(가상 노드)**를 선택합니다.

1. **Create virtual node(가상 노드 생성)**를 선택합니다.

1. **가상 노드 이름**에 대해 **serviceBv2**를 입력하고, **서비스 검색 방법**에 대해 **DNS**를 선택하고 **DNS 호스트 이름**에 대해 **servicebv2.apps.local**을 입력합니다.

1. **리스너 구성**에서 **프로토콜**로 **http2**를 선택하고 **포트**로 **80**을 입력합니다.

1. **Create virtual node(가상 노드 생성)**를 선택합니다.

1. **가상 노드 생성**을 다시 선택합니다. **가상 노드 이름**에 **serviceA**를 입력합니다. **서비스 검색 방법**에 대해 **DNS**를 선택하고 **DNS 호스트 이름**에 대해 **servicea.apps.local**을 입력합니다.

1. **새 백엔드**에서 **가상 서비스 이름 입력**에 **serviceb.apps.local**을 입력합니다.

1. **리스너 구성**에서 **프로토콜**로 **http2**를 선택하고 **포트**에 **80**을 입력한 다음, **가상 노드 생성**을 선택합니다.

1. 왼쪽 탐색 창에서 **Virtual routers(가상 라우터)**를 선택한 다음 목록에서 `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-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. 역할이 Amazon ECR에서 특정 App Mesh 가상 노드의 구성만 읽을 수 있도록 하는 IAM 정책을 역할에 연결합니다.

   1. 다음 콘텐츠를 통해 `virtual-node-policy.json`이라는 파일을 생성합니다. `apps`는 [1단계: 메시 및 가상 서비스 생성](#create-mesh-and-virtual-service)에서 생성한 메시의 이름이고, `serviceB`는 [2단계: 가상 노드 생성](#create-virtual-node)에서 생성한 가상 노드의 이름입니다. *111122223333*을 사용자의 계정 ID로 바꾸고 *us-west-2*를 메시를 생성한 리전으로 바꿉니다.

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

****  

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

------

   1. 다음 명령을 사용하여 정책을 생성합니다.

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

   1. 이전 단계에서 생성한 정책을 역할에 연결하여 역할이 App Mesh에서 `serviceB` 가상 노드에 대한 구성만 읽을 수 있도록 합니다.

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

   1. `AmazonEC2ContainerRegistryReadOnly` 관리형 정책을 역할에 연결하여 해당 역할이 Amazon ECR에서 Envoy 컨테이너 이미지를 끌어올 수 있도록 합니다.

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

1. 생성한 [IAM 역할로 Amazon EC2 인스턴스를 시작](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html#launch-instance-with-role)합니다.

1. SSH를 통해 인스턴스에 연결합니다.

1. 운영 체제 설명서에 따라 인스턴스 AWS CLI 에 Docker와를 설치합니다.

1. Dockerㅅ서 클라이언트가 이미지를 끌어올 리전에서 Envoy Amazon ECR 리포지토리에서 인증을 받습니다.
   + `me-south-1`, `ap-east-1`, `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` 및 `af-south-1`을 제외한 [지원되는 리전](https://docs.aws.amazon.com/general/latest/gr/appmesh.html)으로 바꿀 수 있습니다.

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

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

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

1. 이미지를 가져올 리전에 따라 다음 명령 중 하나를 실행하여 인스턴스에서 App Mesh Envoy 컨테이너를 시작합니다. *apps* 및 *serviceB* 값은 시나리오에 정의된 메시 및 가상 노드 이름입니다. 이 정보는 프록시에 App Mesh에서 읽을 가상 노드 구성을 알려줍니다. 시나리오를 완료하려면 `serviceBv2` 및 `serviceA` 가상 노드가 나타내는 서비스를 호스팅하는 Amazon EC2 인스턴스에 대해서도 이러한 단계를 완료해야 합니다. 자체 애플리케이션의 경우 이 값을 자체 값으로 바꿉니다.
   + `me-south-1`, `ap-east-1`, `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` 및 `af-south-1` 리전을 제외한 [지원되는 리전](https://docs.aws.amazon.com/general/latest/gr/appmesh.html)으로 바꿀 수 있습니다. `1337`을 `0`과 `2147483647` 사이의 값으로 바꿀 수 있습니다.

     ```
     sudo docker run --detach --env APPMESH_RESOURCE_ARN=mesh/apps/virtualNode/serviceB  \
     -u 1337 --network host 840364872350.dkr.ecr.region-code.amazonaws.com/aws-appmesh-envoy:v1.34.13.0-prod
     ```
   + `me-south-1` 리전. `1337`을 `0`과 `2147483647` 사이의 값으로 바꿀 수 있습니다.

     ```
     sudo docker run --detach --env APPMESH_RESOURCE_ARN=mesh/apps/virtualNode/serviceB  \
     -u 1337 --network host 772975370895.dkr.ecr.me-south-1.amazonaws.com/aws-appmesh-envoy:v1.34.13.0-prod
     ```
   + `ap-east-1` 리전. `1337`을 `0`과 `2147483647` 사이의 값으로 바꿀 수 있습니다.

     ```
     sudo docker run --detach --env APPMESH_RESOURCE_ARN=mesh/apps/virtualNode/serviceB  \
     -u 1337 --network host 856666278305.dkr.ecr.ap-east-1.amazonaws.com/aws-appmesh-envoy:v1.34.13.0-prod
     ```
**참고**  
`APPMESH_RESOURCE_ARN` 속성에는 `1.15.0` 이상의 Envoy 이미지 버전이 필요합니다. 자세한 내용은 [Envoy 이미지](envoy.md) 단원을 참조하십시오.
**중요**  
v1.9.0.0-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. 애플리케이션 트래픽을 Envoy 프록시로 라우팅하는 `iptables` 규칙을 구성하려면 이전 단계에서 생성한 스크립트를 실행합니다.

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

1. 가상 노드 애플리케이션 코드를 시작합니다.

**참고**  
App Mesh에 대한 더 많은 예제와 연습 내용을 보려면 [App Mesh 예제 리포지토리](https://github.com/aws/aws-app-mesh-examples)를 참조하세요.

# App Mesh 예제
<a name="examples"></a>

**중요**  
지원 종료 알림: 2026년 9월 30일에에 대한 지원을 중단할 AWS 예정입니다 AWS App Mesh. 2026년 9월 30일 이후에는 AWS App Mesh 콘솔 또는 AWS App Mesh 리소스에 더 이상 액세스할 수 없습니다. 자세한 내용은이 블로그 게시물 [에서 Amazon ECS Service Connect AWS App Mesh 로 마이그레이션](https://aws.amazon.com/blogs/containers/migrating-from-aws-app-mesh-to-amazon-ecs-service-connect)을 참조하세요.

다음 리포지토리에서 다양한 AWS 서비스와 통합하기 위한 AWS App Mesh 실행 및 코드 예제를 보여주는 end-to-end 연습을 찾을 수 있습니다.

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