기록/Kubenetes

Kubernetes (9)

YongE 2025. 4. 21. 14:26

스토리지와 로깅/모니터링 시스템


쿠버네티스 스토리지 시스템

쿠버네티스에서 영구적인 데이터 저장을 위해 PV(Persistent Volume)와 PVC(Persistent Volume Claim)를 사용한다. 이러한 시스템은 컨테이너가 재시작되거나 파드가 이동되어도 데이터가 유지될 수 있도록 해준다.

PV와 PVC 생성 방법

PV를 생성하는 방법에는 여러 가지가 있으며, 각 방법은 다양한 사용 사례에 맞게 설계되어 있다.

  1. 정적 프로비저닝(Static Provisioning)
    • 클러스터 관리자가 직접 PV를 생성하고 PVC와 연결하는 방식이다.
    • PV는 쿠버네티스 API에 저장되며, 클러스터 사용자가 사용할 수 있는 스토리지 리소스 정보를 포함한다.
    • 관리자는 미리 특정 용량의 PV를 생성해두고, 사용자의 PVC 요청이 있을 때 해당 PV를 할당한다.
  2. 스토리지 클래스를 그룹핑 개념으로 사용
    • PVC를 생성할 때 스토리지 클래스를 지정하면, 해당 그룹에 속한 PV 중에서 요청 스펙에 맞는 것과 자동으로 연결된다.
    • 이 방식은 비슷한 특성을 가진 스토리지 리소스를 효율적으로 관리할 수 있게 해준다.
  3. 동적 프로비저닝(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는 다음과 같은 라이프사이클을 가진다

  1. 프로비저닝(Provisioning): 스토리지를 생성하는 과정
  2. 바인딩(Binding): PV와 PVC가 서로 연결되는 과정
  3. 사용(Using): 파드가 PVC를 통해 PV를 사용하는 단계
  4. 회수(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

이 예제는 로컬 볼륨을 생성하며, persistentVolumeReclaimPolicyRetain으로 설정되어 있어 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 프로비저너 설정 과정이다

  1. PV를 동적 배포할 클러스터 생성
  2. kubectl 제어 설정 수행
  3. Dynamic Volume Provisioning 설정
    • YAML 파일 또는 Helm을 사용하여 CSI Provisioner 배포

로깅과 모니터링 시스템

쿠버네티스는 기본적으로 내장된 로깅 및 모니터링 시스템이 없어 Cloud Native 생태계의 다양한 도구를 활용한다.

로깅 시스템의 필요성

쿠버네티스에서 kubectl logs 명령어로 컨테이너 로그를 확인할 수 있지만, 클러스터 레벨의 로깅 시스템이 필요한 이유는 다음과 같다

  1. 로그 히스토리 저장
    • 파드가 종료되거나 1회성 배치 작업인 경우 로그가 삭제되는 문제를 해결
    • 과거 로그 기록 확인 가능
  2. 시스템 컴포넌트 로그 통합
    • 쿠버네티스 시스템 컴포넌트(kubelet 등)의 로그도 통합 관리 가능
  3. 범용 로깅 플랫폼
    • 개발자마다 로깅 기능을 따로 구현할 필요 없음
    • 통일된 인터페이스로 로그 확인 가능

로깅 아키텍처

[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

클러스터 레벨 로깅

클러스터 내 모든 노드의 로그를 포함하는 로깅 구조로, 주로 다음 방식을 사용한다

  1. 노드 로깅 에이전트
    • 각 노드에 로깅 에이전트를 데몬셋으로 배포하여 로그 수집
    • fluentd, fluent-bit, promtail 등의 도구 사용
  2. 사이드카 컨테이너 스트리밍
    • 파드 내에 로그 수집용 사이드카 컨테이너를 함께 배포
    • 메인 컨테이너의 로그를 중앙 로깅 시스템으로 전송

로깅 및 모니터링 스택

PLG 스택

[Pod]
  |
  v
[stdout/stderr]
  |
  v
[Promtail (DaemonSet)]
  |
  v
[Loki (Log DB)]
  |
  v
[Grafana (Dashboard)]

PLG는 Promtail, Loki, Grafana의 조합으로 구성된 로그 통합 시스템이다.

  1. Loki

    • 로그 저장 및 쿼리 엔진
    • 전체 로그 파일을 인덱싱하지 않고 레이블 기반 메타데이터만 인덱싱하여 자원 사용량이 적음
    • LogQL 쿼리 언어를 제공하여 원하는 로그를 빠르게 조회 가능
    # Loki 설치 예제 (Helm 사용)
    persistence:
      enabled: true
      size: 20Gi
    serviceMonitor:
      enabled: true
  2. Promtail

    • 데몬셋으로 실행되어 모든 노드에 자동으로 설치
    • 각 노드에서 발생하는 로그를 중앙의 Loki 서버로 전송하는 에이전트 역할
    # Promtail 설치 예제 (Helm 사용)
    serviceMonitor:
      enabled: true
    config:
      serverPort: 3101
      clients:
        - url: http://loki-headless:3100/loki/api/v1/push
  3. Grafana

    • 로그 데이터 시각화 인터페이스 제공
    • 대시보드를 통해 다양한 로그 분석 도구 제공

ELK/EFK 스택

[Pod]
  |
  v
[stdout/stderr]
  |
  v
[Fluentd/FluentBit (DaemonSet)]
  |
  v
[Elasticsearch (Log DB)]
  |
  v
[Kibana (Dashboard)]

ELK/EFK 스택은 Elasticsearch, Logstash/Fluentd, Kibana로 구성된 또 다른 인기 있는 로깅 솔루션이다.

  1. Elasticsearch
    • 텍스트 검색에 최적화된 오픈소스 검색 엔진
    • JSON 형식으로 데이터를 저장하여 비정형 데이터 처리에 유리
    • 클러스터로 구성하여 확장성 제공
  2. Fluentd/Fluent-bit
    • 로그 수집 및 전송 도구
    • Fluent-bit는 Fluentd의 경량 버전
  3. Kibana
    • Elasticsearch의 데이터를 시각화하는 웹 인터페이스

비용 효율적인 로깅 전략

로깅 시스템을 운영할 때 비용이 급증할 수 있으므로 다음과 같은 전략이 필요하다

  1. 로그 보존 기간 최적화
    • 7일 이상의 로그는 콜드 스토리지로 이동
    • 대부분의 문제는 7일 이내의 로그로 찾을 수 있음
  2. 샘플링 및 필터링
    • 모든 로그를 수집하지 않고 중요한 정보만 선택적으로 저장
    • 대부분의 경우 로드 밸런서에서 상태 코드와 타임아웃을 로깅하는 것으로 95%의 문제 해결 가능
  3. 오픈소스 도구 활용
    • Datadog, New Relic 같은 상용 솔루션보다 Prometheus, Loki, OpenTelemetry 등의 오픈소스 도구 활용
    • 비용을 약 1/4로 줄일 수 있는 사례도 있음

효율적인 클러스터 구성

로깅과 모니터링을 효율적으로 구성하기 위한 클러스터 아키텍처 전략은 다음과 같다

네임스페이스 분리

  1. 팀별 네임스페이스 분리
    • 각 팀이 자신의 애플리케이션을 관리할 수 있도록 별도 네임스페이스 제공
    • RBAC 규칙을 단순화하여 보안 강화
  2. 로깅/모니터링 중앙화
    • 모니터링(Prometheus, Grafana)은 클러스터 전체에서 중앙화
    • 로깅은 중앙 시스템으로 통합하거나 팀별로 분리할 수 있음

전용 노드 활용

  1. 모니터링용 전용 노드
    • 대용량 디스크를 가진 전용 노드에 모니터링 및 로깅 도구 배치
    • Taint를 사용하여 PLG 스택만 해당 노드에서 실행되도록 설정
  2. 프로덕션 환경 분리
    • 개발 및 프로덕션 환경을 별도 클러스터로 분리
    • 클러스터 변경사항을 프로덕션에 적용하기 전에 테스트할 수 있는 공간 확보
728x90
반응형

'기록 > 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