'좌충우돌 커리어'에 해당하는 글 8건

Distributor (배포)

Distributor 서비스는 클라이언트에서 들어오는 streams를 처리하는 역할을 함. 로그 데이터에 대한 쓰기 경로의 첫 번째 장소이다. 일단 distributor가 stream 셋을 받으면 각 stream의 정확성이 검증되고 구성된 테넌트 (혹은 전역) 내에 있는지 확인한다. 그런 다음 유효한 청크를 배치(batch)로 분할하고 병렬로 여러 수집기(ingester)로 보낸다.

distributor의 트래픽 균형을 적절하게 맞추기 위해 로드 밸런서(load balancer)를 그 distributor 앞에 두는 것이 중요하다.

distributor는 stateless(상태를 저장하지 않는) 컴포넌트(구성 요소)이다. 따라서 쓰기 경로에서 가장 중요한 구성 요소인 distributor에서 가능한 한 많은 작업을 쉽게 확장(scale)하고 오프로드(offload)할 수 있다(작업을 내릴 수도 있다). 이러한 검증 작업을 독립적으로 확장할 수 있다는 것은 loki가 distributor에 과부하를 줄 수 있는 서비스 거부 공격(악의적이든 아니든) 으로부터 스스로를 보호할 수 있음을 의미한다. 그들은 정문에서 경비원처럼 행동하여 모든 사람이 적절한 옷을 입고 초대장을 받았는지 확인한다. 또한 replication factor(복제 요소)에 따라 쓰기를 fan-out 할 수 있다.

Validation (확인)

distributor가 취하는 첫 번째 단계는 들어오는 모든 데이터가 사양에 맞는지 확인하는 것이다. 여기에는 레이블이 유효한 Prometheus 레이블인지 확인하고 타임스탬프가 너무 오래되거나 새롭지 않거나 로그 줄이 너무 길지 않은지 확인하는 작업 등이 포함된다.

Preprocessing (전처리)

현재 distributor가 들어오는 데이터를 변경하는 유일한 방법은 레이블을 정규화하는 것이다. 이것이 의미하는 바는 {foo="bar", bazz="buzz"}를 {bazz="buzz", foo="bar"}와 동일하게 만드는 것, 레이블을 정렬하는 것이다. 이를 통해 loki는 레이블을 결정적으로 캐시(cache)하고 해시(hash)할 수 있다.

Rate limiting (속도 제한)

distributor는 최대 테넌트 당 비트 전송률을 기반으로 들어오는 로그 속도를 제한할 수 있다. 이는 테넌트 당 한도를 확인하고 이를 현재 distributor 수로 나누어 수행한다. 이렇게 하면 클러스터 수준에서 테넌트 별로 속도 제한을 지정할 수 있으며 distributor를 확장하거나 축소하고 그에 따라 distributor당 제한을 조정할 수 있다. 예를 들어 10명의 distributor가 있고 테넌트 A의 속도 제한이 10MB라고 가정하자. 각 distributor는 제한 하기 전 최대 1MB/초를 허용한다. 이제 다른 대규모 테넌트가 클러스터에 합류하고 10개의 distributor를 추가로 가동해야 한다고 가정하자. 이제 20개의 distributor가 테넌트 A에 대한 속도 제한을 (10MB / 20 distributor) = 500KB/s로 조정한다. 이것이 전역 제한이 로키 클러스터 동작을 더 단순하고 안전하게 만드는 방법이다.

distributor는 후드 아래에 있는 링 구성 요소를 사용하여 peer(동료) 사이에 자신을 등록하고 활성 distributor의 총 수를 얻는다,. 이것은 링에서 사용하는 ingestor와 다른 key이며 distributor의 자체 링 구성에서 가져온다.

Forwarding (전송)

distributor가 모든 유효성 검사 작업을 수행하고 나면 최종적으로 쓰기 승인을 담당하는 수집 구성 요소에 데이터를 전달한다. 

Replication factor (복제 인자)

단일 ingester에서 데이터 손실 가능성을 줄이기 위해 distributor는 쓰기를 해당 데이터의 replication_factor로 전달한다. 일반적으로 이 값은 3이다. replication은 쓰기 실패 없이 ingester 재시작 및 롤아웃(rollout)을 허용하고 일부 시나리오의 경우 데이터 손실에 대한 추가 보호 기능을 추가한다. 느슨하게 distributor에게 푸시되는 각 레이블 세트(Stream)에 대해 레이블을 해시(hash)하고 링(ring, 분산 해시 테이블을 노출하는 하위 구성요소)에서 replication_factor ingester를 찾는다. 그런 다음 모두에 동일한 데이터를 쓰려고 시도한다.

쓰기 쿼럼(quorum) 미만이 성공하면 오류가 발생한다. 쿼럼은 floor(replication_factor / 2) + 1로 정의된다. 따라서 replication_factor가 3인 경우 두 번의 쓰기가 성공해야 한다. 2개 미만의 쓰기가 성공하면 distributor가 오류를 보여주고 쓰기를 다시 시도할 수 있다. 

주의 사항: 3개의 ingester 중 2개가 수행하는 경우, 쓰기를 승인하는 edge 케이스도 있다. 즉, 2개의 쓰기가 성공한 경우 데이터 손실을 겪기 전에 하나의 ingester만 잃을 수도 있다.

하지만 복제 요소가 데이터 손실을 방지하는 유일한 것은 아니며, 오늘날에는 롤아웃 및 다시 시작하는 동안 중단 없이 쓰기를 계속할 수 있도록 하는 것이 주된 목적이다. ingester 구성 요소에는 디스크가 손상되지 않는 한 손실되지 않도록 디스크에 들어오는 쓰기를 지속하는 미리 쓰기 로그가 포함된다. replication factor(복제 요소)와 WAL의 상호 보완적인 특성은 두 메커니즘 모두에 심각한 장애(예: 여러 ingester가 죽고 디스크가 손실/손상 됨)가 발생하지 않는 한 데이터가 손실되지 않도록 한다. 

Hashing (해싱)

distributor는 구성 가능한 replication component(복제 요소)와 함께 일관된 해싱을 사용하여 주어진 Stream을 수신해야 하는 ingester 서비스 인스턴스를 결정한다. 

Stream(스트림)은 테넌트 및 고유한 레이블 집합과 연결된 로그 집합이다. 스트림은 테넌트 ID와 레이블 집합을 모두 사용하여 해시된 다음 해시를 사용하여 스트림을 보낼 ingester를 찾는다. 

Consul에 저장된 해시 링(hash ring)은 일관된 해싱을 달성하는 데 사용된다. 모든 distributor는 자신이 소유한 토큰 세트를 사용하여 해시 링에 자신을 등록한다. 각 토큰은 임의의 부호 없는 32비트 숫자이다. 토큰 세트와 함께 distributor는 자신의 상태를 해시 링에 등록합니다. 상태 JOINING 및 ACTIVE는 모두 쓰기 요청을 수신할 수 있는 반면 ACTIVE 및 LEAVING ingestor는 읽기 요청을 수신할 수 있다. 해시 조회를 수행할 때 distributor는 요청에 적절한 상태에 있는 ingester에 대해서만 토큰을 사용한다.

해시 조회를 수행하기 위해 distributor는 값이 스트림의 해시보다 크지만 가장 작은 적절한 토큰을 찾는다. 복제 계수(replication factor)가 1보다 크면 다른 ingester에 속하는 다음 후속 토큰(링에서 시계방향)도 결과에 포함된다.

이 해시 설정의 효과는 ingester가 소유한 각 토큰이 해시 범위를 담당한다는 것이다. 값이 0, 25, 50인 토큰이 3개 있는 경우 토큰 25를 소유한 ingester에게 해시 3이 제공된다. 토큰 25를 소유한 ingester는 1-25의 해시 범위를 담당한다. 

Quorum consistency (쿼럼 일관성)

모든 distributor가 동일한 해시 링에 대한 액세스를 공유하므로 쓰기 요청을 모든 distributor에게 보낼 수 있다.

일관된 쿼리 결과를 보장하기 위해 loki는 읽기 및 쓰기에 dynamo 스타일 쿼럼 일관성을 사용한다. 즉, distributor는 보내기를 시작한 클라이언트에 응답하기 전에 샘플을 보낼 ingester 중 1.5개의 긍정적인 응답을 기다린다.

Ingester (인제스터)

인제스터 서비스는 쓰기 경로의 장기 스토리지 백엔드 (DynamoDB, S3, Cassandre 등)에 로그 데이터를 쓰고 읽기 경로의 메모리 내 쿼리에 대한 로그 데이터를 반환하는 역할을 한다.

인제스터에는 해시 링에서 인제스터의 수명 주기를 관리하는 수명 주기 관리자가 포함되어 있다. 각 인제스터의 상태는 PENDING, JOINING, ACTIVE, LEAVING, UNHEALTHY이다. 

더 이상 사용되지 않음: WAL(미리 쓰기 로그)이 이 기능을 대체한다.

1. PENDING은 LEAVING인 다른 인제스터로부터 핸드오프를 기다리고 있을 때 인제스터의 상태이다. 

2. JOINING은 현재 토큰을 링에 삽입하고 자체 초기화 중일 때 ingester의 상태이다. 소유한 토큰에 대한 쓰기 요청을 받을 수 있다.

3. ACTIVE는 완전히 초기화되었을 때의 인제스터 상태이다. 소유한 토큰에 대한 쓰기 및 읽기 요청을 모두 수신할 수 있다.

4. LEAVING은 종료될 때 인제스터의 상태. 아직 메모리에 있는 데이터에 대한 읽기 요청을 수신할 수 있다.

5. UNHEALTHY는 Consul 하트비트에 실패했을 때 인제스터의 상태이다. UNHEALTHY는 주기적으로 링을 확인할 때 배포자가 설정한다.

수집기가 수신하는 각 로그 스트림은 메모리의 많은 청크 세트로 구성되고 구성 가능한 간격으로 백업 스토리지 백엔드로 플러시된다.

다음과 같은 경우 청크가 압축되고 읽기 전용으로 표시된다:

1. 현재 청크가 용량(구성 가능한 값)에 도달했다.

2. 현재 청크가 업데이트 되지 않고 너무 많은 시간이 지났다.

3. 플러쉬가 발생한다.

 

청크가 압축되어 읽기 전용으로 표시될 때마다 쓰기 가능한 청크가 그 자리를 차지한다. 

인제스터 프로세스가 충돌하거나 갑자기 종료되면 아직 플러시되지 않은 모든 데이터가 손실된다. loki는 일반적으로 이러한 위험을 완화하기 위해 각 로그의 여러 복제본(replicas) (보통 3개)을 복제하도록 구성된다.

persistent strorage provider에 플러시가 발생하면 청크는 테넌트, 레이블 및 콘텐츠를 기반으로 해싱됩니다. 즉, 동일한 데이터 복사본을 가진 여러 수집기가 동일한 데이터를 백업 저장소에 두 번 쓰지 않지만 복제본 중 하나에 쓰기가 실패한 경우 여러 개의 다른 청크 개체가 백업 저장소에 생성됩니다. 데이터 중복 제거 방법은 쿼리어를 참조하세요.

 

https://grafana.com/docs/loki/latest/fundamentals/architecture/components/

 

Components

Components Distributor The distributor service is responsible for handling incoming streams by clients. It’s the first stop in the write path for log data. Once the distributor receives a set of streams, each stream is validated for correctness and to en

grafana.com

 

용어 정리

rollout : 


WRITTEN BY
호두만듀
생활형 블로그 심심할 땐 끼적끼적 바쁠 때도 끼적끼적 자나 깨나 끼적끼적

,