Knative 연구하기(Serving)

반응형

Knative 연구하기

안녕하세요 김민욱입니다.

 

최근 개인적으로 Serverless 분야를 흥미있게 연구하고 있는데 이전에 포스팅 했던 Faas(Function as a Service) 프로젝트인 OpenFaaS와 더불어 Kubernetes 인프라 상에서 동작하는 Serverless 프로젝트인 Knative에 정리하고자 합니다.

 

Knative는 2018년 7월 구글에서 발표한 오픈소스 프로젝트로  Knative를 사용하면 컨테이너 기반의 어플리케이션을 쉽게 개발하고 배포하며 또 관리 할 수있게 됩니다. 

그림 1. Knative

그림 1과 같이 Knative를 통해 개발자들은 서버 관리 등에 대해서 고려할 필요없이 오로지 어플리케이션 개발 및 배포에만 신경쓸 수 있게 되며, 사용자 역시 API를 통해 어플리케이션이 제공하는 기능을 사용할 수 있습니다. 물론 기존의 VM 환경과 다르게 사용한 만큼, 즉 서비스를 호출한 만큼만 비용을 지불하게 됩니다. 

 

이번 글에서는 Serving을 우선적으로 확인하고, 이후 Auto Scaling, Eventing 그리고 개발 환경 구축까지 확인하고자 합니다. 

 

Knative 컴포넌트

Knative는 크게 Serving과 Eventing 컴포넌트로 구성됩니다. Serving은 어플리케이션의 라이프사이클을 담당하고 Eventing은 서비스 요청에 대한 필터링 등의 기능을 제공합니다. Serving 및 Eventing 컴포넌트는 Knative-serving, knativer-eventing 네임스페이스의 Pod들로 구성됩니다. 

#Knative Serving

Knative Serving은 Serverless Applicatin Container들을 배포하고 라이프 사이클을 관리하는 역할을 합니다. 특히 어플플리케이션의 관리뿐만 아니라 어플리케이션의 요청이 없을 경우 Pod의 수를 0으로 축소하는 Auto Scaling 기능을 제공하고 있습니다.  또한 Istio와 같은 Data들의 Control Plane 기능을 쉽게 제공하여 트래픽을 관리할 수 있습니다. 

 

Serving은 Custom Resource Definitions(CRD)로 다양한 오브젝트들을 정의하고 있습니다. 해당 CRD들은 Serving을 구성하는 매우 중요한 오브젝트들로 해당 오브젝트들의 실제 기능을 구현한 각각의 컨트롤러들도 모두 구성되어 있습니다. 따라서 Knative는 CRD, Controller, Pod들의 다양한 조합으로 구현되어 있습니다.

 

그림 2. Serving Component Deployment

그림 1에서는 Knative Operator를 사용하여 Serving 컴포넌트를 배포할때 나타나는 과정을 나타냅니다. Knative Operator는 Serving 생성 요청을 감지하고 Serving Pod들을 배포합니다. Serving은 4개의 Pod들로 구성되어 있고 이들 모두 배포됩니다.  그 중 Controller Pod는 서버리스 서비스의 라이프사이클을 관리하는 다양한 오브젝트들의 생성 감지를 위해 오브젝트별 컨트롤러들을 통해 이벤트를 등록합니다.

 

그림 3. Create Controller Workflow

 

Serving이 배포되면, 그림 2에서 보이는 바와 같이 Controller pod 내부 코드에서 ctors 리스트에 정의된 컨트롤러 목록을 읽어 Go routine으로 동작하게 되는데, 이때 각 오브젝트별 컨트롤러들은 Informer 함수를 통해 EventHandler에 등록됩니다.  따라서 모든 오브젝트 컨트롤러는 이벤트를 등록하고 그 이후 이벤트가 발생하게 되면, Controller Pod 코드의 Service.go, Configuration.go에 구현된 기능을 실행하게 됩니다.

 

그림 4. Serving 아키텍쳐

그림 2에서는 Serving 아키텍쳐를 나타냅니다. 해당 아키텍쳐에서 나타난 모든 오브젝트들은 Serving 배포시에 모두 CRD로 등록이 됩니다. 앞서 말씀드린 바와 같이 실질적인 기능을 수행하는 오브젝트들은 Pod가 아닌 Custom Resource로써 동작하게 됩니다.

그림 5. Knative Serving CRD

그림 3에서는 Knative Serving CRD를 나타냅니다. 해당 CRD들은 Serving 배포시에 자동으로 등록되게 됩니다. 따라서 Kubernetes와 연동하여 Knative의 기능들을 사용할 수 있게 됩니다. 

 

우선 서버리스 서비스를 배포하고 사용하기 위해 핵심 적인 오브젝트들을 먼저 살펴 보겠습니다. 

 

그림 6. Knative Serving Object[1]

 

Service는 서버리스 어플리케이션에 대해 전반적인 라이프사이클을 자동적으로 관리하게 되는데, 특히 다양한 버전의 서버리스 어플리케이션이 배포되어 있는 경우, 가장 최신의 버전의 어플리케이션으로 트래픽을 전달할 수 있도록 하거나 특정 버전의 어플리케이션으로 라우팅 할 수 있도록 정의 할 수 있습니다.

 

마찬가지로 Serving 배포시 Controller로 동작하면서, 어플리케이션 생성시 동시에 Service Custom Resource가 생성되고 Controller는 이를 감지하여 구현된 Service 기능을 수행합니다. 

 

Route는 네트워크 엔드포인트를 Revision과 매핑시키거나, Kubernetes Service, Ingress를 통해 traffic을 관리하는 기능을 제공합니다. 

 

Configuration는 어플리케이션이 생성되면 원하는 상태를 유지할 수 있도록 합니다. 특히 다양한 버전의 Revision 즉 다양한 어플리케이션을 배포했을 때 일종의 포인터 처럼 가장 최신의 Revision 정보를 가지고 있습니다. 

 

Revision은 특정 어플리케이션 혹은 코드가 배포된 시점의 정보입니다. 특히 Knative Serving Revision으로 들어오는 트래픽을 유동적으로 관리 할 수 있습니다. 

 

그림 7. Knative Servig Pods

앞서 Serving의 주요한 컴포넌트와 개념들을 알아보았고, 그림 6에서 보이는 것과 같이 실제 배포된 Serving Pod들에 대해 각각 설명하고자 합니다. 

 

Controller는 서버리스 서비스 구성에 전반적인 기능을 제공합니다. AutoScaling, Knative 오브젝트들을 관리하고 동작시키면서, Kubernetes API를 통해 Knative 서비스 생성이 감지 되면 순차적으로 Configuration 등을 생성하게 됩니다. (대략적으로 코드만 보며 사실 생성이라기 보단 기능 실행에 가까울 것같습니다.)

 

Webhook은 이름 그대로 Kubernetes API 호출들을 보면서 CRD 업데이트, 삽입 및 API에 대한 유효성 검사 기능을 제공합니다.

 

Activator는 Auto Scaling 관련 기능으로 서버리스 서비스에 대한 요청이 들어오는 경우  Pod 생성 여부를 확인하고 생성되어 있지 않다면 요청 데이터를 잠시 보관하고 생성이 완료된 후 이후에 Pod들에게 요청을 전달하는 기능합니다. 따라서 서비스 Pod가 없다면 요청을 대신 받습니다.

 

Autoscaler는 Activator와 연동하여 Pod의 요청 수에 따라 Pod를 생성하거나, 삭제하는 기능을 합니다.

 

그림 8. Knative Service Deployment

그림 7에서는 서버리스 생성에 대한 절차를 나타냅니다. 먼저 서비스 배포를 위해 yaml을 작성하게 되는데, Kubernetes와 동일하게 컨테이너 스펙을 작성하고 metadata 부분은 Revision 스펙으로 분류됩니다. 또한 Traffic에 설정된 내용은 Route가 이를 인지하여 Kubernetes ingress, service등과 연동하여 트래픽을 조절하게 됩니다.  특히 서버리스 서비스 Pod에 서비스 요청에 대한 메트릭을 수집하기 위한 Queue Proxy가 같이 포함됩니다.

 

그림 9. 서비스 내부 동작

 

전달된 요청은 Controller Pod에서 인지하게 되고, Main Controller는 순차적으로 Service.go에 있는 기능을 호출하여 Configuration.go, Revision.go, Route.go에 정의된 기능을 호출하여 서비스 생성을   서비스 생성을 진행합니다. 실제로 Main Controller에서 가장 먼저 호출하는 Service.go 파일에서 createRoute와 createConfiguration 함수가 호출됩니다. 결론적으로 Revision.go는 Kubernetes API를 통해 Deployment-> Replicaset-> POD 순으로 서버리스 서비스가 생성됩니다. 

 

 

결론

이번 포스팅에서는 Serving에 대해서 알아보았습니다. 현재까지는 대략적으로 코드 레벨에서의 워크플로우만 대략적으로 파악했지만, 이후 에는 각각의 오브젝트들에 구현된 코드들 기능까지 라인 바이 라인으로 분석할 예정입니다.

 

다음 글에서는 Serving에서 제공하는 Auto Scaling 기능에 대해 말씀드리겠습니다. 혹 오류가 있는 부분이 있다면, 말씀주시면 수정하도록 하겠습니다. 감사합니다.

인용글

[1] Knative docs : https://knative.tips/eventing/delivery-methods/broker-trigger-delivery/

업데이트로그

--------------------------------------------------------------------------------------------------------------

해당 글은 스스로 연구한 내용을 통한 주관적인 이해를 바탕으로 작성 되었습니다. 수정 할 부분이 있거나, 다른 의견이 있으시다면 언제든지 말씀해주시면 반영하도록 하겠습니다. 읽어 주셔서 감사합니다. 끝으로 불법으로 복제하는 것은 금합니다.

 

반응형

댓글

Designed by JB FACTORY