Kubernetes

Kubernetes

이 확장 기능은 Kubernetes에서 Apache Druid를 ZooKeeper 없이 배포할 수 있게 해주는 실험적(EXPERIMENTAL) 기능이에요. Kubernetes API Server를 사용해 노드 발견과 리더 선출을 처리해요.

출처: 문서

본문

이 기능은 오랜 기간 실행되는 다양한 Druid 클러스터에서 아직 광범위하게 테스트되지 않았기 때문에 대체로 실험적(EXPERIMENTAL) 기능으로 간주하세요.

이 확장 기능은 노드 발견(node discovery)과 리더 선출(leader election)에 Kubernetes API Server를 사용할 수 있게 해주는 Apache Druid 확장 기능이에요. 이 확장 기능은 ZooKeeper 없이 Kubernetes에서 Druid 클러스터를 배포할 수 있게 해줘요. 또한 동일한 Kubernetes 클러스터 내에서 여러 Druid 클러스터를 실행할 수 있게 해주는데, 아래의 clusterIdentifier 구성을 참고하세요.

구성 (Configuration)

이 확장 기능을 사용하려면 extensions load list에 druid-kubernetes-extensions를 포함하세요.

이 확장 기능은 Druid의 HTTP 기반 세그먼트 및 태스크 관리를 함께 사용해요. 따라서 다음 구성이 모든 Druid 노드에 설정되어 있어야 해요.

druid.zk.service.enabled=false
druid.serverview.type=http
druid.indexer.runner.type=httpRemote
druid.discovery.type=k8s

노드 발견을 위해 pod 안에서 실행되는 각 Druid 프로세스는 pod spec에 라벨과 어노테이션을 추가해 스스로를 "알립니다". pod가 필요한 라벨과 어노테이션을 갖고 Kubernetes가 컨테이너를 준비(ready) 상태로 간주하면 다른 Druid 프로세스가 해당 pod를 발견할 수 있어요. readiness probe가 없으면 Kubernetes는 프로세스가 시작되는 순간 컨테이너를 준비 상태로 표시해요 — 왜 readiness probe를 구성해야 하는지는 Readiness Probes를 참고하세요.

각 Druid 프로세스는 자신의 pod 이름과 네임스페이스를 인지해야 하는데, 이를 환경 변수 POD_NAME과 POD_NAMESPACE에서 읽어요. 이 변수 이름은 변경할 수 있지만(아래 구성 참고), 모든 pod는 자신의 이름과 네임스페이스를 환경 변수로 사용할 수 있어야 해요.

또한 이 확장 기능은 다음 구성을 가져요.

속성 (Properties)

| Property | Possible Values | Description | Default | required | | druid.discovery.k8s.clusterIdentifier | string that matches [a-z0-9][a-z0-9-]*[a-z0-9] | Unique identifier for this Druid cluster in Kubernetes e.g. us-west-prod-druid. | None | Yes | | druid.discovery.k8s.podNameEnvKey | Pod Env Variable | Pod Env variable whose value is that pod's name. | POD_NAME | No | | druid.discovery.k8s.podNamespaceEnvKey | Pod Env Variable | Pod Env variable whose value is that pod's kubernetes namespace. | POD_NAMESPACE | No | | druid.discovery.k8s.leaseDuration | Duration | Lease duration used by Leader Election algorithm. Candidates wait for this time before taking over previous Leader. | PT60S | No | | druid.discovery.k8s.renewDeadline | Duration | Lease renewal period used by Leader. | PT17S | No | | druid.discovery.k8s.retryPeriod | Duration | Retry wait used by Leader Election algorithm on failed operations. | PT5S | No |

Readiness Probes (Readiness Probes)

info

readiness probe 구성은 발견 동작에 직접 영향을 줘요. probe가 너무 공격적이면(낮은 timeout, 낮은 실패 임계값) 과부하 상태의 pod가 일시적으로 probe에 실패해 발견에서 제거되고, 그 부하가 다른 pod들로 옮겨갈 수 있어요 — 잠재적으로 연쇄(cascade)를 일으킬 수 있어요. 이를 피하려면 짧은 고부하 기간을 견딜 수 있도록 probe를 조정하세요.

이 확장 기능은 라벨과 어노테이션 외에도 Kubernetes 컨테이너 readiness를 사용해 pod가 서비스 발견에 사용 가능한지 결정해요.

모든 Druid pod에 readiness probe를 구성해야 해요. readiness probe가 없으면 Kubernetes는 프로세스가 시작되는 순간 컨테이너를 준비 상태로 표시하는데, 이는 Druid 서비스가 완전히 초기화되어 요청을 처리할 수 있기 전일 수 있어요.

컨테이너가 준비되지 않게(unready) 될 수 있는 경우는:

  • 프로세스가 종료되거나 충돌한 경우. readiness probe가 실패 임계값(failureThreshold)을 넘기를 기다리지 않고 즉시 준비되지 않은 상태로 표시돼요.
  • 프로세스가 살아 있지만 건강하지 않은 경우. readiness probe가 구성된 횟수만큼(failureThreshold) 실패한 후 준비되지 않은 상태로 표시돼요.

일단 준비되지 않은 상태로 표시되면, 컨테이너는 다시 준비된 것으로 간주되어 발견에 복귀하기 전에 readiness probe를 successThreshold번(기본값: 1) 통과해야 해요.

권장 사항 (Recommendations)

/status/ready 엔드포인트는 readiness 확인에 적합한 후보예요. Druid 노드가 요청을 처리할 준비가 되었는지를 나타내기 때문이에요. 서비스들은 이 엔드포인트를 사용해 스스로를 알릴지 결정하므로, readiness probe의 자연스러운 선택이에요. 다만 필요에 더 잘 맞는 다른 엔드포인트를 선택할 수도 있어요.

시작 시간이 긴 Druid 프로세스의 경우 startup probe를 사용해 초기화 동안 readiness probe가 실행(및 실패)되지 않도록 하는 것을 고려하세요.

Druid의 기본 readiness probe 구성은 다음과 같을 수 있어요. port 값을 Druid 프로세스가 수신 대기하는 포트로 바꾸세요(예: Router는 8888, Broker는 8081):

readinessProbe:
  httpGet:
    path: /status/ready
    port: 8888
  periodSeconds: 10
  failureThreshold: 3
  timeoutSeconds: 10

이 구성에서는 pod가 준비되지 않은 상태로 표시되기 전에 readiness 확인을 연속 3번(30초) 실패해야 해요. 워크로드와 일시적으로 불건강한 pod로 라우팅하는 것에 대한 허용도에 따라 이 값을 조정하세요.

주의사항 (Gotchas)

각 pod spec의 label/annotation 경로가 존재해야 해요. pod spec에 이미 라벨이나 어노테이션이 하나 이상 있으면 쉽게 충족돼요.

하나의 Druid 클러스터에 속한 모든 Druid pod는 동일한 Kubernetes 네임스페이스 안에 있어야 해요.

모든 Druid pod는 자신의 pod에 라벨을 추가하고, 다른 pod를 list/watch하며, 리더 선출을 위해 ConfigMap을 생성·조회할 권한이 필요해요. Druid pod가 기본 서비스 계정(default service account)을 사용한다고 가정하면 다음(또는 유사한) Kubernetes Role과 RoleBinding을 추가해야 할 수 있어요.

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: druid-cluster
rules:
- apiGroups:
  - ""
  resources:
  - pods
  - configmaps
  verbs:
  - '*'
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: druid-cluster
subjects:
- kind: ServiceAccount
  name: default
roleRef:
  kind: Role
  name: druid-cluster
  apiGroup: rbac.authorization.k8s.io

더 알아보기 (Learn more)