본문 바로가기
Devops/Kubernetes

[Kubernetes] 쿠버네티스의 컴퓨터 자원(CPU/Memory) 관리 및 제한 - 1

by dev_ss 2024. 2. 5.

쿠버네티스는 Namespace와 Cgroup을 통해 컨테이너의 격리된 환경을 구축하고 배포한다.

 

컨테이너를 생성할 때, 컴퓨터 자원의 할당의 제한이 선언되면 쿠버네티스의 Scheduler컨테이너가 생성되기에 알맞은 노드(컴퓨터 자원이 충족되는)를 선택한다.

 

※ 컨테이너는 CPU, Memory, Disk(FileSystem)와 네트워크, 프로세스 ID, GPU 등의 컴퓨터 리소스를 소비할 수 있다.

 

과거에는 쿠버네티스에서 Cgroups v1을 기반으로 컴퓨터 자원을 격리했는데, 쿠버네티스 1.22 버전을 시작으로 Cgroups v2를 이용하여 더 효율적으로 컴퓨터 자원에 대한 관리를 할 수 있게 되었다.

 

https://kubernetes.io/blog/2021/11/26/qos-memory-resources/

 

Quality-of-Service for Memory Resources

Authors: Tim Xu (Tencent Cloud) Kubernetes v1.22, released in August 2021, introduced a new alpha feature that improves how Linux nodes implement memory resource requests and limits. In prior releases, Kubernetes did not support memory quality guarantees.

kubernetes.io

 


 

1. 컴퓨터 자원(압축/비압축)

 

컴퓨터 자원은 압축이 가능한 자원과 압축이 불가능한 자원으로 나뉜다.

 

 

압축 가능 자원 :

 

압축이 가능한 자원이란, CPU와 네트워크 대역폭과 같은 자원을 뜻하는데, 자원의 사용량이 최대치에 달했을 때, 이 자원을 필요로 하는 프로세스는 자원을 사용할 수 있을 때까지 대기해야 한다는 것을 의미한다.

 

즉, 프로세스를 제한하여 자원을 사용하는 것이다.

 

 

 

압축 불가능 자원 :

 

압축이 불가능한 자원은 Memory와 PID 등의 컴퓨터 자원이 압축 불가능 자원에 속하는데, 압축 가능 자원은 프로세스의 대기를 통하여 컴퓨터 자원을 이용하는 반면, 압축 불가능 자원은 타 프로세스에서 사용 중인 자원의 점유를 해제하고 새 프로세스가 요구하는 자원을 확보한다.

 

새 프로세스를 위하여 기존 프로세스를 종료하게 된다는 것이다.

 

 

※ 쿠버네티스가 관리하는 압축 가능한 자원은 CPU이고, 다른 관리하는 자원(메모리, 임시 스토리지, PID 등)들은 모두 압축이 불가능하다.

 


 

2. 쿠버네티스의 자원 제한 정책

 

아래는 쿠버네티스에서 컴퓨터 자원이 제한된 컨테이너가 있는 파드를 생성하는 예시 yaml이다.

apiVersion: v1
kind: Pod
metadata:
  name: test
spec:
  containers:
  - name: nginx
    resources:
      requests:
        memory: "128Mi"
        cpu: "500m"
      limits:
        memory: "128Mi"
        cpu: "1000m"

 

 

Requests :

 

Requests(CPU, Memory)는 스케줄링을 위해 설계되었는데, 파드를 생성하면 쿠버네티스 스케줄러는 파드가 실행될 노드를 선택하게 된다.

 

각 노드에는 각 자원의 유형에 대한 최대 용량이 있고, 스케줄러는 각 자원의 유형에 대하여 예약된 컨테이너의 리소스 요청 합계가 노드 총량보다 작도록 보장하도록 동작한다.

 

 

 

Limits (Cgroup v1) :

 

Limits는 kubelet이 컨테이너를 시작할 때 컨테이너 런타임에 전달되는데 CPU와 Memory는 Limits에 도달 시 각 방식으로 처리하였다.

 

CPU는 cgroup 버전과 상관없이 "압축 가능한" 자원으로 취급되어 앱이 CPU 제한(Limit)에 도달하기 시작하면 쿠버네티스는 컨테이너를 제한하기 시작하여 앱의 성능이 잠재적으로 저하되나 프로세스가 종료되지는 않는다.

 

Memory는 cgroup v1에선 실제로 메모리를 압축할 수 없었고, 메모리 사용량을 조절할 수 있는 방법도 없었기에 컨테이너가 메모리 제한(Limits)을 초과하면 커널에 의한 OOM(Out Of Memory) 처리로 프로세스가 종료되었다.

 

-> cgroup v2 메모리를 완벽하게 보호하기 위한 새로운 디자인을 기반으로 OOM으로 인한 프로세스 종료와는 다른 방식으로 구현하였다.

 


 

3. Cgroupv1에서 Cgroup v2로

 

위 방식으로 cgroup v1에서는 쿠버네티스 자원의 제한과 그에 대한 관리를 볼 수 있었는데, 메모리와 관련된 관리는 OOM(Out Of Memory)로 프로세스가 종료되었으나, cgroup v2에서는 새로운 방식으로 자원을 관리하였다.

 

메모리 QoS(Quality of Service)는 cgroup v2의 메모리 컨트롤러를 사용하여 쿠버네티스의 메모리 자원을 보장하는데, 아래 사진이 해당 개념을 나타낸 것이다.

 

[출처 : https://kubernetes.io/blog/2021/11/26/qos-memory-resources/]

 

 

메모리 컨트롤러는 특정 인터페이스를 통하여  최저 메모리(memory.min) 및 최고 메모리(memory.high)를 설정하고, 이를 이용하여 파드 내 컨테이너의 메모리 요청(Requests)과 제한(Limits)을 구현한 것이다.

 


메모리의 요청(Requests)이 이루어질 때, memory.min도 함께 설정이 되는데, 커널로 회수되지 않을 메모리의 예약이 이루어진다.

 

이 방법을 통하여 메모리 QoS로 쿠버네티스 파드의 메모리 가용성을 보장한다.

 

 

 

컨테이너에 메모리 제한(Limits)은, 메모리 QoS는 시스템이 컨테이너가 사용하고 있는 메모리 사용량을 제한하게 된다는 것이다.

 

메모리 제한(Limits)에 접근하는 작업량을 조절하기 위해 memory.high를 설정하고, 시스템이 일시적으로 제한된 메모리 할당을 초과하지 않도록 제어한다.

 

  • Memory.min : memory.mincgroup는 항상 보유해야 하는 최소 메모리 양, 즉 시스템이 결코 회수할 수 없는 메모리 양을 지정한다.
    • cgroup의 메모리 사용량이 이 하한에 도달하여 늘릴 수 없는 경우 시스템 OOM 킬러가 호출된다.
  • Memory.high : memory.high는 메모리 사용량의 조절(Throttle) 상한선으로, cgroup의 메모리 사용을 제어하는 ​​주요 메커니즘이 된다.
    • cgroup의 메모리 사용량이 여기에 지정된 상한을 초과하면 cgroup의 프로세스가 제한되어 회수 압력이 커진다..
    • 기본값은 max이며, 이는 제한이 없는 것이다. 

 

 

 

반응형