LabHub
배우기 러닝패스 코스

쿠버네티스 운영 실무 · API 서버가 429 를 돌려준다 · 실습

오퍼레이터 하나가 클러스터 전체를 느리게 만들었다

LabHub 에서 이어서 보기

목표

기본 FlowSchema 와 PriorityLevelConfiguration 을 순서대로 읽고, 폭주하는 서비스 어카운트를 위한 격리 칸을 만들어 분류가 실제로 바뀌는 것을 응답 헤더로 증명한 뒤, 우선순위 값이 겹쳤을 때의 규칙과 exempt 남용을 막는 감시 스크립트, 그리고 좌석 수 지표까지 확인한다.

왜 중요한가

API 서버는 들어오는 모든 요청을 분류하고 격리한다. FlowSchema 가 분류표이고, 요청은 matchingPrecedence 가 작은 것부터 대조해 처음 맞는 하나로 결정된다. 그 스키마가 가리키는 PriorityLevelConfiguration 이 그 칸의 폭 — 동시에 몇 개를 실행할 수 있고 넘치면 줄을 세울지 바로 거절할지 — 를 정한다. 이 구조가 중요한 이유는 하나다. 폭주하는 클라이언트가 있을 때 누가 굶는지를 설계할 수 있기 때문이다. 분류표를 읽을 줄 모르면 429 가 쌓이는 날 할 수 있는 일이 재시작뿐이고, 그건 같은 폭주를 다시 맞겠다는 뜻이다.

단계

1. 클러스터가 기본으로 넣어 둔 FlowSchema(이 실습에서 만들 것들과 구분하기 위해 이름이 ops-zz-ops- 로 시작하지 않는 것으로 정의합니다)를 전부 /root/ops-apf/flowschemas.tsv 에 저장하세요 — <matchingPrecedence><이름><우선순위 등급 이름> 한 줄씩이고, 요청이 심사되는 순서대로 정렬합니다(숫자 정렬입니다).
2. 클러스터가 기본으로 넣어 둔 PriorityLevelConfiguration(이름이 ops- 로 시작하지 않는 것)을 전부 /root/ops-apf/levels.tsv 에 저장하세요 — <이름><type><nominalConcurrencyShares><limitResponse.type> 한 줄씩, 이름 오름차순입니다. Exempt 등급처럼 값이 없는 칸은 - 로 적으세요.
3. 네임스페이스 ops-apf 를 만들고 서비스 어카운트 셋을 만드세요 — widget-operator, plain-reader, bulk-writer. 그다음 /root/ops-apf/classify.sh 를 만드세요 — 인자로 받은 서비스 어카운트를 흉내 내어 요청 하나를 보내고 응답 헤더의 X-Kubernetes-Pf-Flowschema-Uid 로 걸린 FlowSchema 이름만 표준출력에 찍습니다. plain-reader 로 돌려 그 결과를 /root/ops-apf/baseline.tsv 에 한 줄로 저장하세요 — plain-reader<스키마 이름>.
4. /root/ops-apf/ops-noisy.yaml 에 PriorityLevelConfiguration ops-noisy 를 쓰세요 — type: Limited, nominalConcurrencyShares: 5, lendablePercent: 50, borrowingLimitPercent: 20, limitResponsetype: Queue 이고 queuingqueues: 16, handSize: 4, queueLengthLimit: 50 입니다. 적용하세요.
5. /root/ops-apf/ops-noisy-operator.yaml 에 FlowSchema ops-noisy-operator 를 쓰세요 — matchingPrecedence: 950, priorityLevelConfiguration.nameops-noisy, distinguisherMethod.typeByUser, 규칙은 subject 가 kind: ServiceAccountops-apf 네임스페이스의 widget-operator 이고 resourceRules 는 verbs·apiGroups·resources·namespaces 를 모두 * 로 둡니다. 적용하세요.
6. classify.shwidget-operatorplain-reader 로 각각 돌려 결과를 /root/ops-apf/classified.tsv 에 두 줄로 저장하세요 — <어카운트 이름><스키마 이름> 이고 어카운트 이름 오름차순입니다.
7. /root/ops-apf/ops-bulk-a.yaml/root/ops-apf/zz-ops-bulk-b.yaml 에 FlowSchema 두 개를 쓰세요. 둘 다 ops-apf 의 서비스 어카운트 bulk-writer 를 대상으로 하고 ops-noisy 를 가리키며 resourceRules 는 모두 * 입니다. ops-bulk-amatchingPrecedence: 960·distinguisherMethod.type: ByUser, zz-ops-bulk-bmatchingPrecedence: 940·distinguisherMethod.type: ByNamespace 입니다. 둘 다 적용한 뒤 classify.sh bulk-writer 의 결과를 /root/ops-apf/precedence.tsv 에 두 줄로 저장하세요 — ops-bulk-a960<win 또는 lose>, zz-ops-bulk-b940<win 또는 lose>. 그리고 만약 두 스키마의 값이 똑같이 960 이었다면 어느 쪽이 이겼을지 그 이름만 /root/ops-apf/tie.txt 에 한 줄로 쓰세요.
8. /root/ops-apf/exempt-allow.txtexempt 우선순위 등급을 가리켜도 되는 FlowSchema 이름을 한 줄씩 적으세요(지금 클러스터에 실제로 그런 스키마가 어떤 것들인지 먼저 확인하고, 그 이름들만 적습니다). 그리고 /root/ops-apf/exempt-guard.sh 를 만드세요 — exempt 를 가리키는 FlowSchema 를 모두 찾아 허용 목록에 있으면 OK <이름>, 없으면 VIOLATION <이름> 을 이름 순으로 표준출력에만 찍고, 위반이 하나라도 있으면 0 이 아닌 코드로 끝나야 합니다. 지금 상태에서 돌리면 위반이 없어야 합니다.
9. API 서버의 지표에서 apiserver_flowcontrol_nominal_limit_seats 를 읽어 /root/ops-apf/seats.tsv 에 저장하세요 — <우선순위 등급 이름><좌석 수> 한 줄씩, 이름 오름차순입니다. ops-noisy 가 그 안에 있어야 합니다.

참고

단계 9개

  1. 분류표를 우선순위 순으로 읽는다
  2. 각 칸의 폭을 읽는다
  3. 지금은 어느 칸으로 가는지 실측한다
  4. 폭주하는 오퍼레이터를 위한 칸을 만든다
  5. 그 칸으로 보내는 규칙을 쓴다
  6. 분류가 정말 바뀌었는지 헤더로 증명한다
  7. 같은 요청에 두 규칙이 걸릴 때
  8. exempt 를 가리키는 규칙을 감시한다
  9. 새 칸이 좌석을 실제로 받았는지 지표로 확인한다