머신러닝을 위해 AWS Inferentia 인스턴스를 Amazon EKS와 함께 사용하기
머신러닝을 위해 AWS Inferentia 인스턴스를 Amazon EKS와 함께 사용하기
이 주제는 Amazon EC2 Inf1 인스턴스로 실행되는 노드로 Amazon EKS 클러스터를 만들고 (선택적으로) 샘플 애플리케이션을 배포하는 방법을 설명합니다. Amazon EC2 Inf1 인스턴스는 AWS가 클라우드에서 고성능과 최저 비용의 추론을 제공하도록 직접 만든 AWS Inferentia 칩으로 구동됩니다. 머신러닝 모델은 Inferentia 칩의 머신러닝 추론 성능을 최적화하는 컴파일러, 런타임, 프로파일링 도구로 구성된 특수 SDK(소프트웨어 개발 키트)인 AWS Neuron을 사용해서 컨테이너에 배포돼요. AWS Neuron은 TensorFlow, PyTorch, MXNet 같은 널리 쓰이는 머신러닝 프레임워크를 지원합니다.
참고
Neuron 장치 논리 ID는 연속적이어야 합니다. 여러 Neuron 장치를 요청하는 Pod가 둘 이상의 Neuron 장치가 있는
inf1.6xlarge또는inf1.24xlarge인스턴스 유형에 스케줄링될 때, Kubernetes 스케줄러가 연속적이지 않은 장치 ID를 선택하면 해당 Pod는 시작에 실패합니다. 자세한 내용은 GitHub의 Device logical IDs must be contiguous를 참고하세요.
사전 조건 (Prerequisites)
- 컴퓨터에
eksctl이 설치되어 있어야 합니다. 설치되어 있지 않다면eksctl문서의 Installation을 참고하세요. - 컴퓨터에
kubectl이 설치되어 있어야 합니다. 자세한 내용은 Set up kubectl and eksctl을 참고하세요. - (선택) 컴퓨터에
python3이 설치되어 있어야 합니다. 설치되어 있지 않다면 설치 지침은 Python downloads를 참고하세요.
클러스터 생성
Inf1 Amazon EC2 인스턴스 노드로 클러스터를 만듭니다. inf1.2xlarge를 어떤 Inf1 인스턴스 유형으로든 바꿀 수 있어요. eksctl 유틸리티는 Inf1 인스턴스 유형으로 노드 그룹을 시작하고 있음을 감지하고, Amazon EKS 최적화 가속 Amazon Linux AMI 중 하나로 노드를 시작합니다.
참고
TensorFlow Serving에는 서비스 계정용 IAM 역할을 사용할 수 없습니다.
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 device plugin을 자동으로 설치합니다. 이 플러그인은 Neuron 장치를 컨테이너가 요청할 수 있는 시스템 리소스로 Kubernetes 스케줄러에 광고합니다. 기본 Amazon EKS 노드 IAM 정책에 더해 Amazon S3 읽기 전용 접근 정책이 추가되어, 이후 단계에서 다루는 샘플 애플리케이션이 Amazon S3에서 학습된 모델을 로드할 수 있게 해 줍니다.
모든 Pod가 올바르게 시작되었는지 확인합니다.
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 애플리케이션 이미지 배포
학습된 모델은 Inferentia 인스턴스에 배포되기 전에 Inferentia 타겟으로 컴파일되어야 합니다. 계속하려면 Amazon S3에 저장된 Neuron 최적화 TensorFlow 모델이 필요해요. SavedModel이 아직 없다면 Neuron 호환 ResNet50 모델을 만드는 튜토리얼을 따르고 결과 SavedModel을 S3에 업로드하세요. ResNet-50은 이미지 인식 작업에 쓰이는 널리 알려진 머신러닝 모델입니다. Neuron 모델 컴파일에 대한 자세한 내용은 AWS Deep Learning AMIs Developer Guide의 The AWS Inferentia Chip With DLAMI를 참고하세요.
샘플 배포 매니페스트는 AWS Deep Learning Containers가 제공하는 TensorFlow용 사전 빌드 추론 서빙 컨테이너를 관리합니다. 컨테이너 안에는 AWS Neuron Runtime과 TensorFlow Serving 애플리케이션이 들어 있어요. Neuron에 최적화된 사전 빌드 Deep Learning Containers의 전체 목록은 GitHub의 Available Images에 유지 관리됩니다. 시작 시 DLC는 Amazon S3에서 모델을 가져와 저장된 모델로 Neuron TensorFlow Serving을 실행하고 예측 요청을 기다립니다.
서빙 애플리케이션에 할당되는 Neuron 장치 수는 배포 yaml에서 aws.amazon.com/neuron 리소스를 변경해서 조정할 수 있어요. TensorFlow Serving과 Neuron 런타임 간 통신은 GRPC를 통해 이루어지며, 컨테이너에 IPC_LOCK 기능을 전달해야 한다는 점을 유의하세요.
Create a cluster의 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
다음 내용으로 rn50_deployment.yaml 파일을 만듭니다. 원하는 설정과 일치하도록 region-code와 모델 경로를 업데이트하세요. 모델 이름은 클라이언트가 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
모델을 배포합니다.
kubectl apply -f rn50_deployment.yaml
다음 내용으로 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
TensorFlow 모델 Serving 애플리케이션용 Kubernetes 서비스를 만듭니다.
kubectl apply -f rn50_service.yaml
(선택) TensorFlow Serving 서비스에 대해 예측 실행
로컬에서 테스트하려면 gRPC 포트를 eks-neuron-test 서비스로 포워딩합니다.
kubectl port-forward service/eks-neuron-test 8500:8500 &
다음 내용으로 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_neuron'
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))
스크립트를 실행해서 서비스에 예측을 제출합니다.
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)]]
더 알아보기 (Learn more)
출처: 문서