k8s cpu request limit이 뭘까

서민정·2023년 9월 15일

줄줄줄 쓰는 글이라 가독성이 떨어질 수 있는 점...

CPU Request란?

파드가 실행 중인 노드에 리소스가 충분하면, 해당 리소스에 지정한 request보다 더 많은 리소스를 사용할 수 있도록 허용된다. 그러나 limit보다 더 많은 리소스를 사용할 수는 없다. 는게 원칙

limit은 아래처럼 지정할 수 있다.

---
apiVersion: v1
kind: Pod
metadata:
  name: frontend
spec:
  containers:
  - name: app
    image: images.my-company.example/app:v4
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"

예를 들어 위처럼 yaml이 정의되어있을 때, 해당 app 컨테이너는 cpu에 대한 최소 요구사항이 250m(0.25 CPU), limit이 (0.5 CPU)인 것을 확인할 수 있다.

여담으로 노드의 할당할 수 있는 영역을 확인해보면 Kubernetes가 써야 하는 리소스와 시스템 리소스, eviction을 위한 영역을 제외한 부분을 Pod이 사용할 수 있는 영역으로 설정한 것을 볼 수 있다.

팟이 아무리 리소스를 많이 차지하더라도, k8s 시스템 자체에서 사용할 영역은 확보하고 있다는 의미이다. 재밌는 점은 이론적으로 봤을 때 k8s에서 사용할 리소스를 미리 할당해두기 때문에, 장애 상황에서 cpu가 100%가 되었을 때 컨테이너 ssh 접속이 안되는 문제 같은 것이 생기지 않는다는 의미가 된다. (k8s용 가용 리소스는 확보하고 있으므로)

쿠버네티스에는 compressible 리소스(이하 c리소스라고 적겠다)와 incompressible 리소스(ic리소스)가 있다. 전제는 압축할 수 있는 리소스인데, 컨테이너가 리소스를 필요로 할 때 사용할 수 있는 리소스가 없으면 기다릴 수 있다. cpu는 c리소스이고 k8s는 c리소스에 대해서는 스로틀링으로 대응한다. (사용량을 제어)
반대로 메모리는 ic리소스인데 필요한 메모리를 확보하지 못하면 OOM이 발생하면서 앱이 죽는다.

CPU Throttle이란?

CPU 스로틀링이라는 건 CPU Limit에 가까워지면 더더 제한된 리소스가 부여된다는 의미이다.

내가 이해한대로 좀 더 쉽게 설명해보자면 아래와 같다.
롯데월드에 아틀란티스를 타러 갔는데, 아틀란티스는 한번에 8명이서 탈 수 있다고 해보자. 그런데 9명이 타려고 한다면? 아틀란티스에는 8명만 탈 수 있으니 1명은 기다려야한다.
즉, k8s도 동일하게 각 노드는 한번에 처리할 수 있는 CPU 사용량이 정해져있다. 근데 파드들이 너무 많은 일을 하려고 하면, 일부 파드에게 잠깐 기다려라고 할 수 있다. 즉, 제한할 수 있다. 이렇게 제한된 상황을 CPU 스로틀이 발생했다고 설명할 수 있다.

만약 CPU 스로틀링이 발생하면, 파드는 일을 더 느리게 처리하게 된다. 더 제한된 리소스로 같은 양을 처리해야한다면 다 처리하지 못하게 될 수도 있는 등 일정 시간동안 처리할 수 있는 일의 양이 줄어들게 된다. 따라서 레이턴시가 발생할 수 있다.

(설명이 틀렸다면 댓글로 부탁드려요!ㅎㅎ)

다시 돌아와서 CPU Requests

위에서 spec.containers[].resources.requests.cpu 이렇게 설정할 수 있다고 했는데, 이는 CPU 단위로 지정하게 된다. 1000m은 1CPU를 의미한다. 이는 파드를 스케줄링하는 데에 사용되고 1000m으로 설정하면 노드 중 1 CPU의 여유가 있는 노드에 배치된다.

노드에 스케줄링 된 이후에는 CPU Share 라는 단위로 변환된다. 1000m을 할당했다면 1024를 곱해서 1024 * 1 로 1024 CPU Share가 된다. 이 값은 노드 내에서 스케줄링할 때 사용되는데 더 많은 share를 가진 프로세스에 CPU time을 할당하게 된다. (꽤나 어렵다..)

그럼 CPU limits는?

CPU limits는 spec.containers[].resources.limits.cpu로 설정할 수 있고 이는 컨테이너가 사용할 수 있는 CPU 리소스의 제한을 의미한다. 이 제한이 동작하는 방법은 cpu.cfs_period_uscpu.cfs_quota_us 두 파라미터를 봐야 알 수 있다.
전자는 CPU period의 기본 값으로 k8s에서는 100ms이다. (수정가능하나 거의 고정값)
후자는 1CPU의 단위인 100ms의 period_us에서 컨테이너가 어느 정도의 시간을 쓸 수 있는지에 대한 쿼터를 의미한다.
무슨 말인지 모르겠다!

예를 들어보자.
만약 여러 회의실 중 한 회의실을 사용하는데, cpu.cfs_period_us가 1hour라고 한다면, 1시간 이내에 몇 분을 사용할 수 있냐가 cpu.cfs_quota_use가 된다. 이는 전체 회의실의 몇 퍼센트를 쓰냐의 문제가 아니라 1시간 내에 몇 분을 사용하냐가 되고, 1시간이 지나면 쿼터는 다시 리셋된다. 1시간 사용 중 30분을 사용한다면 30분을 한번에 쓸 수도 있고, 10분씩 6번에 나눠서 쓸 수도 있다.

limits.cpu1000m 으로 설정하면 100ms가 쿼터가 된다. (쿼터는 100ms에서 1CPU를 사용할 수 있는 시간이 되므로) 만약 4개의 코어가 동시에 사용한다고 하면, 100ms를 한 코어당 25ms만 사용한 채로 쿼터를 소진할 수 있게 되고(25* 4 = 100) 각 코어당 나머지 75ms는 대기하게된다. (cpu throttling 비율이 75%)

CPU Limit을 해제하면?

CPU limit 설정을 제거하면, 해당 파드는 필요한 만큼의 CPU 자원을 사용할 수 있게 된다. 즉, 특정 파드는 노드에 남아있는 CPU 자원을 모두 사용할 수도 있다. 이로 인해 다른 파드들은 필요한 CPU 자원을 얻지 못할 수도 있다. 이는 시스템 전체의 성능을 저하시키고, 특히 CPU 자원이 많이 필요한 파드의 성능을 크게 저하시킬 수 있다. (왜? 특정 파드가 갑자기 CPU를 다 먹어버릴 수도 있으니깐)

그럼 limit이 있어 발생했던 스로틀링은 어떻게 될까?
우선 리밋이 사라지기 때문에 특정 limit을 초과하는 상황이 발생하지 않아 스로틀링이 발생하지 않게 된다. 하지만 위에서 언급했던 대로 특정 파드가 cpu 자원을 다 먹어버릴 수도 있는 문제가 발생할 수 있는게 가장 우려 포인트다. 근데 그럼 CPU 사용량이 높아질 때 제한을 걸어 파드 수를 늘려버린다면? 동적으로 파드 수가 조절된다면 상관없지 않을까? 그럼 limit을 해제해도 되지 않을까?
는 Horizontal Pod Autoscaler(HPA)와 관련된 이야기인데, 이건 다음 글에서 다뤄봐야겠다.

애매한 마무리;


레퍼런스

profile
Server Engineer

0개의 댓글