eks API Server API Server API Server search API Server exclude true

Answer:
---
search:
  exclude: true
---

# 컨트롤 플레인 모니터링

## API Server
API Server를 살펴볼 때 그 기능 중 하나가 컨트롤 플레인의 과부하를 방지하기 위해 인바운드 요청을 조절하는 것임을 기억하는 것이 중요합니다. API Server 수준에서 병목 현상이 발생하는 것처럼 보일 수 있는 것은 실제로 더 심각한 문제로부터 이를 보호하는 것일 수도 있습니다. 시스템을 통해 이동하는 요청량 증가의 장단점을 고려해야 합니다. API Server 값을 늘려야 하는지 결정하기 위해 염두에 두어야 할 사항에 대한 작은 샘플링은 다음과 같습니다.

1. 시스템을 통해 이동하는 요청의 대기 시간은 얼마나 됩니까?
2. 지연 시간은 API Server 자체입니까, 아니면 etcd와 같은 "다운스트림"입니까?
3. API 서버 대기열 깊이가 이 지연 시간의 요인입니까?
4. API 우선 순위 및 공정성(APF) 대기열이 우리가 원하는 API 호출 패턴에 맞게 올바르게 설정되어 있습니까?

## 문제가 있는 곳은 어디입니까?
먼저 API 지연 시간 측정 지표를 사용하여 API Server가 요청을 처리하는 데 걸리는 시간을 파악할 수 있습니다. 아래 PromQL 및 Grafana 히트맵을 사용하여 이 데이터를 표시해 보겠습니다.

```
max(increase(apiserver_request_duration_seconds_bucket{subresource!="status",subresource!="token",subresource!="scale",subresource!="/healthz",subresource!="binding",subresource!="proxy",verb!="WATCH"}[$__rate_interval])) by (le)
```

!!! tip
    이 문서에 사용된 API 대시보드로 API 서버를 모니터링하는 방법에 대한 자세한 내용은 다음 [blog](https://aws.amazon.com/blogs/containers/troubleshooting-amazon-eks-api-servers-with-prometheus/)를 참조하세요.

![API 요청 지연 히트맵](../images/api-request-duration.png)

이러한 요청은 모두 1초 아래에 있습니다. 이는 컨트롤 플레인이 적시에 요청을 처리하고 있음을 나타내는 좋은 표시입니다. 하지만 그렇지 않다면 어떨까요?

위의 API 요청 기간에서 사용하는 형식은 히트맵입니다. 히트맵 형식의 좋은 점은 기본적으로 API의 제한 시간 값(60초)을 알려준다는 것입니다. 그러나 실제로 알아야 할 것은 시간 초과 임계값에 도달하기 전에 이 값이 어떤 임계값에 관심을 가져야 하는가입니다. 허용 가능한 임계값에 대한 대략적인 지침을 보려면 [여기](https://github.com/kubernetes/community/blob/master/sig-scalability/slos/slos.md#steady-state-slisslos)에서 찾을 수 있는 업스트림 쿠버네티스 SLO를 사용할 수 있습니다.

!!! tip
    이 명령문의 max 함수를 확인하세요. 여러 서버(기본적으로 EKS의 두 API Server)를 집계하는 지표를 사용할 때 해당 서버의 평균을 구하지 않는 것이 중요합니다.

### 비대칭 트래픽 패턴
한 API Server [pod]는 로드가 약하고 다른 하나는 과부하가 걸리면 어떻게 될까요?이 두 숫자의 평균을 구하면 무슨 일이 벌어졌는지 잘못 해석할 수 있습니다. 예를 들어, 여기에는 세 개의 API Server가 있지만 모든 로드는 이 API Server 중 하나에 있습니다. 일반적으로 etcd 및 API 서버와 같이 여러 서버가 있는 모든 것은 규모 및 성능 문제에 투자할 때 분리되어야 합니다.

![Total inflight requests](../images/inflight-requests.png)

API 우선순위 및 공정성(APF)으로 전환하면서 시스템의 총 요청 수는 API Server가 초과 구독되었는지 확인하는 하나의 요소일 뿐입니다. 이제 시스템에서 일련의 대기열을 사용하므로 대기열이 꽉 찼는지, 해당 대기열의 트래픽이 삭제되고 있는지 확인해야 합니다.

다음 쿼리를 사용하여 이러한 대기열을 살펴보겠습니다.

```
max without(instance)(apiserver_flowcontrol_request_concurrency_limit{})
```

!!! note
    API A&F 작동 방식에 대한 자세한 내용은 다음 [모범 사례 가이드](https://aws.github.io/aws-eks-best-practices/scalability/docs/control-plane/#api-priority-and-fairness)를 참조하세요.

여기에서는 클러스터에 기본적으로 제공되는 7개의 서로 다른 우선순위 그룹을 볼 수 있습니다.

![Shared concurrency](../images/shared-concurrency.png)

다음으로 특정 우선순위 수준이 포화 상태인지 파악하기 위해 해당 우선순위 그룹이 몇 퍼센트의 비율로 사용되고 있는지 확인하고자 합니다. 워크로드가 낮은 수준에서는 요청을 스로틀링하는 것이 바람직할 수 있지만 리더 선출 수준에서는 그렇지 않을 수 있습니다.

API 우선 순위 및 공정성(APF) 시스템에는 여러 가지 복잡한 옵션이 있으며, 이러한 옵션 중 일부는 의도하지 않은 결과를 초래할 수 있습니다. 워크로드에서 일반적으로 볼 수 있는 문제는 불필요한 대기 시간이 추가되기 시작하는 지점까지 대기열 깊이를 늘리는 것입니다. `apiserver_flowcontrol_current_inqueue_request` 지표를 사용하여 이 문제를 모니터링할 수 있습니다. `apiserver_flowcontrol_rejected_requests_total`을 사용하여 삭제를 확인할 수 있습니다. 버킷이 동시성을 초과하는 경우 이러한 지표는 0이 아닌 값이 됩니다.

![Requests in use](../images/requests-in-use.png)

대기열 깊이를 늘리면 API Server가 지연 시간의 중요한 원인이 될 수 있으므로 주의해서 수행해야 합니다. 생성된 대기열 수를 신중하게 결정하는 것이 좋습니다. 예를 들어 EKS 시스템의 공유 수는 600개입니다. 너무 많은 대기열을 생성하면 리더 선택 대기열이나 시스템 대기열과 같이 처리량이 필요한 중요한 대기열의 공유가 줄어들 수 있습니다. 추가 대기열을 너무 많이 생성하면 이러한 대기열의 크기를 올바르게 지정하기가 더 어려워질 수 있습니다.

APF에서 수행할 수 있는 간단하고 영향력 있는 변경에 초점을 맞추기 위해 활용도가 낮은 버킷에서 공유를 가져와 최대 사용량에 있는 버킷의 크기를 늘립니다. 이러한 버킷 간에 공유를 지능적으로 재분배함으로써 삭제 가능성을 줄일 수 있습니다.

자세한 내용은 EKS 모범 사례 가이드 [API 우선순위 및 공정성 설정](https://aws.github.io/aws-eks-best-practices/scalability/docs/control-plane/#api-priority-and-fairness)을 참조하세요.

### API vs. etcd 지연 시간
API Server의 메트릭/로그를 사용하여 API Server에 문제가 있는지, API Server의 업스트림/다운스트림 또는 이 둘의 조합에 문제가 있는지 판단하려면 어떻게 해야 합니까? 이를 더 잘 이해하기 위해 API Server와 etcd가 어떤 관련이 있는지, 그리고 잘못된 시스템을 해결하는 것이 얼마나 쉬운지 살펴보겠습니다.

아래 차트에서는 API Server의 지연 시간을 볼 수 있지만, etcd 수준에서 대부분의 지연 시간을 보여주는 그래프의 막대로 인해 이 지연 시간의 상당 부분이 etcd 서버와 연관되어 있음을 알 수 있습니다. etcd 대기 시간이 15초이고 동시에 API 서버 대기 시간이 20초인 경우 대기 시간의 대부분은 실제로 etcd 수준에 있습니다

전체 흐름을 살펴보면 API Server에만 집중하지 않고 etcd가 압박을 받고 있음을 나타내는 신호(예: slow apply counters 증가)를 찾는 것이 현명하다는 것을 알 수 있습니다.

!!! tip
    The dashboard in section can be found at https://github.com/RiskyAdventure/Troubleshooting-Dashboards/blob/main/api-troubleshooter.json

![ETCD duress](../images/etcd-duress.png)

### 컨트롤 플레인과 클라이언트 측 문제
이 차트에서는 해당 기간 동안 완료하는 데 가장 많은 시간이 걸린 API 호출을 찾고 있습니다. 이 경우 사용자 정의 리소스(CRD)가 05:40 시간 프레임 동안 가장 오래걸린 호출이 APPLY 함수라는 것을 볼 수 있습니다.

![Slowest requests](../images/slowest-requests.png)

이 데이터를 바탕으로 Ad-Hoc PromQL 또는 CloudWatch Insights 쿼리를 사용하여 해당 기간 동안 감사 로그에서 LIST 요청을 가져와서 어떤 애플리케이션인지 확인할 수 있습니다.

### CloudWatch로 소스 찾기
메트릭은 살펴보고자 하는 문제 영역을 찾고 문제의 기간과 검색 매개변수를 모두 좁히는 데 가장 잘 사용됩니다. 이 데이터가 확보되면 더 자세한 시간과 오류에 대한 로그로 전환하려고 합니다. 이를 위해 [CloudWatch Logs Insights](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/AnalyzingLogData.html)를 사용하여 로그를 메트릭으로 전환합니다.

예를 들어, 위의 문제를 조사하기 위해 다음 CloudWatch Logs Insights 쿼리를 사용하여 사용자 에이전트 및 requestURI를 가져와서 어떤 애플리케이션이 이 지연을 일으키는지 정확히 파악할 수 있습니다.

!!! tip
    Watch에서 정상적인 List/Resync 동작을 가져오지 않으려면 적절한 개수를 사용해야 합니다.

```
fields *@timestamp*, *@message*
| filter *@logStream* like "kube-apiserver-audit"
| filter ispresent(requestURI)
| filter verb = "list"
| parse requestReceivedTimestamp /\d+-\d+-(?<StartDay>\d+)T(?<StartHour>\d+):(?<StartMinute>\d+):(?<StartSec>\d+).(?<StartMsec>\d+)Z/
| parse stageTimestamp /\d+-\d+-(?<EndDay>\d+)T(?<EndHour>\d+):(?<EndMinute>\d+):(?<EndSec>\d+).(?<EndMsec>\d+)Z/
| fields (StartHour * 3600 + StartMinute * 60 + StartSec + StartMsec / 1000000) as StartTime, (EndHour * 3600 + EndMinute * 60 + EndSec + EndMsec / 1000000) as EndTime, (EndTime - StartTime) as DeltaTime
| stats avg(DeltaTime) as AverageDeltaTime, count(*) as CountTime by requestURI, userAgent
| filter CountTime >=50
| sort AverageDeltaTime desc
```

이 쿼리를 사용하여 대기 시간이 긴 list 작업을 대량으로 실행하는 두 개의 서로 다른 에이전트(Splunk 및 CloudWatch Agent)를 발견했습니다. 데이터를 바탕으로 이 컨트롤러를 제거, 업데이트하거나 다른 프로젝트로 교체하기로 결정할 수 있습니다.

![Query results](../images/query-results.png)

!!! tip
    이 주제에 대한 자세한 내용은 다음 [블로그](https://aws.amazon.com/blogs/containers/troubleshooting-amazon-eks-api-servers-with-prometheus/)를 참조하세요.

## Scheduler
EKS 컨트롤 플레인 인스턴스는 별도의 AWS 계정에서 실행되므로 측정 지표에 대한 해당 구성 요소를 수집할 수 없습니다(API Server는 예외임). 그러나 이러한 구성 요소에 대한 감사 로그에 액세스할 수 있으므로 해당 로그를 지표로 변환하여 확장 시 병목 현상을 일으키는 하위 시스템이 있는지 확인할 수 있습니다. CloudWatch Logs Insights를 사용하여 스케줄러 대기열에 예약되지 않은 Pod가 몇 개 있는지 확인해 보겠습니다.

### 스케줄러 로그에서 예약되지 않은 파드
자체 관리형 쿠버네티스(예: Kops)에서 직접 스케줄러 지표를 스크랩할 수 있는 액세스 권한이 있는 경우 다음 PromQL을 사용하여 스케줄러 백로그를 이해합니다.

```
max without(instance)(scheduler_pending_pods)
```

EKS에서는 위 지표에 액세스할 수 없으므로 아래 CloudWatch Logs Insights 쿼리를 사용하여 특정 기간 동안 예약을 취소할 수 없었던 파드 수를 확인하여 백로그를 확인할 것입니다. 그러면 피크 타임의 메시지를 더 자세히 분석하여 병목 현상의 특성을 이해할 수 있습니다. 노드가 충분히 빠르게 교체되지 않거나 스케줄러 자체의 rate limiter를 예로 들 수 있습니다.

```
fields timestamp, pod, err, *@message*
| filter *@logStream* like "scheduler"
| filter *@message* like "Unable to schedule pod"
| parse *@message*  /^.(?<date>\d{4})\s+(?<timestamp>\d+:\d+:\d+\.\d+)\s+\S*\s+\S+\]\s\"(.*?)\"\s+pod=(?<pod>\"(.*?)\")\s+err=(?<err>\"(.*?)\")/
| count(*) as count by pod, err
| sort count desc
```

여기서는 스토리지 PVC를 사용할 수 없어 파드가 배포되지 않았다는 스케줄러의 오류를 볼 수 있습니다.

![CloudWatch Logs query](../images/cwl-query.png)

!!! note
    이 기능을 활성화하려면 컨트롤 플레인에서 감사 로깅을 켜야 합니다. 시간이 지남에 따라 불필요하게 비용이 증가하지 않도록 로그 보존을 제한하는 것도 가장 좋은 방법입니다. 다음은 EKSCTL 도구를 사용하여 모든 로깅 기능을 켜는 예제입니다.

```yaml
cloudWatch:
  clusterLogging:
    enableTypes: ["*"]
    logRetentionInDays: 10
```

## Kube Controller Manager
다른 모든 컨트롤러와 마찬가지로 Kube Controller Manager는 한 번에 수행할 수 있는 작업 수에 제한이 있습니다. 이러한 파라미터를 설정할 수 있는 KOPS 구성을 살펴보면서 이러한 플래그 중 일부가 무엇인지 살펴보겠습니다.

```yaml
  kubeControllerManager:
    concurrentEndpointSyncs: 5
    concurrentReplicasetSyncs: 5
    concurrentNamespaceSyncs: 10
    concurrentServiceaccountTokenSyncs: 5
    concurrentServiceSyncs: 5
    concurrentResourceQuotaSyncs: 5
    concurrentGcSyncs: 20
    kubeAPIBurst: 20
    kubeAPIQPS: "30"
```

이러한 컨트롤러에는 클러스터에서 변동이 심할 때 대기열이 꽉 차게 됩니다. 이 경우 replicaset controller의 대기열에 대규모 백로그가 있는 것을 확인할 수 있습니다.

![Queues](../images/queues.png)

이러한 상황을 해결하는 방법에는 두 가지가 있습니다. 자체 관리를 실행하는 경우 동시 고루틴을 늘릴 수 있지만 이는 KCM에서 더 많은 데이터를 처리하여 etcd에 영향을 미칠 수 있습니다. 다른 옵션은 배포에서 `.spec.revisionHistoryLimit`을 사용하여 replicaset 개체 수를 줄이고 롤백할 수 있는 replicaset 개체 수를 줄여 해당 컨트롤러에 대한 부담을 줄이는 것입니다.

```yaml
spec:
  revisionHistoryLimit: 2
```

다른 쿠버네티스 기능을 조정하거나 해제하여 이탈률이 높은 시스템의 압력을 줄일 수 있습니다. 예를 들어, 파드의 애플리케이션이 k8s API와 직접 통신할 필요가 없는 경우 해당 파드에 적용된 시크릿을 끄면 ServiceAccountTokenSync의 부하를 줄일 수 있습니다. 가능하면 이런 문제를 해결할 수 있는 더 바람직한 방법입니다.

```yaml
kind: Pod
spec:
  automountServiceAccountToken: false
```

지표에 액세스할 수 없는 시스템에서는 로그를 다시 검토하여 경합을 감지할 수 있습니다. 컨트롤러당 또는 집계 수준에서 처리되는 요청의 수를 확인하려면 다음과 같은 CloudWatch Logs Insights 쿼리를 사용하면 됩니다.

### Total Volume Processed by the KCM

```
# Query to count API qps coming from kube-controller-manager, split by controller type.
# If you're seeing values close to 20/sec for any particular controller, it's most likely seeing client-side API throttling.
fields @timestamp, @logStream, @message
| filter @logStream like /kube-apiserver-audit/
| filter userAgent like /kube-controller-manager/
# Exclude lease-related calls (not counted under kcm qps)
| filter requestURI not like "apis/coordination.k8s.io/v1/namespaces/kube-system/leases/kube-controller-manager"
# Exclude API discovery calls (not counted under kcm qps)
| filter requestURI not like "?timeout=32s"
# Exclude watch calls (not counted under kcm qps)
| filter verb != "watch"
# If you want to get counts of API calls coming from a specific controller, uncomment the appropriate line below:
# | filter user.username like "system:serviceaccount:kube-system:job-controller"
# | filter user.username like "system:serviceaccount:kube-system:cronjob-controller"
# | filter user.username like "system:serviceaccount:kube-system:deployment-controller"
# | filter user.username like "system:serviceaccount:kube-system:replicaset-controller"
# | filter user.username like "system:serviceaccount:kube-system:horizontal-pod-autoscaler"
# | filter user.username like "system:serviceaccount:kube-system:persistent-volume-binder"
# | filter user.username like "system:serviceaccount:kube-system:endpointslice-controller"
# | filter user.username like "system:serviceaccount:kube-system:endpoint-controller"
# | filter user.username like "system:serviceaccount:kube-system:generic-garbage-controller"
| stats count(*) as count by user.username
| sort count desc
```

여기서 중요한 점은 확장성 문제를 조사할 때 자세한 문제 해결 단계로 이동하기 전에 경로의 모든 단계(API, 스케줄러, KCM 등)를 살펴보는 것입니다. 프로덕션에서는 시스템이 최고의 성능으로 작동할 수 있도록 쿠버네티스의 두 부분 이상을 조정해야 하는 경우가 종종 있습니다. 훨씬 더 큰 병목 현상의 단순한 증상(예: 노드 시간 초과)을 실수로 해결하는 것은 쉽습니다.

## ETCD
etcd는 메모리 매핑 파일을 사용하여 키 값 쌍을 효율적으로 저장합니다. 일반적으로 2, 4, 8GB 제한으로 설정된 사용 가능한 메모리 공간의 크기를 설정하는 보호 메커니즘이 있습니다. 데이터베이스의 개체 수가 적다는 것은 개체가 업데이트되고 이전 버전을 정리해야 할 때 etcd에서 수행해야 하는 정리 작업이 줄어든다는 것을 의미합니다. 객체의 이전 버전을 정리하는 이러한 프로세스를 압축이라고 합니다. 여러 번의 압축 작업 후에는 특정 임계값 이상 또는 고정된 시간 일정에 따라 발생하는 조각 모음(defragging)이라는 사용 가능한 공간을 복구하는 후속 프로세스가 있습니다.

쿠버네티스의 개체 수를 제한하여 압축 및 조각 모음 프로세스의 영향을 줄이기 위해 수행할 수 있는 몇 가지 사용자 관련 항목이 있습니다. 예를 들어 Helm은 높은 `revisionHistoryLimit`을 유지합니다. 이렇게 하면 ReplicaSet와 같은 이전 개체가 시스템에 유지되어 롤백을 수행할 수 있습니다. 기록 제한을 2로 설정하면 개체(예: ReplicaSets) 수를 10에서 2로 줄일 수 있으며 결과적으로 시스템에 대한 로드가 줄어듭니다.

```yaml
apiVersion: apps/v1
kind: Deployment
spec:
  revisionHistoryLimit: 2
```

모니터링 관점에서 시스템 지연 시간 급증이 시간 단위로 구분된 설정된 패턴으로 발생하는 경우 이 조각 모음 프로세스가 원인인지 확인하는 것이 도움이 될 수 있습니다. CloudWatch Logs를 사용하면 이를 확인할 수 있습니다.

조각 모음의 시작/종료 시간을 보려면 다음 쿼리를 사용하십시오.

```
fields *@timestamp*, *@message*
| filter *@logStream* like /etcd-manager/
| filter *@message* like /defraging|defraged/
| sort *@timestamp* asc
```

![Defrag query](../images/defrag.png)

search    exclude  true                          API Server API Server                                                                          API Server                                                                                API Server                                                        1                                   2         API Server            etcd                 3  API                            4  API             APF               API                                                   API                   API Server                                    PromQL   Grafana                                  max increase apiserver request duration seconds bucket subresource   status  subresource   token  subresource   scale  subresource    healthz  subresource   binding  subresource   proxy  verb   WATCH      rate interval    by  le           tip               API       API                               blog  https   aws amazon com blogs containers troubleshooting amazon eks api servers with prometheus              API               images api request duration png              1                                                                              API                                              API          60                                                                                https   github com kubernetes community blob master sig scalability slos slos md steady state slisslos                       SLO                   tip            max                        EKS    API Server                                                                API Server  pod                                                                                API Server               API Server                   etcd   API                                                        Total inflight requests     images inflight requests png   API            APF                       API Server                                                                                max without instance  apiserver flowcontrol request concurrency limit             note     API A F                                  https   aws github io aws eks best practices scalability docs control plane  api priority and fairness                                  7                               Shared concurrency     images shared concurrency png                                                                                API             APF                                                                                apiserver flowcontrol current inqueue request                                apiserver flowcontrol rejected requests total                                                 0                Requests in use     images requests in use png               API Server                                                                             EKS            600                                                                                APF                                                                                EKS            API                https   aws github io aws eks best practices scalability docs control plane  api priority and fairness               API vs  etcd       API Server               API Server           API Server                                                                  API Server  etcd                                                              API Server                  etcd                                                   etcd                        etcd        15        API           20                      etcd                       API Server           etcd                        slow apply counters                                    tip     The dashboard in section can be found at https   github com RiskyAdventure Troubleshooting Dashboards blob main api troubleshooter json    ETCD duress     images etcd duress png                                                                API                              CRD   05 40                       APPLY                      Slowest requests     images slowest requests png               Ad Hoc PromQL    CloudWatch Insights                           LIST                                       CloudWatch                                                                                CloudWatch Logs Insights  https   docs aws amazon com AmazonCloudWatch latest logs AnalyzingLogData html                                                   CloudWatch Logs Insights                     requestURI                                                   tip     Watch        List Resync                                      fields   timestamp     message    filter   logStream  like  kube apiserver audit    filter ispresent requestURI    filter verb    list    parse requestReceivedTimestamp   d   d     StartDay  d  T   StartHour  d      StartMinute  d      StartSec  d      StartMsec  d  Z    parse stageTimestamp   d   d     EndDay  d  T   EndHour  d      EndMinute  d      EndSec  d      EndMsec  d  Z    fields  StartHour   3600   StartMinute   60   StartSec   StartMsec   1000000  as StartTime   EndHour   3600   EndMinute   60   EndSec   EndMsec   1000000  as EndTime   EndTime   StartTime  as DeltaTime   stats avg DeltaTime  as AverageDeltaTime  count    as CountTime by requestURI  userAgent   filter CountTime   50   sort AverageDeltaTime desc                          list                               Splunk   CloudWatch Agent                                                                       Query results     images query results png       tip                               https   aws amazon com blogs containers troubleshooting amazon eks api servers with prometheus               Scheduler EKS                   AWS                                           API Server                                                                                CloudWatch Logs Insights                         Pod                                                               Kops                                           PromQL                             max without instance  scheduler pending pods       EKS                         CloudWatch Logs Insights                                                                                rate limiter                     fields timestamp  pod  err    message    filter   logStream  like  scheduler    filter   message  like  Unable to schedule pod    parse   message         date  d 4   s    timestamp  d   d   d    d   s  S  s  S    s          s pod    pod            s err    err               count    as count by pod  err   sort count desc                PVC                                                 CloudWatch Logs query     images cwl query png       note                                                                                EKSCTL                                    yaml cloudWatch    clusterLogging      enableTypes            logRetentionInDays  10         Kube Controller Manager                   Kube Controller Manager                                                   KOPS                                           yaml   kubeControllerManager      concurrentEndpointSyncs  5     concurrentReplicasetSyncs  5     concurrentNamespaceSyncs  10     concurrentServiceaccountTokenSyncs  5     concurrentServiceSyncs  5     concurrentResourceQuotaSyncs  5     concurrentGcSyncs  20     kubeAPIBurst  20     kubeAPIQPS   30                                                      replicaset controller                                      Queues     images queues png                                                                    KCM                  etcd                               spec revisionHistoryLimit        replicaset                    replicaset                                        yaml spec    revisionHistoryLimit  2                                                                             k8s API                                      ServiceAccountTokenSync                                                        yaml kind  Pod spec    automountServiceAccountToken  false                                                                                CloudWatch Logs Insights                     Total Volume Processed by the KCM        Query to count API qps coming from kube controller manager  split by controller type    If you re seeing values close to 20 sec for any particular controller  it s most likely seeing client side API throttling  fields  timestamp   logStream   message   filter  logStream like  kube apiserver audit    filter userAgent like  kube controller manager    Exclude lease related calls  not counted under kcm qps    filter requestURI not like  apis coordination k8s io v1 namespaces kube system leases kube controller manager    Exclude API discovery calls  not counted under kcm qps    filter requestURI not like   timeout 32s    Exclude watch calls  not counted under kcm qps    filter verb     watch    If you want to get counts of API calls coming from a specific controller  uncomment the appropriate line below      filter user username like  system serviceaccount kube system job controller      filter user username like  system serviceaccount kube system cronjob controller      filter user username like  system serviceaccount kube system deployment controller      filter user username like  system serviceaccount kube system replicaset controller      filter user username like  system serviceaccount kube system horizontal pod autoscaler      filter user username like  system serviceaccount kube system persistent volume binder      filter user username like  system serviceaccount kube system endpointslice controller      filter user username like  system serviceaccount kube system endpoint controller      filter user username like  system serviceaccount kube system generic garbage controller    stats count    as count by user username   sort count desc                                                               API        KCM                                                                                ETCD  etcd                                            2  4  8GB                                                                                etcd                                                                                defragging                                                                                Helm      revisionHistoryLimit                 ReplicaSet                                             2             ReplicaSets     10   2                                        yaml apiVersion  apps v1 kind  Deployment spec    revisionHistoryLimit  2                                                                                CloudWatch Logs                                                                fields   timestamp     message    filter   logStream  like  etcd manager    filter   message  like  defraging defraged    sort   timestamp  asc        Defrag query     images defrag png


eks exclude true API Server Controller Manager Scheduler search

Answer:
---
search:
  exclude: true
---

# 쿠버네티스 컨트롤 플레인

쿠버네티스 컨트롤 플레인은 쿠버네티스 API Server, 쿠버네티스 Controller Manager, Scheduler 및 쿠버네티스가 작동하는 데 필요한 기타 구성 요소로 구성됩니다. 이러한 구성 요소의 확장성 제한은 클러스터에서 실행 중인 항목에 따라 다르지만 확장에 가장 큰 영향을 미치는 영역에는 쿠버네티스 버전, 사용률 및 개별 노드 확장이 포함됩니다.

## EKS 1.24 이상을 사용하세요

EKS 1.24에는 여러 가지 변경 사항이 도입되었으며 컨테이너 런타임을 docker 대신 [containerd](https://containerd.io/)로 전환했습니다. Containerd는 쿠버네티스의 요구 사항에 긴밀하게 맞춰 컨테이너 런타임 기능을 제한하여 개별 노드 성능을 높여 클러스터 확장을 돕습니다. Containerd는 지원되는 모든 EKS 버전에서 사용할 수 있으며, 1.24 이전 버전에서 Containerd로 전환하려면 [`--container-runtime` bootstrap flag](https://docs.aws.amazon.com/eks/latest/userguide/eks-optimized-ami.html#containerd-bootstrap)를 사용하세요.

## 워크로드 및 노드 버스팅 제한

!!! Attention
    컨트롤 플레인에서 API 한도에 도달하지 않으려면 클러스터 크기를 한 번에 두 자릿수 비율로 늘리는 급격한 확장을 제한해야 합니다(예: 한 번에 1000개 노드에서 1100개 노드로 또는 4000개에서 4500개 파드로).

EKS 컨트롤 플레인은 클러스터가 성장함에 따라 자동으로 확장되지만 확장 속도에는 제한이 있습니다. EKS 클러스터를 처음 생성할 때 컨트롤 플레인은 즉시 수백 개의 노드 또는 수천 개의 파드로 확장될 수 없습니다. EKS의 스케일링 개선 방법에 대해 자세히 알아보려면 [이 블로그 게시물](https://aws.amazon.com/blogs/containers/amazon-eks-control-plane-auto-scaling-enhancements-improve-speed-by-4x/)을 참조하세요.

대규모 애플리케이션을 확장하려면 인프라가 완벽하게 준비되도록 조정해야 합니다(예: 로드 밸런서 워밍). 확장 속도를 제어하려면 애플리케이션에 적합한 측정 지표를 기반으로 확장하고 있는지 확인합니다. CPU 및 메모리 확장은 애플리케이션 제약 조건을 정확하게 예측하지 못할 수 있으며 쿠버네티스 HPA(Horizontal Pod Autoscaler)에서 사용자 지정 지표(예: 초당 요청)를 사용하는 것이 더 나은 확장 옵션일 수 있습니다.

사용자 정의 지표를 사용하려면 [쿠버네티스 문서](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/#autoscaling-on-multiple-metrics-and-custom-metrics)의 예를 참조하세요. 고급 확장이 필요하거나 외부 소스(예: AWS SQS 대기열)를 기반으로 확장해야 하는 경우 이벤트 기반 워크로드 확장을 위해 [KEDA](https://keda.sh)를 사용하세요.

## 노드와 파드를 안전하게 축소

### 장기 실행 인스턴스 교체

정기적으로 노드를 교체하면 구성 드리프트와 가동 시간이 연장된 후에만 발생하는 문제(예: 느린 메모리 누수)를 방지하여 클러스터를 건강한 상태로 유지할 수 있습니다. 자동 교체는 노드 업그레이드 및 보안 패치에 대한 좋은 프로세스와 사례를 제공합니다. 클러스터의 모든 노드가 정기적으로 교체되면 지속적인 유지 관리를 위해 별도의 프로세스를 유지하는 데 필요한 노력이 줄어듭니다.

Karpenter의 [Time To Live (TTL)](https://aws.github.io/aws-eks-best-practices/karpenter/#use-timers-ttl-to-automatically-delete-nodes-from-the-cluster) 설정을 통해 지정된 시간 동안 인스턴스가 실행된 후 인스턴스를 교체할 수 있습니다. 자체 관리형 노드 그룹은 `max-instance-lifetime` 설정을 사용하여 노드를 자동으로 교체할 수 있습니다. 관리형 노드 그룹에는 현재 이 기능이 없지만 [여기 GitHub에서](https://github.com/aws/containers-roadmap/issues/1190) 요청을 확인할 수 있습니다.

### 활용도가 낮은 노드 제거

[`--scale-down-utilization-threshold`](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/FAQ.md#how-does-scale-down-work)를 통해 쿠버네티스 Cluster Autoscaler의 축소 임계값을 사용하여 실행 중인 워크로드가 없을 때 노드를 제거할 수 있습니다. 또는 Karpenter에서 `ttlSecondsAfterEmpty` 프로비저너 설정을 활용할 수 있습니다.

### Pod Distruption Budgets 및 안전한 노드 셧다운 사용

쿠버네티스 클러스터에서 파드와 노드를 제거하려면 컨트롤러가 여러 리소스(예: EndpointSlices)를 업데이트해야 합니다. 이 작업을 자주 또는 너무 빠르게 수행하면 변경 사항이 컨트롤러에 전파되면서 API Server 쓰로틀링 및 애플리케이션 중단이 발생할 수 있습니다. [Pod Distruption Budgets](https://kubernetes.io/docs/concepts/workloads/pods/disruptions/)은 클러스터에서 노드가 제거되거나 스케줄이 조정될 때 변동 속도를 늦추어 워크로드 가용성을 보호하는 모범 사례입니다.

## Kubectl 실행 시 클라이언트측 캐시 사용

kubectl 명령을 비효율적으로 사용하면 쿠버네티스 API Server에 추가 로드가 발생될 수 있습니다. kubectl을 반복적으로(예: for 루프에서) 사용하는 스크립트나 자동화를 실행하거나 로컬 캐시 없이 명령을 실행하는 것을 피해야 합니다.

`kubectl`에는 필요한 API 호출 양을 줄이기 위해 클러스터에서 검색 정보를 캐시하는 클라이언트 측 캐시가 있습니다. 캐시는 기본적으로 활성화되어 있으며 10분마다 새로 고쳐집니다.

컨테이너에서 또는 클라이언트 측 캐시 없이 kubectl을 실행하는 경우 API 쓰로틀링 문제가 발생할 수 있습니다. 불필요한 API 호출을 피하기 위해 `--cache-dir`을 마운트하여 클러스터 캐시를 유지하는 것이 좋습니다.

## kubectl Compression 비활성화

kubeconfig 파일에서 kubectl compression을 비활성화하면 API 및 클라이언트 CPU 사용량을 줄일 수 있습니다. 기본적으로 서버는 클라이언트로 전송된 데이터를 압축하여 네트워크 대역폭을 최적화합니다. 이렇게 하면 요청마다 클라이언트와 서버에 CPU 부하가 가중되며, 대역폭이 충분하다면 압축을 비활성화하면 오버헤드와 지연 시간을 줄일 수 있습니다. 압축을 비활성화하려면 kubeconfig 파일에서 `--disable-compression=true` 플래그를 사용하거나 `disable-compression: true`로 설정하면 됩니다.

```
apiVersion: v1
clusters:
- cluster:
    server: serverURL
    disable-compression: true
  name: cluster
```

## Cluster Autoscaler 샤딩

[쿠버네티스 Cluster Autoscaler는 테스트를 거쳤습니다](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/proposals/scalability_tests.md). 최대 1,000개 노드까지 확장할 수 있습니다. 1000개 이상의 노드가 있는 대규모 클러스터에서는 Cluster AutoScaler를 여러 인스턴스에 샤드 모드로 실행하는 것이 좋습니다. 각 클러스터 오토스케일러 인스턴스는 노드 그룹 세트를 확장하도록 구성되어 있습니다. 다음 예는 각 4개의 노드 그룹에 구성된 2개의 클러스터 오토 스케일링 구성을 보여줍니다.

ClusterAutoscaler-1

```
autoscalingGroups:
- name: eks-core-node-grp-20220823190924690000000011-80c1660e-030d-476d-cb0d-d04d585a8fcb
  maxSize: 50
  minSize: 2
- name: eks-data_m1-20220824130553925600000011-5ec167fa-ca93-8ca4-53a5-003e1ed8d306
  maxSize: 450
  minSize: 2
- name: eks-data_m2-20220824130733258600000015-aac167fb-8bf7-429d-d032-e195af4e25f5
  maxSize: 450
  minSize: 2
- name: eks-data_m3-20220824130553914900000003-18c167fa-ca7f-23c9-0fea-f9edefbda002
  maxSize: 450
  minSize: 2
```

ClusterAutoscaler-2

```
autoscalingGroups:
- name: eks-data_m4-2022082413055392550000000f-5ec167fa-ca86-6b83-ae9d-1e07ade3e7c4
  maxSize: 450
  minSize: 2
- name: eks-data_m5-20220824130744542100000017-02c167fb-a1f7-3d9e-a583-43b4975c050c
  maxSize: 450
  minSize: 2
- name: eks-data_m6-2022082413055392430000000d-9cc167fa-ca94-132a-04ad-e43166cef41f
  maxSize: 450
  minSize: 2
- name: eks-data_m7-20220824130553921000000009-96c167fa-ca91-d767-0427-91c879ddf5af
  maxSize: 450
  minSize: 2
```

## API Priority and Fairness

![](../images/APF.jpg)

### 개요

<iframe width="560" height="315" src="https://www.youtube.com/embed/YnPPHBawhE0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

요청이 증가하는 기간 동안 과부하가 발생하지 않도록 보호하기 위해 API 서버는 특정 시간에 처리할 수 있는 진행 중인 요청 수를 제한합니다. 이 제한을 초과하면 API 서버는 요청을 거부하기 시작하고 "Too many requests"에 대한 429 HTTP 응답 코드를 클라이언트에 반환합니다. 서버가 요청을 삭제하고 클라이언트가 나중에 다시 시도하도록 하는 것이 요청 수에 대한 서버 측 제한을 두지 않고 컨트롤 플레인에 과부하를 주어 성능이 저하되거나 가용성이 저하될 수 있는 것보다 더 좋습니다.

이러한 진행 중인 요청이 다양한 요청 유형으로 나누어지는 방식을 구성하기 위해 쿠버네티스에서 사용하는 메커니즘을 [API Priority and Fairness](https://kubernetes.io/docs/concepts/cluster-administration/flow-control/)이라고 합니다. API 서버는 `--max-requests-inflight` 및 `--max-mutating-requests-inflight` 플래그로 지정된 값을 합산하여 허용할 수 있는 총 진행 중인 요청 수를 구성합니다. EKS는 이러한 플래그에 대해 기본값인 400개 및 200개 요청을 사용하므로 주어진 시간에 총 600개의 요청을 전달할 수 있습니다. APF는 이러한 600개의 요청을 다양한 요청 유형으로 나누는 방법을 지정합니다. EKS 컨트롤 플레인은 각 클러스터에 최소 2개의 API 서버가 등록되어 있어 가용성이 높습니다. 이렇게 하면 클러스터 전체의 총 진행 중인 요청 수가 1200개로 늘어납니다.

PriorityLevelConfigurations 및 FlowSchemas라는 두 종류의 쿠버네티스 객체는 총 요청 수가 다양한 요청 유형 간에 분할되는 방식을 구성합니다. 이러한 객체는 API 서버에 의해 자동으로 유지 관리되며 EKS는 지정된 쿠버네티스 마이너 버전에 대해 이러한 객체의 기본 구성을 사용합니다. PriorityLevelConfigurations는 허용된 총 요청 수의 일부를 나타냅니다. 예를 들어 워크로드가 높은 PriorityLevelConfiguration에는 총 600개의 요청 중 98개가 할당됩니다. 모든 PriorityLevelConfigurations에 할당된 요청의 합계는 600입니다(또는 특정 수준이 요청의 일부만 허용된 경우 API Server가 반올림하므로 600보다 약간 높음). 클러스터의 PriorityLevelConfigurations와 각각에 할당된 요청 수를 확인하려면 다음 명령을 실행할 수 있습니다. EKS 1.24의 기본값은 다음과 같습니다.

```
$ kubectl get --raw /metrics | grep apiserver_flowcontrol_request_concurrency_limit
apiserver_flowcontrol_request_concurrency_limit{priority_level="catch-all"} 13
apiserver_flowcontrol_request_concurrency_limit{priority_level="global-default"} 49
apiserver_flowcontrol_request_concurrency_limit{priority_level="leader-election"} 25
apiserver_flowcontrol_request_concurrency_limit{priority_level="node-high"} 98
apiserver_flowcontrol_request_concurrency_limit{priority_level="system"} 74
apiserver_flowcontrol_request_concurrency_limit{priority_level="workload-high"} 98
apiserver_flowcontrol_request_concurrency_limit{priority_level="workload-low"} 245
```

두 번째 유형의 객체는 FlowSchemas입니다. 특정 속성 세트가 포함된 API 서버 요청은 동일한 FlowSchema로 분류됩니다. 이러한 속성에는 인증된 사용자나 API Group, 네임스페이스 또는 리소스와 같은 요청의 속성이 포함됩니다. FlowSchema는 또한 이 유형의 요청이 매핑되어야 하는 PriorityLevelConfiguration을 지정합니다. 두 개체는 함께 "이 유형의 요청이 이 inflight 요청 비율에 포함되기를 원합니다."라고 말합니다. 요청이 API Server에 도달하면 모든 필수 속성과 일치하는 FlowSchemas를 찾을 때까지 각 FlowSchemas를 확인합니다. 여러 FlowSchemas가 요청과 일치하는 경우 API Server는 개체의 속성으로 지정된 일치 우선 순위가 가장 작은 FlowSchema를 선택합니다.

FlowSchemas와 PriorityLevelConfigurations의 매핑은 다음 명령을 사용하여 볼 수 있습니다.

```
$ kubectl get flowschemas
NAME                           PRIORITYLEVEL     MATCHINGPRECEDENCE   DISTINGUISHERMETHOD   AGE     MISSINGPL
exempt                         exempt            1                    <none>                7h19m   False
eks-exempt                     exempt            2                    <none>                7h19m   False
probes                         exempt            2                    <none>                7h19m   False
system-leader-election         leader-election   100                  ByUser                7h19m   False
endpoint-controller            workload-high     150                  ByUser                7h19m   False
workload-leader-election       leader-election   200                  ByUser                7h19m   False
system-node-high               node-high         400                  ByUser                7h19m   False
system-nodes                   system            500                  ByUser                7h19m   False
kube-controller-manager        workload-high     800                  ByNamespace           7h19m   False
kube-scheduler                 workload-high     800                  ByNamespace           7h19m   False
kube-system-service-accounts   workload-high     900                  ByNamespace           7h19m   False
eks-workload-high              workload-high     1000                 ByUser                7h14m   False
service-accounts               workload-low      9000                 ByUser                7h19m   False
global-default                 global-default    9900                 ByUser                7h19m   False
catch-all                      catch-all         10000                ByUser                7h19m   False
```

PriorityLevelConfigurations에는 Queue, Reject 또는 Exempt 유형이 있을 수 있습니다. Queue 및 Reject 유형의 경우 해당 우선순위 수준에 대한 최대 진행 중인 요청 수에 제한이 적용되지만 해당 제한에 도달하면 동작이 달라집니다. 예를 들어 워크로드가 높은 PriorityLevelConfiguration은 Queue 유형을 사용하며 컨트롤러 매니저, 엔드포인트 컨트롤러, 스케줄러 및 kube-system 네임스페이스에서 실행되는 파드에서 사용할 수 있는 요청이 98개 있습니다. Queue 유형이 사용되므로 API Server는 요청을 메모리에 유지하려고 시도하며 이러한 요청이 시간 초과되기 전에 진행 중인 요청 수가 98개 미만으로 떨어지기를 희망합니다. 특정 요청이 대기열에서 시간 초과되거나 너무 많은 요청이 이미 대기열에 있는 경우 API Server는 요청을 삭제하고 클라이언트에 429를 반환할 수밖에 없습니다. 대기열에 있으면 요청이 429를 수신하지 못할 수 있지만 요청의 종단 간 지연 시간이 늘어나는 단점이 있습니다.

이제 Reject 유형을 사용하여 포괄적인 PriorityLevelConfiguration에 매핑되는 포괄적인 FlowSchema를 살펴보겠습니다. 클라이언트가 13개의 진행 중인 요청 제한에 도달하면 API Server는 대기열을 실행하지 않고 429 응답 코드를 사용하여 요청을 즉시 삭제합니다. 마지막으로 Exempt 유형을 사용하여 PriorityLevelConfiguration에 매핑하는 요청은 429를 수신하지 않으며 항상 즉시 전달됩니다. 이는 healthz 요청이나 system:masters 그룹에서 오는 요청과 같은 우선순위가 높은 요청에 사용됩니다.

### APF 및 삭제된 요청 모니터링

APF로 인해 삭제된 요청이 있는지 확인하려면 `apiserver_flowcontrol_rejected_requests_total`에 대한 API Server 지표를 모니터링하여 영향을 받은 FlowSchemas 및 PriorityLevelConfigurations를 확인할 수 있습니다. 예를 들어 이 지표는 워크로드가 낮은 대기열의 요청 시간 초과로 인해 service account FlowSchema의 요청 100개가 삭제되었음을 보여줍니다.

```
% kubectl get --raw /metrics | grep apiserver_flowcontrol_rejected_requests_total
apiserver_flowcontrol_rejected_requests_total{flow_schema="service-accounts",priority_level="workload-low",reason="time-out"} 100
```

지정된 PriorityLevelConfiguration이 429를 수신하거나 큐로 인해 지연 시간이 증가하는 정도를 확인하려면 동시성 제한과 사용 중인 동시성의 차이를 비교할 수 있습니다. 이 예에는 100개의 요청 버퍼가 있습니다.

```
% kubectl get --raw /metrics | grep 'apiserver_flowcontrol_request_concurrency_limit.*workload-low'
apiserver_flowcontrol_request_concurrency_limit{priority_level="workload-low"} 245

% kubectl get --raw /metrics | grep 'apiserver_flowcontrol_request_concurrency_in_use.*workload-low'
apiserver_flowcontrol_request_concurrency_in_use{flow_schema="service-accounts",priority_level="workload-low"} 145
```

특정 PriorityLevelConfiguration에서 대기열이 발생하지만 반드시 요청이 삭제되는 것은 아닌지 확인하려면 `apiserver_flowcontrol_current_inqueue_requests`에 대한 측정 지표를 참조할 수 있습니다.

```
% kubectl get --raw /metrics | grep 'apiserver_flowcontrol_current_inqueue_requests.*workload-low'
apiserver_flowcontrol_current_inqueue_requests{flow_schema="service-accounts",priority_level="workload-low"} 10
```

기타 유용한 Prometheus 측정항목은 다음과 같습니다:

- apiserver_flowcontrol_dispatched_requests_total
- apiserver_flowcontrol_request_execution_seconds
- apiserver_flowcontrol_request_wait_duration_seconds

[APF 지표](https://kubernetes.io/docs/concepts/cluster-administration/flow-control/#observability)의 전체 목록은 업스트림 문서를 참조하세요.

### 삭제된 요청 방지

#### 워크로드를 변경하여 429를 방지

APF가 허용된 최대 내부 요청 수를 초과하는 지정된 PriorityLevelConfiguration으로 인해 요청을 삭제하는 경우 영향을 받는 FlowSchemas의 클라이언트는 지정된 시간에 실행되는 요청 수를 줄일 수 있습니다. 이는 429가 발생하는 기간 동안 이루어진 총 요청 수를 줄임으로써 달성할 수 있습니다. 비용이 많이 드는 목록 호출과 같은 장기 실행 요청은 실행되는 전체 기간 동안 진행 중인 요청으로 계산되기 때문에 특히 문제가 됩니다. 비용이 많이 드는 요청 수를 줄이거나 목록 호출의 대기 시간을 최적화하면(예: 요청 당 가져오는 객체 수를 줄이거나 watch 요청을 사용하도록 전환) 해당 워크로드에 필요한 총 동시성을 줄이는 데 도움이 될 수 있습니다.

#### APF 설정을 변경하여 429를 방지

!!! warning
     수행 중인 작업을 알고 있는 경우에만 기본 APF 설정을 변경하십시오. APF 설정이 잘못 구성되면 API Server 요청이 중단되고 워크로드가 크게 중단될 수 있습니다.

요청 삭제를 방지하기 위한 또 다른 접근 방식은 EKS 클러스터에 설치된 기본 FlowSchemas 또는 PriorityLevelConfigurations를 변경하는 것입니다. EKS는 지정된 쿠버네티스 마이너 버전에 대한 FlowSchemas 및 PriorityLevelConfigurations의 업스트림 기본 설정을 설치합니다. API는 객체에 대한 다음 주석이 false로 설정되지 않은 한 이러한 객체를 기본값으로 자동으로 다시 조정합니다.

```
  metadata:
    annotations:
      apf.kubernetes.io/autoupdate-spec: "false"
```

높은 수준에서 APF 설정은 다음 중 하나로 수정될 수 있습니다.

- 관심 있는 요청에 더 많은 기내 수용 능력을 할당하세요.
- 다른 요청 유형에 대한 용량이 부족할 수 있는 비필수적이거나 비용이 많이 드는 요청을 격리합니다.

이는 기본 FlowSchemas 및 PriorityLevelConfigurations를 변경하거나 이러한 유형의 새 개체를 생성하여 수행할 수 있습니다. 관리자는 관련 PriorityLevelConfigurations 개체에 대한 authenticateConcurrencyShares 값을 늘려 할당되는 진행 중 요청 비율을 늘릴 수 있습니다. 또한 요청이 발송되기 전에 대기열에 추가되어 발생하는 추가 대기 시간을 애플리케이션에서 처리할 수 있는 경우 특정 시간에 대기열에 추가할 수 있는 요청 수도 늘어날 수 있습니다.

또는 고객의 워크로드에 맞는 새로운 FlowSchema 및 PriorityLevelConfigurations 개체를 생성할 수 있습니다. 기존 PriorityLevelConfigurations 또는 새로운 PriorityLevelConfigurations에 더 많은 secureConcurrencyShares를 할당하면 전체 한도가 API Server 당 600개로 유지되므로 다른 버킷에서 처리할 수 있는 요청 수가 줄어듭니다.

APF 기본값을 변경할 때 설정 변경으로 인해 의도하지 않은 429가 발생하지 않도록 비프로덕션 클러스터에서 이러한 측정항목을 모니터링해야 합니다.

1. 버킷이 요청 삭제를 시작하지 않도록 모든 FlowSchemas에 대해 `apiserver_flowcontrol_rejected_requests_total`에 대한 측정 지표를 모니터링해야 합니다.
2. `apiserver_flowcontrol_request_concurrency_limit` 및 `apiserver_flowcontrol_request_concurrency_in_use` 값을 비교하여 사용 중인 동시성이 해당 우선순위 수준의 제한을 위반할 위험이 없는지 확인해야 합니다.

새로운 FlowSchema 및 PriorityLevelConfiguration을 정의하는 일반적인 사용 사례 중 하나는 격리입니다. 파드에서 장기 실행 목록 이벤트 호출을 자체 요청 공유로 분리한다고 가정해 보겠습니다. 이렇게 하면 기존 서비스 계정 FlowSchema를 사용하는 파드의 중요한 요청이 429를 수신하여 요청 용량이 부족해지는 것을 방지할 수 있습니다. 진행 중인 요청의 총 개수는 유한하지만 이 예에서는 APF 설정을 수정하여 지정된 워크로드에 대한 요청 용량을 더 잘 나눌 수 있음을 보여줍니다.

List 이벤트 요청을 분리하기 위한 FlowSchema 객체의 예:

```
apiVersion: flowcontrol.apiserver.k8s.io/v1beta1
kind: FlowSchema
metadata:
  name: list-events-default-service-accounts
spec:
  distinguisherMethod:
    type: ByUser
  matchingPrecedence: 8000
  priorityLevelConfiguration:
    name: catch-all
  rules:
  - resourceRules:
    - apiGroups:
      - '*'
      namespaces:
      - default
      resources:
      - events
      verbs:
      - list
    subjects:
    - kind: ServiceAccount
      serviceAccount:
        name: default
        namespace: default
```

- 이 FlowSchema는 기본 네임스페이스의 Service Account에서 수행된 모든 List 이벤트 호출을 캡처합니다.
- 일치 우선 순위 8000은 기존 Service Account FlowSchema에서 사용하는 값 9000보다 낮으므로 이러한 List 이벤트 호출은 Service Account가 아닌 list-events-default-service-account와 일치합니다.
- 이러한 요청을 격리하기 위해 포괄적인 PriorityLevelConfiguration을 사용하고 있습니다. 이 버킷은 장기 실행되는 list 이벤트 호출에서 13개의 진행 중인 요청만 사용할 수 있도록 허용합니다. 파드는 동시에 13개 이상의 요청을 발행하려고 시도하지만 즉시 429를 응답받기 시작합니다.

## API Server에서 리소스 검색

API Server에서 정보를 가져오는 것은 모든 규모의 클러스터에서 예상되는 동작입니다. 클러스터의 리소스 수를 확장하면 요청 빈도와 데이터 볼륨이 빠르게 컨트롤 플레인의 병목 현상이 되어 API 쓰로틀링 및 속도 저하로 이어질 수 있습니다. 지연 시간의 심각도에 따라 주의하지 않으면 예상치 못한 다운타임이 발생할 수 있습니다.

이러한 유형의 문제를 방지하기 위한 첫 번째 단계는 무엇을 요청하고 얼마나 자주 요청하는지 파악하는 것입니다. 다음은 규모 조정 모범 사례에 따라 쿼리 양을 제한하는 지침입니다. 이 섹션의 제안 사항은 확장성이 가장 좋은 것으로 알려진 옵션부터 순서대로 제공됩니다.

### Shared Informers 사용

쿠버네티스 API와 통합되는 컨트롤러 및 자동화를 구축할 때 쿠버네티스 리소스에서 정보를 가져와야 하는 경우가 많습니다. 이러한 리소스를 정기적으로 폴링하면 API Server에 상당한 부하가 발생할 수 있습니다.

client-go 라이브러리의 [informer](https://pkg.go.dev/k8s.io/client-go/informers) 를 사용하면 변경 사항을 폴링하는 대신 이벤트를 기반으로 리소스의 변경 사항을 관찰할 수 있다는 이점이 있습니다. Shared Informer는 이벤트 및 변경 사항에 공유 캐시를 사용하여 부하를 더욱 줄이므로 동일한 리소스를 감시하는 여러 컨트롤러로 인해 추가 부하가 가중되지 않습니다.

컨트롤러는 특히 대규모 클러스터의 경우 label 및 field selectors 없이 클러스터 전체 리소스를 폴링하지 않아야 합니다. 필터링되지 않은 각 폴링에는 클라이언트가 필터링하기 위해 etcd에서 API Server를 통해 많은 양의 불필요한 데이터를 전송해야 합니다. 레이블과 네임스페이스를 기반으로 필터링하면 API 서버가 요청을 처리하고 클라이언트에 전송되는 데이터를 처리하기 위해 수행해야 하는 작업량을 줄일 수 있습니다.

### 쿠버네티스 API 사용 최적화

사용자 정의 컨트롤러 또는 자동화를 사용하여 쿠버네티스 API를 호출할 때 필요한 리소스로만 호출을 제한하는 것이 중요합니다. 제한이 없으면 API Server 및 etcd에 불필요한 로드가 발생할 수 있습니다.

가능하면 watch 인자를 사용하는 것이 좋습니다. 인자가 없으면 기본 동작은 객체를 나열하는 것입니다. list 대신 watch를 사용하려면 API 요청 끝에 `?watch=true`를 추가하면 됩니다. 예를 들어 watch를 사용하여 기본 네임스페이스의 모든 파드를 가져오려면 다음을 사용하세요.

```
/api/v1/namespaces/default/pods?watch=true
```

객체를 나열하는 경우 나열하는 항목의 범위와 반환되는 데이터의 양을 제한해야 합니다. 요청에 `limit=500` 인수를 추가하여 반환되는 데이터를 제한할 수 있습니다. `fieldSelector` 인수와 `/namespace/` 경로는 목록의 범위를 필요에 따라 좁게 지정하는 데 유용할 수 있습니다. 예를 들어 기본 네임스페이스에서 실행 중인 파드만 나열하려면 다음 API 경로와 인수를 사용합니다.

```
/api/v1/namespaces/default/pods?fieldSelector=status.phase=Running&limit=500
```

또는 다음을 사용하여 실행 중인 모든 파드를 나열합니다.

```
/api/v1/pods?fieldSelector=status.phase=Running&limit=500
```

나열된 오브젝트를 제한하는 또 다른 옵션은 [`ResourceVersions` (쿠버네티스 설명서 참조)](https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions)를 사용하는 것 입니다. `ResourceVersion` 인자가 없으면 사용 가능한 최신 버전을 받게 되며, 이 경우 데이터베이스에서 가장 비용이 많이 들고 가장 느린 etcd 쿼럼 읽기가 필요합니다. resourceVersion은 쿼리하려는 리소스에 따라 달라지며, `Metadata.Resourceversion` 필드에서 찾을 수 있습니다.

API Server 캐시에서 결과를 반환하는 특별한 `ResourceVersion=0`이 있습니다. 이렇게 하면 etcd 부하를 줄일 수 있지만 Pagination은 지원하지 않습니다.

```
/api/v1/namespaces/default/pods?resourceVersion=0
```

인자 없이 API를 호출하면 API Server 및 etcd에서 리소스를 가장 많이 사용하게 됩니다.이 호출을 사용하면 Pagination이나 범위 제한 없이 모든 네임스페이스의 모든 파드를 가져오고 etcd에서 쿼럼을 읽어야 합니다.

```
/api/v1/pods
```

search    exclude  true                                             API Server        Controller Manager  Scheduler                                                                                EKS 1 24            EKS 1 24                                 docker     containerd  https   containerd io            Containerd                                                                      Containerd          EKS                 1 24         Containerd            container runtime  bootstrap flag  https   docs aws amazon com eks latest userguide eks optimized ami html containerd bootstrap                                    Attention               API                                                                    1000       1100         4000    4500         EKS                                                     EKS                                                              EKS                                       https   aws amazon com blogs containers amazon eks control plane auto scaling enhancements improve speed by 4x                                                                                CPU                                                  HPA Horizontal Pod Autoscaler                                                                                https   kubernetes io docs tasks run application horizontal pod autoscale walkthrough  autoscaling on multiple metrics and custom metrics                                   AWS SQS                                           KEDA  https   keda sh                                                                                Karpenter   Time To Live  TTL   https   aws github io aws eks best practices karpenter  use timers ttl to automatically delete nodes from the cluster                                                                max instance lifetime                                                             GitHub    https   github com aws containers roadmap issues 1190                                          scale down utilization threshold   https   github com kubernetes autoscaler blob master cluster autoscaler FAQ md how does scale down work            Cluster Autoscaler                                                   Karpenter    ttlSecondsAfterEmpty                             Pod Distruption Budgets                                                             EndpointSlices                                                          API Server                                Pod Distruption Budgets  https   kubernetes io docs concepts workloads pods disruptions                                                                        Kubectl                    kubectl                       API Server                     kubectl           for                                                             kubectl        API                                                                       10                                       kubectl          API                           API               cache dir                                    kubectl Compression       kubeconfig      kubectl compression         API         CPU                                                                                CPU                                                                     kubeconfig         disable compression true              disable compression  true                  apiVersion  v1 clusters    cluster      server  serverURL     disable compression  true   name  cluster         Cluster Autoscaler            Cluster Autoscaler              https   github com kubernetes autoscaler blob master cluster autoscaler proposals scalability tests md      1 000                   1000                         Cluster AutoScaler                                                                                4              2                            ClusterAutoscaler 1      autoscalingGroups    name  eks core node grp 20220823190924690000000011 80c1660e 030d 476d cb0d d04d585a8fcb   maxSize  50   minSize  2   name  eks data m1 20220824130553925600000011 5ec167fa ca93 8ca4 53a5 003e1ed8d306   maxSize  450   minSize  2   name  eks data m2 20220824130733258600000015 aac167fb 8bf7 429d d032 e195af4e25f5   maxSize  450   minSize  2   name  eks data m3 20220824130553914900000003 18c167fa ca7f 23c9 0fea f9edefbda002   maxSize  450   minSize  2      ClusterAutoscaler 2      autoscalingGroups    name  eks data m4 2022082413055392550000000f 5ec167fa ca86 6b83 ae9d 1e07ade3e7c4   maxSize  450   minSize  2   name  eks data m5 20220824130744542100000017 02c167fb a1f7 3d9e a583 43b4975c050c   maxSize  450   minSize  2   name  eks data m6 2022082413055392430000000d 9cc167fa ca94 132a 04ad e43166cef41f   maxSize  450   minSize  2   name  eks data m7 20220824130553921000000009 96c167fa ca91 d767 0427 91c879ddf5af   maxSize  450   minSize  2         API Priority and Fairness         images APF jpg            iframe width  560  height  315  src  https   www youtube com embed YnPPHBawhE0  title  YouTube video player  frameborder  0  allow  accelerometer  autoplay  clipboard write  encrypted media  gyroscope  picture in picture  web share  allowfullscreen   iframe                                        API                                                   API                    Too many requests      429 HTTP                                                                                API Priority and Fairness  https   kubernetes io docs concepts cluster administration flow control           API        max requests inflight       max mutating requests inflight                                                 EKS                   400    200                      600                   APF      600                                  EKS                     2   API                                                      1200           PriorityLevelConfigurations   FlowSchemas                                                                API                     EKS                                             PriorityLevelConfigurations                                        PriorityLevelConfiguration     600        98             PriorityLevelConfigurations              600                             API Server         600                 PriorityLevelConfigurations                                         EKS 1 24                        kubectl get   raw  metrics   grep apiserver flowcontrol request concurrency limit apiserver flowcontrol request concurrency limit priority level  catch all   13 apiserver flowcontrol request concurrency limit priority level  global default   49 apiserver flowcontrol request concurrency limit priority level  leader election   25 apiserver flowcontrol request concurrency limit priority level  node high   98 apiserver flowcontrol request concurrency limit priority level  system   74 apiserver flowcontrol request concurrency limit priority level  workload high   98 apiserver flowcontrol request concurrency limit priority level  workload low   245                   FlowSchemas                   API            FlowSchema                           API Group                                   FlowSchema                        PriorityLevelConfiguration                               inflight                                 API Server                      FlowSchemas           FlowSchemas            FlowSchemas              API Server                               FlowSchema          FlowSchemas  PriorityLevelConfigurations                                   kubectl get flowschemas NAME                           PRIORITYLEVEL     MATCHINGPRECEDENCE   DISTINGUISHERMETHOD   AGE     MISSINGPL exempt                         exempt            1                     none                 7h19m   False eks exempt                     exempt            2                     none                 7h19m   False probes                         exempt            2                     none                 7h19m   False system leader election         leader election   100                  ByUser                7h19m   False endpoint controller            workload high     150                  ByUser                7h19m   False workload leader election       leader election   200                  ByUser                7h19m   False system node high               node high         400                  ByUser                7h19m   False system nodes                   system            500                  ByUser                7h19m   False kube controller manager        workload high     800                  ByNamespace           7h19m   False kube scheduler                 workload high     800                  ByNamespace           7h19m   False kube system service accounts   workload high     900                  ByNamespace           7h19m   False eks workload high              workload high     1000                 ByUser                7h14m   False service accounts               workload low      9000                 ByUser                7h19m   False global default                 global default    9900                 ByUser                7h19m   False catch all                      catch all         10000                ByUser                7h19m   False      PriorityLevelConfigurations   Queue  Reject    Exempt                Queue   Reject                                                                                PriorityLevelConfiguration  Queue                                       kube system                                 98        Queue           API Server                                                     98                                                                  API Server                  429                             429                                                   Reject               PriorityLevelConfiguration            FlowSchema                  13                     API Server               429                                 Exempt          PriorityLevelConfiguration           429                           healthz      system masters                                          APF                APF                        apiserver flowcontrol rejected requests total      API Server                   FlowSchemas   PriorityLevelConfigurations                                                     service account FlowSchema     100                        kubectl get   raw  metrics   grep apiserver flowcontrol rejected requests total apiserver flowcontrol rejected requests total flow schema  service accounts  priority level  workload low  reason  time out   100          PriorityLevelConfiguration  429                                                                             100                       kubectl get   raw  metrics   grep  apiserver flowcontrol request concurrency limit  workload low  apiserver flowcontrol request concurrency limit priority level  workload low   245    kubectl get   raw  metrics   grep  apiserver flowcontrol request concurrency in use  workload low  apiserver flowcontrol request concurrency in use flow schema  service accounts  priority level  workload low   145         PriorityLevelConfiguration                                         apiserver flowcontrol current inqueue requests                                kubectl get   raw  metrics   grep  apiserver flowcontrol current inqueue requests  workload low  apiserver flowcontrol current inqueue requests flow schema  service accounts  priority level  workload low   10             Prometheus                    apiserver flowcontrol dispatched requests total   apiserver flowcontrol request execution seconds   apiserver flowcontrol request wait duration seconds   APF     https   kubernetes io docs concepts cluster administration flow control  observability                                                          429      APF                           PriorityLevelConfiguration                         FlowSchemas                                          429                                                                                watch                                                             APF          429          warning                              APF             APF             API Server                                                           EKS              FlowSchemas    PriorityLevelConfigurations             EKS                       FlowSchemas   PriorityLevelConfigurations                     API                false                                                metadata      annotations        apf kubernetes io autoupdate spec   false               APF                                                                                FlowSchemas   PriorityLevelConfigurations                                               PriorityLevelConfigurations        authenticateConcurrencyShares                                                                                FlowSchema   PriorityLevelConfigurations                    PriorityLevelConfigurations        PriorityLevelConfigurations       secureConcurrencyShares              API Server   600                                        APF                               429                                               1                         FlowSchemas      apiserver flowcontrol rejected requests total                         2   apiserver flowcontrol request concurrency limit     apiserver flowcontrol request concurrency in use                                                                FlowSchema   PriorityLevelConfiguration                                                                                FlowSchema                   429                                                                APF                                                   List                 FlowSchema             apiVersion  flowcontrol apiserver k8s io v1beta1 kind  FlowSchema metadata    name  list events default service accounts spec    distinguisherMethod      type  ByUser   matchingPrecedence  8000   priorityLevelConfiguration      name  catch all   rules      resourceRules        apiGroups                    namespaces          default       resources          events       verbs          list     subjects        kind  ServiceAccount       serviceAccount          name  default         namespace  default          FlowSchema             Service Account          List                           8000     Service Account FlowSchema          9000            List         Service Account     list events default service account                                PriorityLevelConfiguration                           list          13                                      13                         429                  API Server           API Server                                                                                API                                                                                Shared Informers           API                                                                               API Server                       client go         informer  https   pkg go dev k8s io client go informers                                                                  Shared Informer                                                                                label   field selectors                                                               etcd   API Server                                                       API                                                                          API                                        API                                             API Server   etcd                             watch                                                 list    watch        API         watch true                   watch                                                api v1 namespaces default pods watch true                                                           limit 500                                  fieldSelector        namespace                                                                                API                      api v1 namespaces default pods fieldSelector status phase Running limit 500                                            api v1 pods fieldSelector status phase Running limit 500                                ResourceVersions                  https   kubernetes io docs reference using api api concepts  resource versions                ResourceVersion                                                                etcd               resourceVersion                       Metadata Resourceversion                   API Server                    ResourceVersion 0                etcd              Pagination                   api v1 namespaces default pods resourceVersion 0            API       API Server   etcd                                  Pagination                                   etcd                      api v1 pods


Answer:
---
search:
  exclude: true
---

# 쿠버네티스 데이터 플레인

쿠버네티스 데이터 플레인은 쿠버네티스 컨트롤 플레인이 사용하는 EC2 인스턴스, 로드 밸런서, 스토리지 및 기타 API를 포함합니다. 조직화를 위해 [클러스터 서비스](./cluster-services.md)를 별도의 페이지로 그룹화했으며 로드 밸런서 확장은 [워크로드 섹션](./workloads.md)에서 찾을 수 있습니다. 이 섹션에서는 컴퓨팅 리소스 확장에 중점을 둡니다.

여러 워크로드가 있는 클러스터에서는 EC2 인스턴스 유형을 선택하는 것이 고객이 직면하는 가장 어려운 결정 중 하나일 수 있습니다. 모든 상황에 맞는 단일 솔루션은 없습니다. 다음은 컴퓨팅 확장과 관련된 일반적인 위험을 방지하는 데 도움이 되는 몇 가지 팁입니다.

## 자동 노드 오토 스케일링

수고를 줄이고 쿠버네티스와 긴밀하게 통합되는 노드 오토 스케일링을 사용하는 것이 좋습니다. 대규모 클러스터에는 [관리형 노드 그룹](https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html) 및 [Karpenter](https://karpenter.sh/) 를 사용하는 것이 좋습니다.

관리형 노드 그룹은 관리형 업그레이드 및 구성에 대한 추가 이점과 함께 Amazon EC2 Auto Scaling 그룹의 유연성을 제공합니다. [쿠버네티스 Cluster Autoscaler](https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler)를 사용하여 확장할 수 있으며 다양한 컴퓨팅 요구 사항이 있는 클러스터에 대한 일반적인 옵션입니다.

Karpenter는 AWS에서 만든 오픈 소스 워크로드 네이티브 노드 오토 스케일러입니다. 노드 그룹을 관리하지 않고도 리소스 (예: GPU) 와 taint 및 tolerations (예: zone spread)에 대한 워크로드 요구 사항을 기반으로 클러스터의 노드를 확장합니다. 노드는 EC2로부터 직접 생성되므로 기본 노드 그룹 할당량 (그룹당 450개 노드)이 필요 없으며 운영 오버헤드를 줄이면서 인스턴스 선택 유연성이 향상됩니다. 고객은 가능하면 Karpenter를 사용하는 것이 좋습니다.

## 다양한 EC2 인스턴스 유형 사용

각 AWS 리전에는 인스턴스 유형별로 사용 가능한 인스턴스 수가 제한되어 있습니다. 하나의 인스턴스 유형만 사용하는 클러스터를 생성하고 리전의 용량을 초과하여 노드 수를 확장하면 사용 가능한 인스턴스가 없다는 오류가 발생합니다. 이 문제를 방지하려면 클러스터에서 사용할 수 있는 인스턴스 유형을 임의로 제한해서는 안 됩니다.

Karpenter는 기본적으로 호환되는 다양한 인스턴스 유형을 사용하며 보류 중인 워크로드 요구 사항, 가용성 및 비용을 기반으로 프로비저닝 시 인스턴스를 선택합니다. [NodePools](https://karpenter.sh/docs/concepts/nodepools/#instance-types)의 `karpenter.k8s.aws/instance-category` 키에 사용되는 인스턴스 유형 목록을 정의할 수 있습니다.

쿠버네티스 Cluster Autoscaler를 사용하려면 노드 그룹이 일관되게 확장될 수 있도록 유사한 크기의 유형을 필요로 합니다. CPU 및 메모리 크기를 기준으로 여러 그룹을 생성하고 독립적으로 확장해야 합니다. [ec2-instance-selector](https://github.com/aws/amazon-ec2-instance-selector)를 사용하여 노드 그룹과 비슷한 크기의 인스턴스를 식별하세요.

```
ec2-instance-selector --service eks --vcpus-min 8 --memory-min 16
a1.2xlarge
a1.4xlarge
a1.metal
c4.4xlarge
c4.8xlarge
c5.12xlarge
c5.18xlarge
c5.24xlarge
c5.2xlarge
c5.4xlarge
c5.9xlarge
c5.metal
```

## API 서버 부하를 줄이기 위해 더 큰 노드를 선호

어떤 인스턴스 유형을 사용할지 결정할 때 노드 수가 적고 크면 쿠버네티스 컨트롤 플레인에 걸리는 부하가 줄어듭니다. 실행 중인 kubelet과 데몬셋의 수가 줄어들기 때문입니다. 그러나 큰 노드는 작은 노드처럼 충분히 활용되지 않을 수 있습니다. 노드 크기는 워크로드의 가용성 및 확장성을 기반으로 평가해야 합니다.

u-24tb1.metal 인스턴스 3개 (24TB Memory 및 448 cores)가 있는 클러스터에는 3개의 kubelets가 있으며 기본적으로 노드당 110개의 파드로 제한됩니다. 파드가 각각 4개의 코어를 사용하는 경우 이는 예상할 수 있습니다 (4코어 x 110 = 노드당 440코어). 클러스터에 3개의 노드를 사용하면 인스턴스 1개가 중단될 때 클러스터의 1/3에 영향을 미칠 수 있으므로 인스턴스 인시던트를 처리하는 능력이 떨어집니다. 쿠버네티스 스케줄러가 워크로드를 적절하게 배치할 수 있도록 워크로드에 노드 요구 사항과 pod spread를 지정해야 합니다.

워크로드는 taint, tolerations 및 [PodTopologySpread](https://kubernetes.io/blog/2020/05/introducing-podtopologyspread/)를 통해 필요한 리소스와 필요한 가용성을 정의해야 합니다. 이들은 컨트롤 플레인의 부하 감소, 운영 감소, 비용 절감이라는 가용성 목표를 충분히 활용할 수 있고 가용성 목표를 충족할 수 있는 가장 큰 노드를 선호해야 합니다.

쿠버네티스 Scheduler는 리소스를 사용할 수 있는 경우 가용 영역과 호스트에 워크로드를 자동으로 분산하려고 합니다. 사용 가능한 용량이 없는 경우 쿠버네티스 Cluster Autoscaler는 각 가용 영역에 노드를 균등하게 추가하려고 시도합니다. 워크로드에 다른 요구 사항이 지정되어 있지 않는 한 Karpenter는 가능한 한 빠르고 저렴하게 노드를 추가하려고 시도합니다.

스케줄러를 통해 워크로드를 분산시키고 가용 영역 전체에 새 노드를 생성하도록 하려면 TopologySpreadConstraints (topologySpreadConstraints) 를 사용해야 합니다.

```
spec:
  topologySpreadConstraints:
    - maxSkew: 3
      topologyKey: "topology.kubernetes.io/zone"
      whenUnsatisfiable: ScheduleAnyway
      labelSelector:
        matchLabels:
          dev: my-deployment
    - maxSkew: 2
      topologyKey: "kubernetes.io/hostname"
      whenUnsatisfiable: ScheduleAnyway
      labelSelector:
        matchLabels:
          dev: my-deployment
```

## 일관된 워크로드 성능을 위해 유사한 노드 크기 사용

워크로드는 일관된 성능과 예측 가능한 확장을 허용하기 위해 실행해야 하는 노드 크기를 정의해야 합니다. 500m CPU를 요청하는 워크로드는 4 cores 인스턴스와 16 cores 인스턴스에서 다르게 수행됩니다. T 시리즈 인스턴스와 같이 버스트 가능한 CPU를 사용하는 인스턴스 유형은 피하세요.

워크로드가 일관된 성능을 얻을 수 있도록 워크로드는 [지원되는 Karpenter 레이블](https://karpenter.sh/docs/concepts/scheduling/#labels)을 사용하여 특정 인스턴스 크기를 대상으로 할 수 있습니다.

```
kind: deployment
...
spec:
  template:
    spec:
    containers:
    nodeSelector:
      karpenter.k8s.aws/instance-size: 8xlarge
```

쿠버네티스 Cluster Autoscaler를 사용하여 클러스터에서 스케줄링되는 워크로드는 레이블 매칭을 기반으로 node selector를 노드 그룹과 일치시켜야 합니다.

```
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: eks.amazonaws.com/nodegroup
            operator: In
            values:
            - 8-core-node-group    # match your node group name
```

## 컴퓨팅 리소스를 효율적으로 사용

컴퓨팅 리소스에는 EC2 인스턴스 및 가용 영역이 포함됩니다. 컴퓨팅 리소스를 효과적으로 사용하면 확장성, 가용성, 성능이 향상되고 총 비용이 절감됩니다. 오토 스케일링 환경에서 여러 애플리케이션은 효율적인 리소스 사용량을 예측하기가 극히 어렵습니다. [Karpenter](https://karpenter.sh/)는 워크로드 요구 사항에 따라 온디맨드로 인스턴스를 프로비저닝하여 활용도와 유연성을 극대화하기 위해 만들어졌습니다.

Karpenter를 사용하면 먼저 노드 그룹을 생성하거나 특정 노드에 대한 label taint를 구성하지 않고도 워크로드에 필요한 컴퓨팅 리소스 유형을 선언할 수 있습니다. 자세한 내용은 [Karpenter best practices](https://aws.github.io/aws-eks-best-practices/karpenter/)를 참조하세요. Karpenter provisioner에서 [consolidation](https://aws.github.io/aws-eks-best-practices/karpenter/#configure-requestslimits-for-all-non-cpu-resources-when-using-consolidation)을 활성화하여 활용도가 낮은 노드를 교체해 보세요.

## Amazon Machine Image (AMI) 업데이트 자동화

Worker 노드 구성 요소를 최신 상태로 유지하면 최신 보안 패치와 쿠버네티스 API와 호환되는 기능을 사용할 수 있습니다. kublet 업데이트는 쿠버네티스 기능의 가장 중요한 구성 요소이지만 OS, 커널 및 로컬에 설치된 애플리케이션 패치를 자동화하면 확장에 따른 유지 관리 비용을 줄일 수 있습니다.

노드 이미지에는 최신 [Amazon EKS optimized Amazon Linux 2](https://docs.aws.amazon.com/eks/latest/userguide/eks-optimized-ami.html) 또는 [Amazon EKS optimized Bottlerocket AMI](https://docs.aws.amazon.com/eks/latest/userguide/eks-optimized-ami-bottlerocket.html)를 사용하는 것이 좋습니다. Karpenter는 [사용 가능한 최신 AMI](https://karpenter.sh/docs/concepts/nodepools/#instance-types) 를 자동으로 사용하여 클러스터에 새 노드를 프로비저닝합니다. 관리형 노드 그룹은 [노드 그룹 업데이트](https://docs.aws.amazon.com/eks/latest/userguide/update-managed-node-group.html) 중에 AMI를 업데이트하지만 노드 프로비저닝 시에는 AMI ID를 업데이트하지 않습니다.

관리형 노드 그룹의 경우 패치 릴리스에 사용할 수 있게 되면 Auto Scaling Group (ASG) 시작 템플릿을 새 AMI ID로 업데이트해야 합니다. AMI 마이너 버전 (예: 1.23.5~1.24.3)은 EKS 콘솔 및 API에서 [노드 그룹 업그레이드](https://docs.aws.amazon.com/eks/latest/userguide/update-managed-node-group.html)로 제공됩니다. 패치 릴리스 버전 (예: 1.23.5 ~ 1.23.6)은 노드 그룹에 대한 업그레이드로 제공되지 않습니다. AMI 패치 릴리스를 통해 노드 그룹을 최신 상태로 유지하려면 새 시작 템플릿 버전을 생성하고 노드 그룹이 인스턴스를 새 AMI 릴리스로 교체하도록 해야 합니다.

[이 페이지](https://docs.aws.amazon.com/eks/latest/userguide/eks-optimized-ami.html) 에서 사용 가능한 최신 AMI를 찾거나 AWS CLI를 사용할 수 있습니다.

```
aws ssm get-parameter \
  --name /aws/service/eks/optimized-ami/1.24/amazon-linux-2/recommended/image_id \
  --query "Parameter.Value" \
  --output text
```
## 컨테이너에 여러 EBS 볼륨 사용

EBS 볼륨에는 볼륨 유형 (예: gp3) 및 디스크 크기에 따른 입/출력 (I/O) 할당량이 있습니다. 애플리케이션이 호스트와 단일 EBS 루트 볼륨을 공유하는 경우 전체 호스트의 디스크 할당량이 고갈되고 다른 애플리케이션이 가용 용량을 기다리게 될 수 있습니다.응 용 프로그램은 오버레이 파티션에 파일을 쓰고, 호스트에서 로컬 볼륨을 마운트하고, 사용된 로깅 에이전트에 따라 표준 출력 (STDOUT)에 로그온할 때도 디스크에 기록합니다.

Disk I/O 소모를 방지하려면 두 번째 볼륨을 컨테이너 state 폴더 (예: /run/containerd)에 마운트하고, 워크로드 스토리지용으로 별도의 EBS 볼륨을 사용하고, 불필요한 로컬 로깅을 비활성화해야 합니다.

[eksctl](https://eksctl.io/)을 사용하여 EC2 인스턴스에 두 번째 볼륨을 마운트하려면 다음과 같은 구성의 노드 그룹을 사용할 수 있습니다.

```
managedNodeGroups:
  - name: al2-workers
    amiFamily: AmazonLinux2
    desiredCapacity: 2
    volumeSize: 80
    additionalVolumes:
      - volumeName: '/dev/sdz'
        volumeSize: 100
    preBootstrapCommands:
    - |
      "systemctl stop containerd"
      "mkfs -t ext4 /dev/nvme1n1"
      "rm -rf /var/lib/containerd/*"
      "mount /dev/nvme1n1 /var/lib/containerd/"
      "systemctl start containerd"
```

Terraform을 사용하여 노드 그룹을 프로비저닝하는 경우 [EKS Blueprints for terraform](https://aws-ia.github.io/terraform-aws-eks-blueprints/patterns/stateful/#eks-managed-nodegroup-w-multiple-volumes)의 예를 참조하세요. Karpenter를 사용하여 노드를 프로비저닝하는 경우 노드 사용자 데이터와 함께 [`blockDeviceMappings`](https://karpenter.sh/docs/concepts/nodeclasses/#specblockdevicemappings)를 사용하여 추가 볼륨을 추가할 수 있습니다.

EBS 볼륨을 파드에 직접 탑재하려면 [AWS EBS CSI 드라이버](https://github.com/kubernetes-sigs/aws-ebs-csi-driver)를 사용하고 스토리지 클래스가 있는 볼륨을 사용해야 합니다.

```
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: ebs-sc
provisioner: ebs.csi.aws.com
volumeBindingMode: WaitForFirstConsumer
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: ebs-claim
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: ebs-sc
  resources:
    requests:
      storage: 4Gi
---
apiVersion: v1
kind: Pod
metadata:
  name: app
spec:
  containers:
  - name: app
    image: public.ecr.aws/docker/library/nginx
    volumeMounts:
    - name: persistent-storage
      mountPath: /data
  volumes:
  - name: persistent-storage
    persistentVolumeClaim:
      claimName: ebs-claim
```

## 워크로드에서 EBS 볼륨을 사용하는 경우 EBS 연결 제한이 낮은 인스턴스를 피하세요.

EBS는 워크로드가 영구 스토리지를 확보하는 가장 쉬운 방법 중 하나이지만 확장성 제한도 있습니다. 각 인스턴스 유형에는 [연결할 수 있는 최대 EBS 볼륨](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/volume_limits.html) 수가 있습니다. 워크로드는 실행해야 하는 인스턴스 유형을 선언하고 쿠버네티스 taints가 있는 단일 인스턴스의 복제본 수를 제한해야 합니다.

## 디스크에 불필요한 로깅을 비활성화

프로덕션 환경에서 디버그 로깅을 사용하여 애플리케이션을 실행하지 않고 디스크를 자주 읽고 쓰는 로깅을 비활성화하여 불필요한 로컬 로깅을 피하세요. Journald는 로그 버퍼를 메모리에 유지하고 주기적으로 디스크에 플러시하는 로컬 로깅 서비스입니다. Journald는 모든 행을 즉시 디스크에 기록하는 syslog보다 선호됩니다. syslog를 비활성화하면 필요한 총 스토리지 용량도 줄어들고 복잡한 로그 순환 규칙이 필요하지 않습니다. syslog를 비활성화하려면 cloud-init 구성에 다음 코드 조각을 추가하면 됩니다.

```
runcmd:
  - [ systemctl, disable, --now, syslog.service ]
```

## OS 업데이트 속도가 필요할 때 in place 방식으로 인스턴스 패치

!!! Attention
    인스턴스 패치는 필요한 경우에만 수행해야 합니다. Amazon에서는 인프라를 변경할 수 없는 것으로 취급하고 애플리케이션과 동일한 방식으로 하위 환경을 통해 승격되는 업데이트를 철저히 테스트할 것을 권장합니다. 이 섹션은 이것이 불가능할 때 적용됩니다.

컨테이너화된 워크로드를 중단하지 않고 기존 Linux 호스트에 패키지를 설치하는 데 몇 초 밖에 걸리지 않습니다. 인스턴스를 차단(cordoning), 드레이닝(draining) 또는 교체(replacing)하지 않고도 패키지를 설치하고 검증할 수 있습니다.

인스턴스를 교체하려면 먼저 새 AMI를 생성, 검증 및 배포해야 합니다. 인스턴스에는 대체 인스턴스가 생성되어야 하며, 이전 인스턴스는 차단 및 제거되어야 합니다. 그런 다음 새 인스턴스에 워크로드를 생성하고 확인하고 패치가 필요한 모든 인스턴스에 대해 반복해야 합니다. 워크로드를 중단하지 않고 인스턴스를 안전하게 교체하려면 몇 시간, 며칠 또는 몇 주가 걸립니다.

Amazon에서는 자동화된 선언적 시스템에서 구축, 테스트 및 승격되는 불변 인프라를 사용할 것을 권장합니다. 하지만 시스템에 신속하게 패치를 적용해야 하는 경우 시스템을 패치하고 새 AMI가 출시되면 교체해야 합니다. 시스템 패치와 교체 사이의 시간 차이가 크기 때문에 [AWS Systems Manager Patch Manager](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-patch.html)를 사용하는 것이 좋습니다. 필요한 경우 노드 패치를 자동화합니다.

노드 패치를 사용하면 보안 업데이트를 신속하게 출시하고 AMI가 업데이트된 후 정기적인 일정에 따라 인스턴스를 교체할 수 있습니다. [Flatcar Container Linux](https://platcar-linux.org/) 또는 [Bottlerocket OS](https://github.com/bottlerocket-os/bottlerocket)와 같은 읽기 전용 루트 파일 시스템이 있는 운영 체제를 사용하는 경우 해당 운영 체제에서 작동하는 업데이트 연산자를 사용하는 것이 좋습니다. [Flatcar Linux update operator](https://github.com/platcar/platcar-linux-update-operator) 및 [Bottlerocket update operator](https://github.com/bottlerocket-os/bottlerocket-update-operator)는 인스턴스를 재부팅하여 노드를 자동으로 최신 상태로 유지합니다.

search    exclude  true                                                           EC2                         API                              cluster services md                                          workloads md                                                                 EC2                                                                                https   docs aws amazon com eks latest userguide managed node groups html     Karpenter  https   karpenter sh                                                            Amazon EC2 Auto Scaling                        Cluster Autoscaler  https   github com kubernetes autoscaler tree master cluster autoscaler                                                          Karpenter  AWS                                                             GPU    taint   tolerations     zone spread                                            EC2                               450                                                         Karpenter                        EC2               AWS                                                                                Karpenter                                                                                NodePools  https   karpenter sh docs concepts nodepools  instance types    karpenter k8s aws instance category                                         Cluster Autoscaler                                                   CPU                                             ec2 instance selector  https   github com aws amazon ec2 instance selector                                         ec2 instance selector   service eks   vcpus min 8   memory min 16 a1 2xlarge a1 4xlarge a1 metal c4 4xlarge c4 8xlarge c5 12xlarge c5 18xlarge c5 24xlarge c5 2xlarge c5 4xlarge c5 9xlarge c5 metal         API                                                                                kubelet                                                                                u 24tb1 metal      3   24TB Memory   448 cores             3   kubelets                110                     4                              4   x 110       440           3                 1               1 3                                                                                pod spread                   taint  tolerations    PodTopologySpread  https   kubernetes io blog 2020 05 introducing podtopologyspread                                                                                Scheduler                                                                            Cluster Autoscaler                                                              Karpenter                                                                                TopologySpreadConstraints  topologySpreadConstraints                   spec    topologySpreadConstraints        maxSkew  3       topologyKey   topology kubernetes io zone        whenUnsatisfiable  ScheduleAnyway       labelSelector          matchLabels            dev  my deployment       maxSkew  2       topologyKey   kubernetes io hostname        whenUnsatisfiable  ScheduleAnyway       labelSelector          matchLabels            dev  my deployment                                                                                500m CPU             4 cores       16 cores                   T                      CPU                                                          Karpenter      https   karpenter sh docs concepts scheduling  labels                                        kind  deployment     spec    template      spec      containers      nodeSelector        karpenter k8s aws instance size  8xlarge            Cluster Autoscaler                                        node selector                         spec    affinity      nodeAffinity        requiredDuringSchedulingIgnoredDuringExecution          nodeSelectorTerms            matchExpressions              key  eks amazonaws com nodegroup             operator  In             values                8 core node group      match your node group name                                      EC2                                                                                Karpenter  https   karpenter sh                                                                    Karpenter                                 label taint                                                      Karpenter best practices  https   aws github io aws eks best practices karpenter           Karpenter provisioner    consolidation  https   aws github io aws eks best practices karpenter  configure requestslimits for all non cpu resources when using consolidation                                  Amazon Machine Image  AMI            Worker                                       API                       kublet                                 OS                                                                          Amazon EKS optimized Amazon Linux 2  https   docs aws amazon com eks latest userguide eks optimized ami html      Amazon EKS optimized Bottlerocket AMI  https   docs aws amazon com eks latest userguide eks optimized ami bottlerocket html                 Karpenter             AMI  https   karpenter sh docs concepts nodepools  instance types                                                            https   docs aws amazon com eks latest userguide update managed node group html     AMI                       AMI ID                                                  Auto Scaling Group  ASG            AMI ID              AMI            1 23 5 1 24 3   EKS      API                 https   docs aws amazon com eks latest userguide update managed node group html                        1 23 5   1 23 6                               AMI                                                                 AMI                             https   docs aws amazon com eks latest userguide eks optimized ami html               AMI      AWS CLI                   aws ssm get parameter       name  aws service eks optimized ami 1 24 amazon linux 2 recommended image id       query  Parameter Value        output text                 EBS        EBS                gp3                     I O                             EBS                                                                                STDOUT                        Disk I O                         state         run containerd                           EBS                                     eksctl  https   eksctl io         EC2                                                          managedNodeGroups      name  al2 workers     amiFamily  AmazonLinux2     desiredCapacity  2     volumeSize  80     additionalVolumes          volumeName    dev sdz          volumeSize  100     preBootstrapCommands                 systemctl stop containerd         mkfs  t ext4  dev nvme1n1         rm  rf  var lib containerd           mount  dev nvme1n1  var lib containerd          systemctl start containerd       Terraform                          EKS Blueprints for terraform  https   aws ia github io terraform aws eks blueprints patterns stateful  eks managed nodegroup w multiple volumes             Karpenter                                       blockDeviceMappings   https   karpenter sh docs concepts nodeclasses  specblockdevicemappings                            EBS                   AWS EBS CSI       https   github com kubernetes sigs aws ebs csi driver                                            apiVersion  storage k8s io v1 kind  StorageClass metadata    name  ebs sc provisioner  ebs csi aws com volumeBindingMode  WaitForFirstConsumer     apiVersion  v1 kind  PersistentVolumeClaim metadata    name  ebs claim spec    accessModes        ReadWriteOnce   storageClassName  ebs sc   resources      requests        storage  4Gi     apiVersion  v1 kind  Pod metadata    name  app spec    containers      name  app     image  public ecr aws docker library nginx     volumeMounts        name  persistent storage       mountPath   data   volumes      name  persistent storage     persistentVolumeClaim        claimName  ebs claim                EBS             EBS                        EBS                                                                              EBS     https   docs aws amazon com AWSEC2 latest UserGuide volume limits html                                             taints                                                                                Journald                                                  Journald                     syslog          syslog                                                      syslog          cloud init                              runcmd        systemctl  disable    now  syslog service           OS                in place                   Attention                                 Amazon                                                                                Linux                                            cordoning        draining        replacing                                                AMI                                                                                Amazon                                                                                AMI                                               AWS Systems Manager Patch Manager  https   docs aws amazon com systems manager latest userguide systems manager patch html                                                                       AMI                                         Flatcar Container Linux  https   platcar linux org       Bottlerocket OS  https   github com bottlerocket os bottlerocket                                                                                Flatcar Linux update operator  https   github com platcar platcar linux update operator     Bottlerocket update operator  https   github com bottlerocket os bottlerocket update operator