공부하고 기록하는, 경제학과 출신 개발자의 노트

학습일지/Knative

KnativeCon 2022 NA - Achieving a highly Available / Scalable Multi-Tenant Eventing backend - Eventing Scheduler

inspirit941 2022. 12. 10. 13:30
반응형

Achieving a highly Available / Scalable Multi-Tenant Eventing backend

영상: https://youtu.be/PKuUXaDl7w0

 

발표자료: https://knativeconna22.sched.com/event/1AGbi/achieving-a-highly-available-and-scalable-multi-tenant-eventing-backend-architecture-in-your-serverless-products-ansu-ann-varghese-aleksander-slominski-ibm

 


발표자

  • Ansu Varghese : IBM Senior SW Engineer within Hybrid Cloud Research.

스크린샷 2022-12-09 오후 1 11 52

  • 현재 knative의 pull-based components (Eventing Sources / CR) / Eventing backend에는 크게 두 가지 문제가 있음
    • Autoscaling out of box 기능을 지원하지 않음.
    • Serverless Experience에 맞게 scale up / down되지 않음.
  • 위 기능은 Enterprise Organization solution을 knative으로 구성하려면 꼭 필요한 기능임.

Eventing Scheduler 제안.

  • scaling solution
  • distribute consumers across the data plane pods, based on your priorities.
  • 데모: kafkaSource를 scale out
  • Ongoing: scheduler를 다른 knative component에 적용하기 / KEDA autoscaler에 통합하려는 작업을 진행중.

 

스크린샷 2022-12-09 오후 1 19 42

 

Knative로 Event-Driven Architecture 프로덕트를 구상하려는 사용자의 Expectation.

  • Knative는 Serverless 프로덕트 => AutoScaling 기능.
    • 쓰지 않게 되면 Scale Down to 0, pull로 들어오는 이벤트 양에 따라 Scale out
    • 즉 Workload demand 변화에 따라 idle / fast 하게 반응할 수 있어야 한다.
    • multi-tenant 환경
  • Efficient Resources utilization.
  • Data plane / Controller는 max throughput / compute density on running cluster.
  • High Availablity, Resilient. 장애가 생겨도 영향도는 최소화할 수 있어야 함.

 

스크린샷 2022-12-09 오후 1 59 12

 

현재의 구조

  • 하나의 dispatcher 당 하나의 knative resource가 할당됨.
  • consumer가 늘어나면 dispatcher도 같이 늘어남.
  • throughput 증가를 위한 parallelism이 지원되지 않음. scaling으로 throughput 증가시켜야 하는데 autoscale도 지원하지 않음

New Eventing Scheduler

  • 하나의 dispatcher가 여러 consumer와 연결될 수 있도록 partitioning
  • Delivery Parallelism
  • KEDA autoscaler와 integration

스크린샷 2022-12-09 오후 2 10 25

대략적인 구조. kubernetes scheduler를 많이 참고한 구조.

  • Duck Type API (Placement) : outcome resulting from scheduler.
    • data plane architecture의 동적 타입
    • 실제 pod에 연결되어 있는 virtual replicas의 정보를 기록한다.
  • Sub Component
    • scheduler / De-scheduler
    • autoscaler : 관리해야 할 replicas가 많아지면 data plane pod의 개수를 늘린다.
    • state collector : cluster 상태를 주기적으로 체크해서 scheduler가 최적의 판단을 내릴 수 있도록 함
    • compactor / evictor : compactor는 주기적으로 distribution 상태를 체크하고, evictor는 lower ordinal pod에 공간이 있으면 higher pod에 있는 Replica를 lower로 옮긴다.
  • 스케줄링 방법에 관련된 로직은 plugin 형태로 추가해서 쓸 수 있음. core logic을 간결하게 만들어서 유지보수 편의성을 높일 목적.
    • 스케줄링의 절차는 stage 단위로 이루어진다.
      • filter stage: filter plugin인 predicates에서 로직 수행.
        • replica를 할당할 수 없는 Pod인지 아닌지 판단함.
      • scoring stage: scoring plugin인 priorities에서 로직 수행
        • filter 통과한 pod에 score를 부여함.
        • 스케줄러는 score sum이 가장 큰 pod을 선택한다.
    • plugin은 스케줄러에 register & compile되어 동작한다.
  • Recovery: unexpected domain failure / planned worker restart 등의 용도로 쓰임
    • data plane replicas used for scheduling consumers -> statefulSet architecture.
    • consumer 숫자의 변화로 rebalancing 동작... reconcile loop 로직으로 동작함.

스크린샷 2022-12-09 오후 5 03 00

 

기존 KafkaSource

  • Consuming Messages for One or more kafka topics -> single Sink Service로 cloudevent 전달하는 컴포넌트.
    • user가 사용하는 external API 역할.

새로운 컴포넌트 개념 도입 : ConsumerGroup / Consumers

  • internal API. 사용자가 신경쓸 필요 없는 영역.
  • kafka에서 쓰는 Consumer와는 다른 개념. (바꿀 생각도 하고 있음)

kafkaSource는 ConsumerGroup을 생성한다.

  • ConsumerGroup은 Eventing Scheduler에서 사용할 virtual pod.
  • virtual Pod의 Replica 개수에 따라 scale up / down 되고, KEDA autoscaler가 통제하거나 개발자가 수동으로 scale 조정할 수 있다.

Eventing Scheduler

  • virtual replica를 data plane pod (real k8s pod)에 배치하고, kafkaSource의 status field로 값이 propagate(전파) 되도록 한다.
    • (now, the job of scheduler is to place these virtual replicas onto real kubernetes pods, and then come up with a set of placements which is then propagated back to kafkasource status fields.)
  • Consumer라는 Resource가 real pod에 매핑된다. (하나의 consumer는 하나의 pod에 매핑됨.)

화면 오른쪽의 configmap은 scheduler 설정.

  • priorities / predicates는 요구사항아 맞게 설정하면 된다.

 

스크린샷 2022-12-09 오후 5 30 51

 

  • General Standalone Eventing Scheduler를 설계한 가장 큰 이유는 Reusability.
  • scheduler의 동작 방식에서 사용자의 Configurable 자유도를 제공함.
  • 확장성이 높고 결합도를 낮춘 Resource Controller
  • Availability / Scalability 제공

 

스크린샷 2022-12-09 오후 5 49 00

 

Demo

kafkaSource Autoscale - scale to zero

KafkaSource 설정값: https://github.com/aavarghese/eventing-kafka-broker/blob/knativecon-demo/source-demo.yaml

apiVersion: sources.knative.dev/v1beta1
kind: KafkaSource
metadata:
  name: kafka-source-demo
  annotations:
    eventing.knative.dev/broker.class: Kafka
    autoscaling.knative.dev/class: keda.autoscaling.knative.dev
    autoscaling.knative.dev/minScale: "0" 
    autoscaling.knative.dev/maxScale: "12" 
    keda.autoscaling.knative.dev/pollingInterval: "3" 
    keda.autoscaling.knative.dev/cooldownPeriod: "10" 
spec:
  consumers: 12
  consumerGroup: my-demo-group
  bootstrapServers: 
  - kafka-0.mh-lbnyvywmvwwvpcmssqgl-4c201a12d7add7c99d2b22e361c6f175-0000.us-south.containers.appdomain.cloud:9093
  - kafka-1.mh-lbnyvywmvwwvpcmssqgl-4c201a12d7add7c99d2b22e361c6f175-0000.us-south.containers.appdomain.cloud:9093
  - kafka-2.mh-lbnyvywmvwwvpcmssqgl-4c201a12d7add7c99d2b22e361c6f175-0000.us-south.containers.appdomain.cloud:9093
  topics:
  - my-demo-topic
  net:
    sasl:
      enable: true
      type:
        secretKeyRef:
          name: kafka-secret-source
          key: type
      user:
        secretKeyRef:
          name: kafka-secret-source
          key: username
      password:
        secretKeyRef:
          name: kafka-secret-source
          key: password
    tls:
      enable: true
  sink:
    ref:
      apiVersion: v1
      kind: Service
      name: eventdisplay

스크린샷 2022-12-09 오후 6 04 47

kafkaSource를 배포한 다음 kubectl get consumergroup 으로 consumergroup 상태를 확인한다.

  • kafkaSource에서 consumer를 12로 선언했으므로, replicas가 12개.
  • placement 정보를 확인해보면, 12개의 replica가 4개의 kafka dispatcher와 연결된 것을 볼 수 있다.
    • dispatcher pod를 multiple nodes in different zones -> HA 확보.

 

스크린샷 2022-12-09 오후 6 08 55

 

KEDA의 scale을 변경하면 (kubectl scale --replicas=1 deployment keda-operator -n keda)

  • keda Operator가 올라오면, consumergroup에서 볼 수 있는 replica 값이 12 -> 0으로 내려갔다.
  • kafkaSource가 idle 상태이므로, event를 받지 않았으니 scale to zero로 내려간 것.

 

스크린샷 2022-12-09 오후 6 12 36

 

오른쪽 상단의 터미널에서 kafka에 메시지를 넣은 다음 consumergroup을 조회하면, replica값이 0에서 1로 변경된 걸 볼 수 있다.

  • 하단 터미널에서 eventDisplay pod의 로그를 조회하면, kafka로 보낸 메시지가 cloudevent로 변환되어 정상적으로 sink에 들어온 것을 확인할 수 있다.
  • 시간이 지나면 다시 scale to zero.

Recovery

스크린샷 2022-12-10 오후 12 09 12



스크린샷 2022-12-10 오후 12 13 17



  • kafka로 10만 건의 메시지를 보내고, kubectl scale --replicas=60 consumergroup <consumergroupName> 명령어로 replica를 60으로 지정.
    • 10만 건의 메시지를 처리하기 위해 replica가 60으로 올라간 걸 볼 수 있다.
  • kubectl describe pod kafka-source-dispatcher-2 -n knative-eventing | grep Node 명령어로 kafka dispatcher가 돌고 있는 노드의 ip주소를 확인
    • demo에서는 노드 버전을 업그레이드하는 식으로 해당 노드를 비활성화함.
    • 다시 dispatcher의 노드를 확인하면, 다른 노드로 pod가 이동한 것을 볼 수 있다.

Lesson Learned

스크린샷 2022-12-10 오후 12 13 45

  • kafkaSource는 'at least once ordered delivery'를 보장한다. 즉 return code가 돌아오지 않으면 retry를 수행하는 식으로 resiliency를 확보.
  • 하지만 실제로 테스트해보면
    • kafka가 아니라 다른 컴포넌트의 퍼포먼스 이슈로 duplicate event를 처리하는 상황이 종종 발생.
      • 예컨대 queue로 받은 이벤트 처리에 시간이 오래 걸려서
      • not enough concurrent clients to process events synchronosly
  • kafkaBroker를 써서 kafka Consumer Configuration을 configmap으로 설정할 수 있다. parameter tuning이 중요했음
    • lower the number of duplicate messages
    • speed up concurrent processing

 

스크린샷 2022-12-10 오후 12 21 30

 

  • Eventing Scheduler와 knative-based kafka component (broker / channel) 를 연동하는 작업을 진행중.
  • Autoscaling과 Scheduling을 동일한 api에서 처리할 수 있도록 만드는 것이 목표
반응형