5.2 리소스 관리
Kubernetes는 노드의 CPU·메모리를 여러 Pod가 나눠 쓴다. 이 자원을 어떻게 요청하고 어디까지 쓸 수 있는지 명시하지 않으면, 한 Pod가 자원을 독점하거나 노드가 메모리 부족에 빠졌을 때 PostgreSQL Pod가 먼저 종료되는 일이 벌어진다. CloudNativePG는 두 가지 값으로 이를 통제한다. requests는 스케줄러가 Pod를 배치할 때 확보하는 최소 자원이고, limits는 Pod가 넘을 수 없는 상한이다.
resources:
requests:
memory: "32Mi"
cpu: "50m"
limits:
memory: "128Mi"
cpu: "100m"CPU 단위 50m은 1 코어의 1000분의 50, 즉 0.05 코어를 뜻한다. 메모리 Mi는 메비바이트다. requests만 있으면 상한이 없어 다른 Pod를 압박할 수 있고, limits만 있으면 스케줄러가 자원을 미리 확보하지 못한다. 둘을 함께 쓰는 것이 기본이다.
QoS class
Kubernetes는 Pod에 지정된 requests·limits 조합에 따라 Quality of Service(QoS) class를 자동으로 매긴다. 노드가 메모리 부족(OOM)에 빠지면 이 등급이 낮은 Pod부터 축출된다.
flowchart TD
START[requests·limits 확인] --> Q1{requests=limits<br/>메모리·CPU 모두}
Q1 -->|예| G[Guaranteed]
Q1 -->|아니오| Q2{requests 또는<br/>limits 존재}
Q2 -->|예| B[Burstable]
Q2 -->|아니오| BE[BestEffort]
세 등급의 우선순위는 다음과 같다.
| QoS class | 조건 | OOM 시 축출 순위 |
|---|---|---|
| Guaranteed | 메모리·CPU의 requests와 limits가 서로 같음 | 가장 나중 |
| Burstable | requests나 limits 중 일부만 지정 | 중간 |
| BestEffort | requests·limits 모두 없음 | 가장 먼저 |
PostgreSQL 워크로드에는 Guaranteed가 권장된다. 메모리와 CPU 각각에서 requests와 limits를 동일한 값으로 맞추면 이 등급이 된다.
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: postgresql-resources
spec:
instances: 3
postgresql:
parameters:
shared_buffers: "256MB"
resources:
requests:
memory: "1024Mi"
cpu: 1
limits:
memory: "1024Mi"
cpu: 1
storage:
size: 1GiPG_OOM_ADJUST_VALUE를 0으로 설정한다. 그러면 OOM 상황에서 postmaster보다 자식 프로세스가 먼저 종료되므로, 인스턴스 자체는 살아남아 깨끗하게 셧다운할 여지를 남긴다.메모리 산정과 shared_buffers
PostgreSQL의 shared_buffers는 공유 버퍼 캐시 크기다. 관례적으로 Pod 전체 메모리의 25% 안팎으로 잡는다. 위 예시처럼 메모리 limits가 1024Mi라면 shared_buffers는 256MB가 적당하다. 나머지 메모리는 work_mem·maintenance_work_mem, 그리고 운영체제 페이지 캐시가 나눠 쓴다.
정리하면 다음을 지킨다.
- 메모리·CPU의 requests와 limits를 같은 값으로 맞춰 Guaranteed QoS를 확보한다.
shared_buffers는 Pod 메모리의 약 25%로 시작해 워크로드에 맞게 조정한다.- requests/limits를 명시해
OOMKilled와 CPU throttling을 예방한다. - 전용 노드가 필요하면
nodeSelector로 Pod 배치를 제한한다(5.4에서 다룬다).
hugepages
hugepages는 리눅스가 메모리를 관리하는 페이지의 크기를 기본 4KB보다 크게(예: 2MB) 잡는 기능이다. PostgreSQL처럼 큰 공유 메모리를 다루는 프로세스는 페이지 테이블 오버헤드가 줄어 성능이 좋아진다. Kubernetes에서는 hugepages도 하나의 자원이므로 resources에 명시하고, 노드에 미리 hugepages가 예약되어 있어야 한다.
spec:
instances: 3
postgresql:
parameters:
shared_buffers: "256MB"
resources:
requests:
memory: "1024Mi"
cpu: 1
hugepages-2Mi: "512Mi"
limits:
memory: "1024Mi"
cpu: 1
hugepages-2Mi: "512Mi"huge_pages 파라미터를 try로 두면 hugepages 확보에 실패해도 일반 페이지로 기동을 이어 간다.오토스케일러 연동
- Vertical Pod Autoscaler(VPA): CNPG는 권고 전용 모드(
updateMode: Off)에서만 VPA와 함께 쓴다. VPA가 제안한 값은 DBA가 직접 Cluster 매니페스트에 반영한다. - Horizontal Pod Autoscaler(HPA): PostgreSQL 클러스터에는 권장하지 않는다. 인스턴스를 늘려도 standby replica만 추가될 뿐 primary의 쓰기 부하는 줄지 않기 때문이다.
Auto·Recreate·Initial 모드로 CNPG 클러스터에 붙이지 않는다. Operator는 spec.resources를 유일한 기준(source of truth)으로 삼기 때문에, VPA가 Pod 스펙에 직접 써넣은 값을 받아들이지 않는다.