스토리지와 로깅/모니터링 시스템
쿠버네티스 스토리지 시스템
쿠버네티스에서 영구적인 데이터 저장을 위해 PV(Persistent Volume)와 PVC(Persistent Volume Claim)를 사용한다. 이러한 시스템은 컨테이너가 재시작되거나 파드가 이동되어도 데이터가 유지될 수 있도록 해준다.
PV와 PVC 생성 방법
PV를 생성하는 방법에는 여러 가지가 있으며, 각 방법은 다양한 사용 사례에 맞게 설계되어 있다.
- 정적 프로비저닝(Static Provisioning)
- 클러스터 관리자가 직접 PV를 생성하고 PVC와 연결하는 방식이다.
- PV는 쿠버네티스 API에 저장되며, 클러스터 사용자가 사용할 수 있는 스토리지 리소스 정보를 포함한다.
- 관리자는 미리 특정 용량의 PV를 생성해두고, 사용자의 PVC 요청이 있을 때 해당 PV를 할당한다.
- 스토리지 클래스를 그룹핑 개념으로 사용
- PVC를 생성할 때 스토리지 클래스를 지정하면, 해당 그룹에 속한 PV 중에서 요청 스펙에 맞는 것과 자동으로 연결된다.
- 이 방식은 비슷한 특성을 가진 스토리지 리소스를 효율적으로 관리할 수 있게 해준다.
- 동적 프로비저닝(Dynamic Provisioning)
- StorageClass를 사용하여 PVC 요청 시 자동으로 PV를 생성하는 방식이다.
- PVC가 요청되면 프로비저너(Provisioner)가 적절한 PV를 동적으로 생성하고 연결한다.
- 이 방식은 일반적으로 사용 가능한 정적 PV가 PVC와 일치하지 않을 때 발생한다.
[StorageClass] [StorageClass] [StorageClass]
| | |
v v v
[Provisioner] [Provisioner] [Provisioner]
| | |
v v v
[PersistentVolume] [PersistentVolume] [PersistentVolume]
| | |
v v v
[PersistentVolumeClaim] (PVC) <------> [Pod]
- 정적 프로비저닝: [PersistentVolume]를 미리 생성 → [PersistentVolumeClaim]이 직접 연결
- 스토리지 클래스 그룹핑: [StorageClass] 지정 → 해당 그룹 내 PV와 자동 매칭
- 동적 프로비저닝: [StorageClass] + [Provisioner] → PVC 요청 시 PV 자동 생성
PV 라이프사이클
PV는 다음과 같은 라이프사이클을 가진다
- 프로비저닝(Provisioning): 스토리지를 생성하는 과정
- 바인딩(Binding): PV와 PVC가 서로 연결되는 과정
- 사용(Using): 파드가 PVC를 통해 PV를 사용하는 단계
- 회수(Reclaiming): 사용이 끝난 PV의 데이터를 어떻게 처리할지 결정하는 단계
바인딩 상태의 종류
- Available: 사용 가능한 상태이며 아직 바인딩되지 않음
- Bound: PVC와 매칭되어 바인딩이 완료된 상태
- Released: 사용자가 PVC를 삭제했지만 아직 클러스터에 의해 재요청되지 않은 상태
- Failed: 자동으로 클러스터에 의해 재요청될 수 없는 상태
스토리지 클래스 예제 코드
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: my-storage
namespace: storage
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
이 스토리지 클래스는 볼륨 바인딩 모드를 WaitForFirstConsumer
로 설정하여 파드가 실제로 사용하기 전까지는 볼륨 바인딩을 수행하지 않도록 한다.
PV 예제 코드
apiVersion: v1
kind: PersistentVolume
metadata:
name: my-pv
namespace: storage
spec:
storageClassName: my-storage
capacity:
storage: 5Gi
local:
path: /Users/1111489/Documents/01.STUDY/KUBE/local-storage
persistentVolumeReclaimPolicy: Retain
accessModes:
- ReadWriteOnce
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- node1
이 예제는 로컬 볼륨을 생성하며, persistentVolumeReclaimPolicy
가 Retain
으로 설정되어 있어 PVC가 삭제되어도 데이터가 유지된다.
PVC 예제 코드
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-pvc
namespace: storage
spec:
accessModes:
- ReadWriteOnce
storageClassName: my-storage
resources:
requests:
storage: 200Mi
이 PVC는 200Mi의 스토리지를 요청하고 있으며, my-storage
스토리지 클래스를 사용한다.
스토리지 타입
쿠버네티스에서 사용할 수 있는 주요 스토리지 유형에는 파일 스토리지, 오브젝트 스토리지, 블록 스토리지가 있다.
파일 스토리지
파일 스토리지는 가장 일반적인 저장소 유형 중 하나로, 데이터를 폴더와 파일의 계층 구조로 저장한다.
- 사용자가 익숙한 파일/폴더 형태로 데이터 관리가 가능하다.
- 메타데이터는 생성 날짜, 수정 날짜, 파일 크기 등으로 제한적이다.
- 데이터 양이 증가하면 파일 시스템 추적에 자원 요구가 증가하여 성능이 저하될 수 있다.
- 일반적으로 하드 드라이브와 NAS(Network Attached Storage) 시스템에서 주로 사용된다.
오브젝트 스토리지
오브젝트 스토리지는 데이터를 '오브젝트'라 불리는 개별 단위로 저장하는 방식이다.
- 폴더 계층 구조 없이 단일 평면 구조로 저장된다.
- 각 오브젝트는 PDF, 비디오, 오디오, 텍스트 등 다양한 데이터 유형이 될 수 있다.
- 모든 기본 및 사용자 정의 메타데이터는 오브젝트 자체에 저장되어 색인과 접근이 용이하다.
- 클라우드 기반 저장소에서 일반적으로 사용되며, 높은 확장성과 신뢰성을 제공한다.
- 오브젝트 이름이 색인 테이블의 '키' 역할을 하여 빠른 검색이 가능하다.
블록 스토리지
블록 스토리지는 데이터를 고정된 크기의 '블록'으로 처리하는 방식이다.
- 데이터 파일을 여러 블록으로 분산 저장할 수 있다.
- 각 블록은 고유 주소를 가지며 서로 독립적으로 존재한다.
- 데이터를 빠르게 검색할 수 있으며, 블록이 인접하지 않아도 효율적으로 저장 가능하다.
- 일반적으로 SAN(Storage Area Network) 저장소에 배치된다.
- 특정 노드에 스토리지를 마운트하는 개념으로 사용된다.
- 일반적으로 고가이며 메타데이터 처리 능력이 제한적이어서 애플리케이션 수준에서 처리해야 한다.
스토리지 타입 비교 표
스토리지 타입 | 저장 구조 | 주요 특징 | 사용 예시 |
---|---|---|---|
파일 스토리지 | 계층적(폴더/파일) | 메타데이터 제한, 파일 단위 관리 | NAS, 일반 파일 서버 |
오브젝트 스토리지 | 평면(오브젝트) | 메타데이터 풍부, 키 기반 색인 | AWS S3, 클라우드 백업 |
블록 스토리지 | 블록 단위 | 고성능, 특정 노드 마운트, 메타데이터 제한 | SAN, 데이터베이스, VM 디스크 |
CSI(Container Storage Interface)
CSI는 쿠버네티스에서 다양한 스토리지 시스템을 통합하기 위한 표준 인터페이스다. 카카오클라우드 같은 서비스에서는 CSI 프로비저너를 통해 블록 스토리지를 영구 볼륨으로 사용할 수 있도록 지원한다.
CSI 프로비저너를 설정하면 간단하게 PVC를 생성하여 영구 볼륨을 생성할 수 있다. 다음은 CSI 프로비저너 설정 과정이다
- PV를 동적 배포할 클러스터 생성
- kubectl 제어 설정 수행
- Dynamic Volume Provisioning 설정
- YAML 파일 또는 Helm을 사용하여 CSI Provisioner 배포
로깅과 모니터링 시스템
쿠버네티스는 기본적으로 내장된 로깅 및 모니터링 시스템이 없어 Cloud Native 생태계의 다양한 도구를 활용한다.
로깅 시스템의 필요성
쿠버네티스에서 kubectl logs
명령어로 컨테이너 로그를 확인할 수 있지만, 클러스터 레벨의 로깅 시스템이 필요한 이유는 다음과 같다
- 로그 히스토리 저장
- 파드가 종료되거나 1회성 배치 작업인 경우 로그가 삭제되는 문제를 해결
- 과거 로그 기록 확인 가능
- 시스템 컴포넌트 로그 통합
- 쿠버네티스 시스템 컴포넌트(kubelet 등)의 로그도 통합 관리 가능
- 범용 로깅 플랫폼
- 개발자마다 로깅 기능을 따로 구현할 필요 없음
- 통일된 인터페이스로 로그 확인 가능
로깅 아키텍처
[Application Pod]
|
|---> [stdout/stderr]
| |
| v
| [Node-level Agent (DaemonSet)]
| |
| v
| [Centralized Log Store]
| |
| v
| [Visualization/Query Tool]
|
|---> [Sidecar Container] (옵션)
|
v
[stdout/stderr or File]
노드 레벨 로깅
단일 노드 내에서 발생하는 로그를 관리하는 구조다. 도커 컨테이너의 로그는 호스트 서버의 특정 디렉터리에 저장된다
/var/lib/docker/containers//-json.log
클러스터 레벨 로깅
클러스터 내 모든 노드의 로그를 포함하는 로깅 구조로, 주로 다음 방식을 사용한다
- 노드 로깅 에이전트
- 각 노드에 로깅 에이전트를 데몬셋으로 배포하여 로그 수집
- fluentd, fluent-bit, promtail 등의 도구 사용
- 사이드카 컨테이너 스트리밍
- 파드 내에 로그 수집용 사이드카 컨테이너를 함께 배포
- 메인 컨테이너의 로그를 중앙 로깅 시스템으로 전송
로깅 및 모니터링 스택
PLG 스택
[Pod]
|
v
[stdout/stderr]
|
v
[Promtail (DaemonSet)]
|
v
[Loki (Log DB)]
|
v
[Grafana (Dashboard)]
PLG는 Promtail, Loki, Grafana의 조합으로 구성된 로그 통합 시스템이다.
Loki
- 로그 저장 및 쿼리 엔진
- 전체 로그 파일을 인덱싱하지 않고 레이블 기반 메타데이터만 인덱싱하여 자원 사용량이 적음
- LogQL 쿼리 언어를 제공하여 원하는 로그를 빠르게 조회 가능
# Loki 설치 예제 (Helm 사용) persistence: enabled: true size: 20Gi serviceMonitor: enabled: true
Promtail
- 데몬셋으로 실행되어 모든 노드에 자동으로 설치
- 각 노드에서 발생하는 로그를 중앙의 Loki 서버로 전송하는 에이전트 역할
# Promtail 설치 예제 (Helm 사용) serviceMonitor: enabled: true config: serverPort: 3101 clients: - url: http://loki-headless:3100/loki/api/v1/push
Grafana
- 로그 데이터 시각화 인터페이스 제공
- 대시보드를 통해 다양한 로그 분석 도구 제공
ELK/EFK 스택
[Pod]
|
v
[stdout/stderr]
|
v
[Fluentd/FluentBit (DaemonSet)]
|
v
[Elasticsearch (Log DB)]
|
v
[Kibana (Dashboard)]
ELK/EFK 스택은 Elasticsearch, Logstash/Fluentd, Kibana로 구성된 또 다른 인기 있는 로깅 솔루션이다.
- Elasticsearch
- 텍스트 검색에 최적화된 오픈소스 검색 엔진
- JSON 형식으로 데이터를 저장하여 비정형 데이터 처리에 유리
- 클러스터로 구성하여 확장성 제공
- Fluentd/Fluent-bit
- 로그 수집 및 전송 도구
- Fluent-bit는 Fluentd의 경량 버전
- Kibana
- Elasticsearch의 데이터를 시각화하는 웹 인터페이스
비용 효율적인 로깅 전략
로깅 시스템을 운영할 때 비용이 급증할 수 있으므로 다음과 같은 전략이 필요하다
- 로그 보존 기간 최적화
- 7일 이상의 로그는 콜드 스토리지로 이동
- 대부분의 문제는 7일 이내의 로그로 찾을 수 있음
- 샘플링 및 필터링
- 모든 로그를 수집하지 않고 중요한 정보만 선택적으로 저장
- 대부분의 경우 로드 밸런서에서 상태 코드와 타임아웃을 로깅하는 것으로 95%의 문제 해결 가능
- 오픈소스 도구 활용
- Datadog, New Relic 같은 상용 솔루션보다 Prometheus, Loki, OpenTelemetry 등의 오픈소스 도구 활용
- 비용을 약 1/4로 줄일 수 있는 사례도 있음
효율적인 클러스터 구성
로깅과 모니터링을 효율적으로 구성하기 위한 클러스터 아키텍처 전략은 다음과 같다
네임스페이스 분리
- 팀별 네임스페이스 분리
- 각 팀이 자신의 애플리케이션을 관리할 수 있도록 별도 네임스페이스 제공
- RBAC 규칙을 단순화하여 보안 강화
- 로깅/모니터링 중앙화
- 모니터링(Prometheus, Grafana)은 클러스터 전체에서 중앙화
- 로깅은 중앙 시스템으로 통합하거나 팀별로 분리할 수 있음
전용 노드 활용
- 모니터링용 전용 노드
- 대용량 디스크를 가진 전용 노드에 모니터링 및 로깅 도구 배치
- Taint를 사용하여 PLG 스택만 해당 노드에서 실행되도록 설정
- 프로덕션 환경 분리
- 개발 및 프로덕션 환경을 별도 클러스터로 분리
- 클러스터 변경사항을 프로덕션에 적용하기 전에 테스트할 수 있는 공간 확보
'기록 > Kubenetes' 카테고리의 다른 글
Kubernetes (8) (0) | 2025.04.21 |
---|---|
Kubernetes (7) (0) | 2025.04.17 |
Kubernetes (6) (0) | 2025.04.16 |
Kubernetes (5) (1) | 2025.04.15 |
Kubernetes (4) (0) | 2025.04.14 |