

 **이 페이지 개선에 도움 주기** 

이 사용자 가이드에 기여하려면 모든 페이지의 오른쪽 창에 있는 **GitHub에서 이 페이지 편집** 링크를 선택합니다.

# 기계 학습을 위해 Amazon EKS와 함께 AWS Inferentia 인스턴스 사용
<a name="inferentia-support"></a>

이 주제에서는 [Amazon EC2 Inf1](https://aws.amazon.com/ec2/instance-types/inf1/) 인스턴스를 실행하는 노드가 있는 Amazon EKS 클러스터를 생성하고 샘플 애플리케이션을 배포(선택사항)하는 방법을 설명합니다. Amazon EC2 Inf1 인스턴스는 [AWS Inferentia](https://aws.amazon.com/machine-learning/inferentia/) 칩으로 구동됩니다. 이 칩은 클라우드에서 고성능의 가장 저렴한 추론을 제공하기 위해 AWS에서 사용자 지정으로 구축됩니다. 기계 학습 모델은 Inferentia 칩의 기계 학습 추론 성능을 최적화하는 컴파일러, 런타임 및 프로필링 도구로 구성된 특수 소프트웨어 개발 키트(SDK)인 [AWS Neuron](https://aws.amazon.com/machine-learning/neuron/)을 사용하여 컨테이너에 배포됩니다. AWS Neuron은 TensorFlow, PyTorch, MXNet과 같은 인기 있는 기계 학습 프레임워크를 지원합니다.

**참고**  
Neuron 디바이스 논리적 ID는 연속적이어야 합니다. Neuron 디바이스를 여러 개 요청하는 포드가 `inf1.6xlarge` 또는 `inf1.24xlarge` 인스턴스 유형(둘 이상의 Neuron 디바이스가 있음)에서 예약된 경우 Kubernetes 스케줄러가 불연속적인 디바이스 ID를 선택하면 해당 포드가 시작되지 않습니다. 자세한 내용은 GitHub의 [Device logical IDs must be contiguous](https://github.com/aws/aws-neuron-sdk/issues/110)를 참조하십시오.

## 사전 조건
<a name="inferentia-prerequisites"></a>
+ `eksctl`가 컴퓨터에 설치되어 있어야 합니다. 설치되지 않은 경우 `eksctl` 설명서에서 [설치](https://eksctl.io/installation)를 참조하세요.
+ `kubectl`가 컴퓨터에 설치되어 있어야 합니다. 자세한 내용은 [`kubectl` 및 `eksctl` 설정](install-kubectl.md) 섹션을 참조하세요.
+ (선택사항) `python3`이 컴퓨터에 설치되어 있어야 합니다. 설치되어 있지 않은 경우 [Python downloads](https://www.python.org/downloads/)를 참조하여 설치 지침을 확인하세요.

## 클러스터 생성
<a name="create-cluster-inferentia"></a>

1. Inf1 Amazon EC2 인스턴스 노드를 사용하여 클러스터를 생성합니다. *inf1.2xlarge*를 모든 [Inf1 인스턴스 유형](https://aws.amazon.com/ec2/instance-types/inf1/)으로 바꿀 수 있습니다. `eksctl` 유틸리티는 `Inf1` 인스턴스 유형을 사용하여 노드 그룹을 시작한다는 것을 감지하고 Amazon EKS 최적화 가속 Amazon Linux AMI 중 하나를 사용하여 노드를 시작합니다.
**참고**  
TensorFlow Serving에서는 [서비스 계정에 IAM 역할](iam-roles-for-service-accounts.md)을 사용할 수 없습니다.

   ```
   eksctl create cluster \
       --name inferentia \
       --region region-code \
       --nodegroup-name ng-inf1 \
       --node-type inf1.2xlarge \
       --nodes 2 \
       --nodes-min 1 \
       --nodes-max 4 \
       --ssh-access \
       --ssh-public-key your-key \
       --with-oidc
   ```
**참고**  
출력의 다음 행의 값을 적어 둡니다. 이후 (선택사항) 단계에서 이 값을 사용합니다.

   ```
   [9]  adding identity "arn:aws:iam::111122223333:role/eksctl-inferentia-nodegroup-ng-in-NodeInstanceRole-FI7HIYS3BS09" to auth ConfigMap
   ```

   `Inf1` 인스턴스로 노드 그룹을 시작하면 `eksctl`은 AWS Neuron Kubernetes 디바이스 플러그인을 자동으로 설치합니다. 이 플러그인은 Neuron 디바이스를 Kubernetes 스케줄러에 시스템 리소스로 알립니다. 이 스케줄러는 컨테이너에서 요청할 수 있습니다. 기본 Amazon EKS 노드 IAM 정책 외에도 Amazon S3 읽기 전용 액세스 정책이 추가되어 이후 단계에서 다루는 샘플 애플리케이션이 Amazon S3에서 훈련된 모델을 로드할 수 있습니다.

1. 모든 포드가 올바르게 시작되었는지 확인합니다.

   ```
   kubectl get pods -n kube-system
   ```

   간략한 출력:

   ```
   NAME                                   READY   STATUS    RESTARTS   AGE
   [...]
   neuron-device-plugin-daemonset-6djhp   1/1     Running   0          5m
   neuron-device-plugin-daemonset-hwjsj   1/1     Running   0          5m
   ```

## (선택사항) TensorFlow Serving 애플리케이션 이미지 배포
<a name="deploy-tensorflow-serving-application"></a>

훈련된 모델은 Inferentia 인스턴스에서 배포하기 전에 Inferentia 대상에 컴파일되어야 합니다. 계속하려면, Amazon S3 저장된 [Neuron 최적화 TensorFlow](https://awsdocs-neuron.readthedocs-hosted.com/en/latest/neuron-guide/neuron-frameworks/tensorflow-neuron/index.html) 모델이 필요합니다. 아직 SavedModel이 없는 경우 [Neuron 호환 ResNet50 모델 생성](https://docs.aws.amazon.com/dlami/latest/devguide/tutorial-inferentia-tf-neuron.html)에 대한 자습서를 따르고 그 결과로 생성된 SavedModel을 S3에 업로드합니다. ResNet-50은 이미지 인식 작업에 사용되는 인기 있는 기계 학습 모델입니다. Neuron 모델 컴파일에 대한 자세한 내용은 AWS 딥러닝 AMI 개발자 가이드에서 [DLAMI를 사용한 AWS Inferentia 칩](https://docs.aws.amazon.com/dlami/latest/devguide/tutorial-inferentia.html) 섹션을 참조하세요.

샘플 배포 매니페스트는 AWS Deep Learning Containers에서 제공되는 사전 구축된 TensorFlow용 추론 Serving 컨테이너를 관리합니다. 이 컨테이너 내부에는 AWS Neuron 런타임 및 TensorFlow Serving 애플리케이션이 있습니다. Neuron에 최적화된 사전 구축된 Deep Learning Containers의 전체 목록은 GitHub의 [사용 가능한 이미지](https://github.com/aws/deep-learning-containers/blob/master/available_images.md#neuron-inference-containers)에서 관리됩니다. 시작 시 DLC가 Amazon S3에서 모델을 가져오고, 저장된 모델로 Neuron TensorFlow Serving을 시작하고, 예측 요청을 기다립니다.

Serving 애플리케이션에 할당된 Neuron 디바이스의 수는 배포 yaml에서 `aws.amazon.com/neuron` 리소스를 변경하여 조정할 수 있습니다. TensorFlow Serving과 Neuron 런타임 간의 통신은 GRPC를 통해 발생하므로 `IPC_LOCK` 기능을 컨테이너에 전달해야 합니다.

1. [클러스터 생성](#create-cluster-inferentia)의 1단계에서 생성한 노드 인스턴스 역할에 `AmazonS3ReadOnlyAccess` IAM 정책을 추가합니다. 이는 샘플 애플리케이션이 Amazon S3에서 훈련된 모델을 로드하기 위해 필요합니다.

   ```
   aws iam attach-role-policy \
       --policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess \
       --role-name eksctl-inferentia-nodegroup-ng-in-NodeInstanceRole-FI7HIYS3BS09
   ```

1. 다음 콘텐츠를 가진 `rn50_deployment.yaml`이라는 파일을 생성합니다: 원하는 설정과 일치하도록 리전 코드 및 모델 경로를 업데이트합니다. 모델 이름은 클라이언트가 TensorFlow 서버에 요청할 때 식별을 위한 것입니다. 이 예에서는 모델 이름을 사용하여 예측 요청을 보내는 이후 단계에서 사용할 샘플 ResNet50 클라이언트 스크립트와 일치시킵니다.

   ```
   aws ecr list-images --repository-name neuron-rtd --registry-id 790709498068 --region us-west-2
   ```

   ```
   kind: Deployment
   apiVersion: apps/v1
   metadata:
     name: eks-neuron-test
     labels:
       app: eks-neuron-test
       role: master
   spec:
     replicas: 2
     selector:
       matchLabels:
         app: eks-neuron-test
         role: master
     template:
       metadata:
         labels:
           app: eks-neuron-test
           role: master
       spec:
         containers:
           - name: eks-neuron-test
             image: 763104351884.dkr.ecr.us-east-1.amazonaws.com/tensorflow-inference-neuron:1.15.4-neuron-py37-ubuntu18.04
             command:
               - /usr/local/bin/entrypoint.sh
             args:
               - --port=8500
               - --rest_api_port=9000
               - --model_name=resnet50_neuron
               - --model_base_path=s3://${your-bucket-of-models}/resnet50_neuron/
             ports:
               - containerPort: 8500
               - containerPort: 9000
             imagePullPolicy: IfNotPresent
             env:
               - name: AWS_REGION
                 value: "us-east-1"
               - name: S3_USE_HTTPS
                 value: "1"
               - name: S3_VERIFY_SSL
                 value: "0"
               - name: S3_ENDPOINT
                 value: s3.us-east-1.amazonaws.com
               - name: AWS_LOG_LEVEL
                 value: "3"
             resources:
               limits:
                 cpu: 4
                 memory: 4Gi
                 aws.amazon.com/neuron: 1
               requests:
                 cpu: "1"
                 memory: 1Gi
             securityContext:
               capabilities:
                 add:
                   - IPC_LOCK
   ```

1. 모델을 배포합니다.

   ```
   kubectl apply -f rn50_deployment.yaml
   ```

1. 다음 콘텐츠를 가진 `rn50_service.yaml`이라는 파일을 생성합니다: HTTP 및 gRPC 포트가 예측 요청을 수락하기 위해 열립니다.

   ```
   kind: Service
   apiVersion: v1
   metadata:
     name: eks-neuron-test
     labels:
       app: eks-neuron-test
   spec:
     type: ClusterIP
     ports:
       - name: http-tf-serving
         port: 8500
         targetPort: 8500
       - name: grpc-tf-serving
         port: 9000
         targetPort: 9000
     selector:
       app: eks-neuron-test
       role: master
   ```

1. TensorFlow 모델 Serving 애플리케이션을 위한 Kubernetes 서비스를 만듭니다.

   ```
   kubectl apply -f rn50_service.yaml
   ```

## (선택사항) TensorFlow Serving 서비스에 대한 예측
<a name="make-predictions-against-tensorflow-service"></a>

1. 로컬로 테스트하려면 gRPC 포트를 `eks-neuron-test` 서비스로 전달합니다.

   ```
   kubectl port-forward service/eks-neuron-test 8500:8500 &
   ```

1. 다음 콘텐츠를 통해 `tensorflow-model-server-infer.py`라는 Python 스크립트를 생성합니다. 이 스크립트는 서비스 프레임워크인 gRPC를 통해 추론을 실행합니다.

   ```
   import numpy as np
      import grpc
      import tensorflow as tf
      from tensorflow.keras.preprocessing import image
      from tensorflow.keras.applications.resnet50 import preprocess_input
      from tensorflow_serving.apis import predict_pb2
      from tensorflow_serving.apis import prediction_service_pb2_grpc
      from tensorflow.keras.applications.resnet50 import decode_predictions
   
      if __name__ == '__main__':
          channel = grpc.insecure_channel('localhost:8500')
          stub = prediction_service_pb2_grpc.PredictionServiceStub(channel)
          img_file = tf.keras.utils.get_file(
              "./kitten_small.jpg",
              "https://raw.githubusercontent.com/awslabs/mxnet-model-server/master/docs/images/kitten_small.jpg")
          img = image.load_img(img_file, target_size=(224, 224))
          img_array = preprocess_input(image.img_to_array(img)[None, ...])
          request = predict_pb2.PredictRequest()
          request.model_spec.name = 'resnet50_inf1'
          request.inputs['input'].CopyFrom(
              tf.make_tensor_proto(img_array, shape=img_array.shape))
          result = stub.Predict(request)
          prediction = tf.make_ndarray(result.outputs['output'])
          print(decode_predictions(prediction))
   ```

1. 스크립트를 실행하여 서비스에 예측을 제출합니다.

   ```
   python3 tensorflow-model-server-infer.py
   ```

   예제 출력은 다음과 같습니다.

   ```
   [[(u'n02123045', u'tabby', 0.68817204), (u'n02127052', u'lynx', 0.12701613), (u'n02123159', u'tiger_cat', 0.08736559), (u'n02124075', u'Egyptian_cat', 0.063844085), (u'n02128757', u'snow_leopard', 0.009240591)]]
   ```