본문 바로가기
Big Data

[KUBEFLOW] 1. Data science at scale

by 유주원 2022. 2. 12.

https://www.manning.com/books/kubeflow-in-action 

 

Kubeflow in Action

Kubeflow simplifies and automates machine learning tasks like interactive analysis, complex pipelines, and model training. Seamlessly push models to production in the containerized and distributed environment and scale your ML infrastructure from your lapt

www.manning.com

kubeflow는 데이터 사전 처리에서 모델 학습, 배포까지의 모든 기능을 제공하는 프레임워크이다.

 

1.1 왜 k8s와 kubeflow가 필요할까?

- 아래의 그림을 보면 쉽게 알 수가 있다. 데이터 과학자는 대부분 아래와 같은 자신의 업무를 행하고 있다.

 

데이터 수집 -> 데이터 분석 및 클렌징 -> 모델 학습 -> 배포 및 모니터링까지의 모든 작업을 kubeflow에서는 손쉽게 제공해 주고 있다.

또한 kubeflow는 k8s 상에서 동작되고 있으며 컨테이너 단위로 움직일 수가 있다. 그렇게 때문에 손쉽게 워크노드의 확장이 가능하다.

 

1.2 OS, VM 그리고 컨테이너

기존 VM 구조는 아래와 같이 host OS 위쪽에 hypervisor를 통해 이기종의 os를 띄울 수 있도록 되어 있다. hypervisor에서는 vm os들의 리소스 등을 제한해 주거나 isolation등을 제공해주는 역할을 하고 있다.

컨테이너는 어떨까?

hypervisor 위치에 Container Runtime이라는 layer가 들어 있는 것을 확인할 수 있다. Container Runtime은 docker script를 읽고, 이미지를 만들고 컨테이너와 해당 이미지를 관리하는 역할을 한다. 가장 많이 쓰이고 있는 것은 Docker이며, OKD에서는 CRI-O를 사용한다.

 

1.2.2 k8s와 OKD

OKD의 경우 컨테이너의 보안 요소가 강화되어 있다. 예를 들어 dockerfile 내에 USERID가 따로 지정되어 있지 않다면, 해당 docker 컨테이너가 루트 ID를 상속받기 때문에, dockerfile은 실행되지 않는다. 

 

Master 와 Worker Node

k8s에서는 모든 머신을 Node라고 표현하며, Control plane 기능을 수행하는 머신을 Master Node, 실제 애플리케이션을 실행하는 머신을 Worker Node라고 표현한다. k8s에서 관리하는 단일 클러스터에는 최소한 하나의 Master Node와 하나의 Worker Node가 있어야 한다. 일반적으로 Master Node에서는 애플리케이션 pod가 실행되지 않는다.

Control plane 기능으로는 컨테이너 스케줄링, API 서버, 데이터 저장소 등의 기능이 있다.

 

Kubernetes API

pod, 서비스, ingress 등은 모두 k8s 내부의 리소스 개체로 표시가 된다. 이러한 리소스 개체는 kubernetes API를 사용해서 사용자가 직접 생성, 변경 및 삭제할 수 있다.

사용자가 yaml 파일을 작성한 후 kubernetes의 "kubectl" 또는 OKD의 "oc" 등을 통해 명령을 전달하면, 해당 명령은 kubernetes API에 전달되고 kubernetes에 의해 실행이 된다. 아래 그림은 pod를 생성하는 예시를 보여주고 있다. 사용자가 pod를 생성하겠다는 명령을 kube-apiserver에 보내면, kube-apiserver는 etcd에 정보를 저장하고 kube-scheduler에 문의해서 pod를 생성할 수 있는 node를 할당 받는다. 할당된 node의 kubelet에서는 컨테이너 런타임에 컨테이너를 생성하고, pod에서 실행하도록 작업을 수행한다.

Pods, Deployment and ReplicaSet

pod는 k8s에서 배포 가능한 가장 작은 단위이며, 하나 이상의 컨테이너로 구성이 된다. 왜 여러 개의 컨테이너를 띄워야 할까? 

대표적인 예는, 한 컨테이너가 모델에 대한 모든 REST 호출을 처리하고, 다른 컨테이너가 모델 코드를 처리하는(sidecar) 구조에서 여러 개의 컨테이너가 필요한 이유를 찾을 수 있다. 

pod 내에서 실행되는 컨테이너들은 스토리지와 네트워크 리소스의 공유가 가능하다.

클러스터 상에서 실행되는 pod는 deployment라는 리소스에 의해 제어된다. deployment는 ReplicaSet도 함께 제어한다.

아래 그림은 deployment 파일의 예를 보여주고 있다. k8s에서는 이 배포 파일을 읽고 지속적으로 원하는 상태를 실제 상태와 일치시키려고 시도하고 일치 상태를 유지힌다. pod를 영구적으로 삭제하기 위해서는 연결된 deployment를 삭제해야 한다.

Services, Ingress/Routes, Istio

k8s의 서비스는 여러 웹서버에 전역 도메인 이름을 할당하는 것과 비슷하다. k8s의 서비스는 하나 또는 여러 개의 pod를 정의할 수 있으며, ip 또는 internal single domain name(your-svc.your-namespace.svc.cluster.local)으로 처리되기 때문에 여러 포드 사이에서 로드 밸런싱 될 수 있다. 해당 ip 또는 도메인은 클러스터 또는 네임스페이스 내에서만 액세스 할 수 있다. 서비스를 외부에 노출하기 위해서는 Ingress 또는 Route를 이용해야 한다. 해당 서비스에는 외부 도메인 이름이 할당 될 수 있다.

Ingress/Route에서 제공하는 기능을 포함하여 마이크로 서비스 간에 다양한 기능을 제공하기 위해 istio라는 서비스 메시 플랫폼이 도입되었다. kubeflow는 기본적으로 istio를 설치하고 이 플랫폼을 사용해서 마이크로서비스를 관리한다. istio는 라우팅 외에도 마이크로 서비스 간의 보안 규칙 및 모니터링 기능을 제공한다. 아래 그림은 외부 트래픽을 kubeflow의 pod로 전달하는 것과 관련된 구성 요소를 보여준다.

kubeflow Gateway와 같은 게이트웨이 및 Virtual Service A와 같은 가상 서비스는 서로 다른 pod에 라우팅 기능을 제공하는 istio 구성 요소이다.

Storage and Networking

컨테이너의 파일 시스템에 저장된 모든 파일은 컨테이너를 다시 시작할 때 손실된다. volumns 또는 Persistent Volumns라는 영구 저장소를 만들고 사용해야 한다. volumn은 아래 예와 같이 컨테이너 컨텍스트에서 설명할 수 있다. Persistent Volumn은 아래 예와 같이 yaml을 정의해서 생성할 수 있다. Persistent Volumn이 생성되면 컨테이너는 아래 예와 같이 Persistent Volumn Claim을 생성해서 사용할 수 있다. 

 

apiVersion: v1
kind: Pod
metadata:
  name: appa
spec:
  containers:
  - image: nakfour/pythonapp:0.1
    name: appa
    volumeMounts:
    - mountPath: /data
      name: datavolume
  volumes:
  - name: datavolume
    emptyDir: {}
 
 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: example-volume
spec:
  storageClassName: manual
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/mnt/data"
 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: example-pvc
spec:
  storageClassName: manual
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
 
apiVersion: v1
kind: Pod
metadata:
  name: appa
spec:
  volumes:
    - name: pod-storage
      persistentVolumeClaim:
        claimName: example-pvc
  containers:
    - image: nakfour/pythonapp:0.1
      name: appa
      volumeMounts:
        - mountPath: "/data"
          name: pod-storage

Operators

앞에서 설명한 것처럼 pod, service, deployment는 모두 Kubernetes API를 사용하여 생성, 삭제 및 수정할 수 있는 Kubernetes 리소스 개체이다. 플랫폼을 더욱 강력하게 만들기 위해 kubernetes를 통해 개발자는 API를 확장하고 새 리소스 또는 사용자 지정 리소스를 정의하고 사용자가 이러한 새 리소스를 생성, 삭제 또는 수정할 수 있도록 하는 애플리케이션 컨트롤러를 작성할 수 있다. 

이러한 새 응용 프로그램과 해당 사용자 지정 리소스를 operators라고 한다. 개발자는 아래 그림과 같이 OKD 대시보드를 통해 operatorhub.io 또는 OperatorHub에 자신의 Operators를 게시할 수 있다.

 

Operators는 효율적인 리소스 관리 및 원할한 애플리케이션 관리를 위한 자동 업그레이드 및 매트릭 수집과 같은 애플리케이션 관리 기능을 제공한다.