# Porting to APP MESH

제품 카탈로그 프런트엔드 `frontend-node`는 `prodcatalog`에 대한 요청을 하도록 hardwired 되었으며 `prodcatalog`는 `proddetail`에 대한 요청을 하도록 hardwired되어 있습니다.

새 버전의 `proddetail` 릴리스가 있을 때마다 버전별 엔드포인트를 가리키도록 새 버전과 이전 버전을 모두 지원하는 새 버전의 `prodcatalog`도 릴리스해야 합니다. 장기적으로 유지하기에 최적의 구성은 아닙니다.

`prodcatalog` 백엔드 서비스가 Faragate에 배포되고 나머지 서비스 `frontend-node`와 `proddetail`은 관리 노드 그룹에 배포됩니다. 우리는 이러한 모든 서비스를 App Mesh에 추가하고 이러한 마이크로 서비스가 서로 통신할 수 있도록 해야 합니다.

이제 AWS App Mesh를 사용하여 이 아키텍처를 단순화하는 방법을 실습할 것입니다. `proddetail` 서비스를 가상화함으로써 동적 구성을 추가하고 원하는 버전의 엔드포인트로 트래픽을 라우팅할 수 있으므로, 새로운 `proddetail` 서비스 릴리스가 있을 때마다 `prodcatalog` 서비스의 재구축 필요성을 최소화할 수 있습니다.

또한 Nodegroup과 Fargate의 모든 마이크로 서비스가 App Mesh를 통해 서로 통신할 수 있는 방법을 시연할 것입니다.

이 장의 응용 프로그램 포팅이 완료되면 다음과 같이 표시됩니다.

![](https://1998608250-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MhByD5wv8eUbA5ZbUY5%2Fuploads%2FQFSciJYYIVyoAhYt08n5%2Fimage.png?alt=media\&token=0f4687a4-a769-4488-bb27-73292fc7648d)

## 1. Mesh Design

![](https://1998608250-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MhByD5wv8eUbA5ZbUY5%2Fuploads%2FgHDUWLWn4tqLmR6k4Hzj%2Fimage.png?alt=media\&token=74c52550-c956-4577-9313-6f60d31c560c)

위의 이미지에서 제품 카탈로그 애플리케이션의 모든 서비스가 App Mesh 내에서 실행되고 있는 것을 볼 수 있습니다. 각 서비스에는 VirtualNode가 정의되어 있으며, VirtualService도 있습니다. 이러한 VirtualServices는 트래픽을 Mesh 내의 VirtualRouter로 전송하며, VirtualRouter는 라우팅 규칙을 지정합니다. 이렇게 하면 트래픽이 각각의 VirtualNode로 이동하며 궁극적으로는 Kubernetes 내의 서비스 엔드포인트로 이동하게 됩니다.

* 기능적으로, Mesh-enabled 버전은 현재 버전의 기능을 정확히 수행합니다.&#x20;
  * `frontend-node` 에서 만든 요청은 `prodcatalog` 백엔드 서비스에 의해 처리됩니다.
  * `prodcatalog`에서 만든 요청은 `prodetail-v1` 백엔드 서비스에서 제공됩니다.&#x20;
* 차이점은 AWS App Mesh를 사용하여 `Prodcatalog`와 `Prodetail`이라는 새로운 가상 서비스를 만든다는 것입니다.&#x20;
  * `frontend-node`  서비스에서 요청을 하면 트래픽을 클러스터 내의 서비스 엔드포인트로 라우팅하도록 구성된 `VirtualRouter` 인스턴스로 논리적으로 트래픽을 전송하여 카탈로그를 생성합니다.&#x20;
  * `Prodcatalog` 서비스의 요청은 트래픽을 클러스터 내의 서비스 엔드포인트로 라우팅하도록 구성할 `VirtualRouter` 인스턴스로 트래픽을 논리적으로 전송하여 `prodetail-v1`로 전송합니다.

## 2. Mesh Resource

**Mesh**

Product Catalog App을 App Mesh로 포팅하려면 먼저 Mesh를 만들어야 합니다. 또한 `Prodcatalog-ns` 네임스페이스에 Label을 적용하여 새로운 Mesh와 제휴하고 그 안에 있는 Pod의 자동 sidecar injection입을 가능하게 할 것입니다. 다음 장에서 VirtualGateway 설정에 사용할 게이트웨이 Label도 추가합니다. 아래에 표시된 [mesh.yaml](https://github.com/aws-containers/eks-app-mesh-polyglot-demo/blob/master/deployment/mesh.yaml) 섹션을 보면 `prodcatalog-ns` 네임스페이스에 필요한 Label을 추가하고 `prodcatalog-mesh`라는 이름의 Mesh를 지정했음을 알 수 있습니다.

![](https://1998608250-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MhByD5wv8eUbA5ZbUY5%2Fuploads%2FekUS7LHoYmFaaFWzZ5Tf%2Fimage.png?alt=media\&token=c47135d8-5e45-42bf-9eac-876183ea177b)

**VirtualNode**

App Mesh 내에서 실행되는 Kubernetes 애플리케이션 개체를 `VirtualNode`로 정의해야 합니다. 이렇게 하면 App Mesh가 Kubernetes Deployments 및 Services와 같은 개체에 추상화를 제공하고 통신 및 라우팅 구성을 위한 엔드포인트를 제공합니다. [meshed\_app.yaml](https://github.com/aws-containers/eks-app-mesh-polyglot-demo/blob/master/deployment/meshed_app.yaml)을 살펴보면, 아래는 `frontend-node` 서비스의 `VirtualNode` spec입니다.

![](https://1998608250-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MhByD5wv8eUbA5ZbUY5%2Fuploads%2F04wu9J0K681JyagMfNt9%2Fimage.png?alt=media\&token=cdd69324-89e6-4750-aec6-be4d11b63a13)

`podSelector`를 사용하여 이 VirtualNode의 멤버인 Pod와 `frontend-node Service`에 대한 포인터를 식별합니다.



**VirtualService and VirtualRouter**

또한 각 제품 카탈로그 세부 정보 버전에는 `VirtualService` 및 `VirtualRouter` spec이 있어 각 엔드포인트로의 트래픽 라우팅을 설정합니다. 이 작업은 `Prodetail-v1` 가상 노드를 가리키는 경로를 추가하여 수행됩니다. App Mesh는 애플리케이션 트래픽에 대한 논리적 서비스 경로를 지정할 수 있는 `VirtualService` 구성도 제공합니다. 이 예에서는 `VirtualRouter`로 트래픽을 전송한 다음 `VirtualNode`로 트래픽을 라우팅합니다. [meshed\_app.yaml](https://github.com/aws-containers/eks-app-mesh-polyglot-demo/blob/master/deployment/meshed_app.yaml)을 보면 아래는 트래픽을 백엔드 서비스 `prodetail-v1` 버전 1로 라우팅하는 Prodetail VirtualService 및 VirtualRouter입니다.

![](https://1998608250-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MhByD5wv8eUbA5ZbUY5%2Fuploads%2FHt4W0uNplEJ4ZcWYCMGe%2Fimage.png?alt=media\&token=77ea5b1e-852a-4f7c-97a6-8bc71042256d)

## 3. Meshed Application 생성

App Mesh Labels 과 함께 네임스페이스를 구성하고 Mesh Object를 배포 합니다.&#x20;

```bash
kubectl apply -f deployment/mesh.yaml  
```

![](https://1998608250-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MhByD5wv8eUbA5ZbUY5%2Fuploads%2FNfIgk1zecmUrPamzPMG2%2Fimage.png?alt=media\&token=b689c309-df14-48e4-8eae-75d3718abadb)

Confirm the Mesh object and Namespace are created

```bash
kubectl describe namespace prodcatalog-ns
```

![](https://1998608250-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MhByD5wv8eUbA5ZbUY5%2Fuploads%2FXfltudglXuhflHld5uqX%2Fimage.png?alt=media\&token=bf5d998e-0a95-4e0b-adbc-3e0699a33837)

```bash
kubectl describe mesh prodcatalog-mesh
```

![](https://1998608250-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MhByD5wv8eUbA5ZbUY5%2Fuploads%2FebPCP4fTtp8juMWKoXiw%2Fimage.png?alt=media\&token=d0f64e0e-c65c-4364-b56a-1ff46b8cb6b8)

서비스에 필요한 App Mesh Resources를 생성합니다.

```bash
kubectl apply -f deployment/meshed_app.yaml
```

![](https://1998608250-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MhByD5wv8eUbA5ZbUY5%2Fuploads%2FtffNJWdpfsDr0jXsjsSn%2Fimage.png?alt=media\&token=d9cef3aa-5a81-4841-b7cd-789d103d4f3e)

모든 Mesh 자원이 생성되었는지 확인합니다.

```bash
kubectl get virtualnode,virtualservice,virtualrouter -n prodcatalog-ns
```

콘솔의 AWS App Mesh 메뉴에서 자원의 정보를 확인합니다.

&#x20; &#x20;

![](https://www.eksworkshop.com/images/app_mesh_fargate/mesh-1.png)

![](https://www.eksworkshop.com/images/app_mesh_fargate/mesh-2.png)

![](https://www.eksworkshop.com/images/app_mesh_fargate/mesh-3.png)

## 4. SIDECAR INJECTION

Application내의 Pod가 mesh에 연결되기 위해서는 Pod 내에 sidecar로 동작하는 Envoy proxy container가 존재해야 합니다. 이렇게 하면 AWS App mesh가 제어하는 data plane이 설정됩니다.&#x20;

![](https://1998608250-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MhByD5wv8eUbA5ZbUY5%2Fuploads%2F2CiwdGVIxDE8ssapOSQk%2Fimage.png?alt=media\&token=e06217af-df4a-46af-aa7f-4fcba9663e31)

SIDECAR INJECTION을 위한 몇ㄱ 가지 방법이 있습니다.

* 애플리케이션을 설치하기 전에 제품 카탈로그 앱 Deployment spec을 App Mesh 사이드카 컨테이너를 포함하도록 수정하고 몇 가지 필수 구성 요소 및 환경 변수를 설정할 수 있습니다. 포드가 전개되면 사이드카가 작동됩니다.
* 애플리케이션을 설치한 후 사이드카 컨테이너 specs을 포함하도록 각 Deployment를 패치할 수 있습니다. 이 패치를 적용하면, 오래된 포드는 사라지고, 새로운 포드는 사이드카를 만들게 됩니다.
* Mesh 네임스페이스에서 AWS App Mesh Sidecar Injector를 사용하도록 설정할 수 있습니다. 이 장치는 새 포드가 생성되는지 감시하고 배치될 때 자동으로 사이드카 컨테이너와 필요한 구성을 포드에 추가합니다.

이 실습에서는 세 번째 옵션을 사용하여 Mesh 포드에 자동 사이드카 주입을 활성화합니다. `Labels: appmesh.k8s.aws/sidecarInjectorWebhook=enabled`를 추가하여 자동 사이드카 주입을 활성화했습니다. [이전 장](#3.-meshed-application)에서 Mesh 리소스를 만들 때 `prodcatalog-ns` 네임스페이스에서 사용했지만 초기 포드 생성 후 이 작업이 수행되었습니다. 현재, 우리의 포드들은 각각 하나의 컨테이너를 가동하고 있습니다.

```
kubectl get pods -n prodcatalog-ns -o wide
```

![](https://1998608250-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MhByD5wv8eUbA5ZbUY5%2Fuploads%2FKsiPTIGNoGzzpajQktZJ%2Fimage.png?alt=media\&token=903c7f29-eec2-4382-998a-d6fbb43cbc3f)

간단하게 deployment를 재시작하여 sidecar 프록시 injection을 할 수 있습니다.

```
kubectl -n prodcatalog-ns rollout restart deployment prodcatalog

kubectl -n prodcatalog-ns rollout restart deployment proddetail 

kubectl -n prodcatalog-ns rollout restart deployment frontend-node

```

&#x20;Pod detail에서 각 Pod에 `main application container`, `envoy sidecar container` and `xray sidecar container` 이렇게 3개의 컨테이너를 확인할 수 있습니다.

![](https://1998608250-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MhByD5wv8eUbA5ZbUY5%2Fuploads%2FvnWgLd2cUE4CuxzQLQmq%2Fimage.png?alt=media\&token=5fce2730-25ba-45f4-9eac-c3305f20636f)

```
POD=$(kubectl -n prodcatalog-ns get pods -o jsonpath='{.items[0].metadata.name}')
kubectl -n prodcatalog-ns get pods ${POD} -o jsonpath='{.spec.containers[*].name}'; echo

```

![](https://1998608250-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MhByD5wv8eUbA5ZbUY5%2Fuploads%2FATZjdXeG71mq33j2J30x%2Fimage.png?alt=media\&token=9d869b50-9bc0-41b6-a5e1-fc7415f99e37)

## 5. APPLICATION TEST

![](https://1998608250-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MhByD5wv8eUbA5ZbUY5%2Fuploads%2FDVO3Sxc6Z0QVSdpp4he2%2Fimage.png?alt=media\&token=0b78d04a-9410-4f6f-b17e-d962577e1b70)

Mesh에 porting된 Product Catalog App 이 제대로 동작하는지 확인하기 위해 `frontend-node` 컨테이너에 접속하여 명령어를 수행합니다.

```
export FE_POD_NAME=$(kubectl get pods -n prodcatalog-ns -l app=frontend-node -o jsonpath='{.items[].metadata.name}') 

kubectl -n prodcatalog-ns exec -it ${FE_POD_NAME} -c frontend-node bash

```

port 5000을 사용하는 virtual service `prodcatalog` 에 curl을 호출합니다.&#x20;

```
curl -v http://prodcatalog.prodcatalog-ns.svc.cluster.local:5000/products/    

```

![](https://1998608250-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MhByD5wv8eUbA5ZbUY5%2Fuploads%2FpujcaGQfAHpl89gnskih%2Fimage.png?alt=media\&token=81959787-9142-4188-983f-c759ecf7b9b1)

이번에는 `prodcatalog`와 `proddetail` 간의 연결을 확인합니다. (ctrl+d 로 container에서 빠져나옵니다.)

```
export BE_POD_NAME=$(kubectl get pods -n prodcatalog-ns -l app=prodcatalog -o jsonpath='{.items[].metadata.name}') 

kubectl -n prodcatalog-ns exec -it ${BE_POD_NAME} -c prodcatalog bash

```

```
curl -v http://proddetail.prodcatalog-ns.svc.cluster.local:3000/catalogDetail 

```

![](https://1998608250-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MhByD5wv8eUbA5ZbUY5%2Fuploads%2Fxh5EanVblcTJzOe6TQWb%2Fimage.png?alt=media\&token=e937eaac-0885-4e78-b1b1-933824c2b2a3)

이제 End-user에게 서비스를 노출 시킬 `VirtualGateway`를 생성합니다.
