[Ceph] Custom Container 배포를 해보자! (+Prometheus 연동)

2025. 11. 26. 23:47·dev/Ceph
반응형

RBD 이미지 -> PG -> OSD 매핑

Ceph 클러스터를 운영하다 보면 장애 분석이나 성능·용량 이슈가 생겼을 때,“지금 보고 있는 RBD 이미지가 실제로 어떤 PG에 올라가 있고, 그 PG가 어떤 OSD 들에 퍼져 있는지”를 알고 싶은 순간이 생겼습니다. 

예를 들어,

1. 특정 OSD 장애가 발생했을 때, 그 OSD에 어떤 이미지가 얼마나 몰려 있는지 보고 싶거나

2. 리밸런싱 이후 데이터가 의도대로 고르게 분산됐는지 확인하고 싶은경우

 

"Ceph 내부에서는 객체 이름과 풀 ID로 해시해서 PG를 계산하고 이 PG를 다시 CRUSH로 여러 OSD에 배치를 하게 됩니다."

그래서 저는 go-cpeh(librados를 go 언어로 래핑한 오픈소스)를 사용하여 RBD 이미지 -> PG -> OSD 매핑 API 개발을 진행했습니다.

 

이후 해당 관련 내용은 다음 포스팅에서 다루도록 하겠습니다!

Ceph MGR Module vs Custom Container

Ceph MGR Module

MGR Module: https://docs.ceph.com/en/latest/mgr/modules/

 

개요

- Ceph-Mgr 데몬 내부에 동작하는 Python 기반의 플러그인 모듈

- Python으로 MgrModule 클래스를 상속 받아서 구현해야 하며, serve(), notify(), handler_command()등의 메소드를 오버라이드 구현이 필요

 

장점

- Ceph 클러스터 내부 데이터(모니터, OSD, PG 등) 밀접하게 연동하여 기능 확장이 가능

- ceph mgr module enable <my_module> 로 활성화 가능

Custom Container

Custom Conatainer: https://docs.ceph.com/en/reef/cephadm/services/custom-container/

 

        [Ceph MON / MGR / OSD]                [Custom Service (go-ceph API)]
                 (Core Ceph)                        (독립 컨테이너)
                       │                                   │
                       └────── Ceph Protocols ──────┬──────┘
                                 (librados, REST 등)

 

- Ceph 클러스터 내부에서 배포되지만, Ceph의 핵심 데몬 (OSD, MON, MGR등)에 직접 속하지 않는 독립 실행형 컨테이너를 의미

- Cephadm이 이서비스를 container 단위로 배포하고, 운영 관리를 도와주는 형태이지 Ceph 데몬처럼 클러스터의 핵심 구성요소는 아님

개요

- Ceph 크러스터 외부에 독립 실행형 컨테이너 서비스를 배포할 수 있는 기능

- ceph orch apply 명령으로 배포하고 Ceph-orchestrator가 lifecycle을 관리

 

주요 특징

- Ceph core 역할은 아니지만 Ceph 프로토콜(librados, REST)로 클러스터와 느슨하게 연결 (loose coupling)

- 배포는 원하는 노드에 자유롭게, cephadm orchestrator가 관리

 

Ceph-MGR Module vs Custom Container Servcie

항목 MgrModule Custom Container Service
실행 위치 Ceph‑Mgr 데몬 내부 독립 실행 컨테이너
언어 제약 Python only 언어 제한 없음 (Go, Java, Python 등)
클러스터와 연동도 매우 밀접 (내부 기능) 느슨한 결합 (REST, librados 등 사용)
배포 대상 모든 mgr 노드 지정한 노드에 선택 배포
관리 주체 Ceph‑Mgr 데몬 cephadm orchestrator
라이프사이클 관리 ceph mgr module enable/disable ceph orch apply/update/remove

 

선택 배경 및 결정 이유

이번에 개발한 API는 go-ceph 기반으로 구현하였으며, Ceph 클러스터 내부의 상태 정보를 활용하는 구조입니다. 이 기능을 실 서비스 환경에 통합하기 위해 처음에는 Ceph-MGR Module을 고려했습니다. MGR Module은 Ceph 클러스터 내부 기능과 밀접하게 연동할 수 있다는 점에서 매력적이었지만, 몇 가지 현실적인 제약이 있었습니다.

 

첫 번째로, MGR Module은 Python 기반으로만 개발할 수 있으며, ceph-mgr 데몬 내부에서 동작하기 때문에 실제 Ceph 환경이 갖춰진 상태에서만 테스트가 가능합니다. 이로 인해 개발 및 디버깅 속도가 느려지고, 개발 환경 구축이 까다롭습니다.

 

두 번째로, 저희는 cephadm 기반으로 클러스터를 운영하고 있는데, 이 환경에서는 mgr 데몬이 컨테이너로 실행되므로, 직접 소스 파일을 수정하거나 테스트하는 데 제약이 따릅니다. 예를 들어, 새로운 mgr 모듈을 반영하려면 컨테이너에 볼륨 마운트 설정을 추가하거나 재시작해야 하고, ceph mgr module enable/disable 과정을 반복해야 합니다.

 

이러한 이유들로 인해 결국 Custom Container Service를 선택하게 되었습니다. Custom Container는 Ceph 클러스터 외부에서 독립적으로 동작하는 서비스이기 때문에, 언어나 프레임워크에 제한이 없고, 개발 및 테스트도 로컬에서 쉽게 수행할 수 있습니다. 배포 또한 ceph orch apply 명령어 한 줄로 가능하며, 전체 라이프사이클을 Ceph의 orchestrator가 관리해주기 때문에 운영 측면에서도 효율적입니다.

 

결과적으로 여러 요소를 고려했을 때, Custom Container Service가 우리 팀에게 더 적합한 방향이라고 판단되었고, 이에 따라 실제 구현과 배포를 진행하게 되었습니다.

 

과정

우선 제 목표는 클러스터에 컨테이너가 잘 올라가는지 테스트를 하는게 목적이었기 때문에, go로 간단하게 API를 하나 만들었습니다.

 

Dockerfile

# 빌드 단계
FROM --platform=linux/amd64 golang:1.24-bookworm AS builder
WORKDIR /app
LABEL ceph="true"

RUN apt-get update && apt-get install -y \
  build-essential \
  librados-dev \
  librbd-dev \
  ceph-common \
  && rm -rf /var/lib/apt/lists/*

COPY go.mod go.sum ./
RUN go mod download

COPY . .

RUN CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -tags no_encryption -o ceph-core-api ./cmd/api

# 실행 단계
FROM --platform=linux/amd64 debian:bookworm-slim
WORKDIR /app
RUN apt-get update && apt-get install -y librados2 ceph-common && rm -rf /var/lib/apt/lists/*
COPY --from=builder /app/ceph-core-api .

EXPOSE 9080
CMD ["./ceph-core-api"]

 

Ceph 클러스터와 통신할 수 있는 Go 기반 API를 효율적으로 빌드하고 실행하기 위해 멀티스테이지 빌드 방식을 사용했습니다. 이를 통해 불필요한 의존성을 제거한 경량 컨테이너 이미지를 만들 수 있습니다.

 

빌드

FROM --platform=linux/amd64 golang:1.24-bookworm AS builder
  • golang 이미지를 기반으로 Go 애플리케이션을 컴파일합니다.
  • --platform=linux/amd64는 호스트 아키텍처와 관계없이 명확한 타깃 플랫폼을 지정해 M1/M2 Mac 등에서도 호환 문제를 방지
RUN apt-get update && apt-get install -y \
  build-essential \
  librados-dev \
  librbd-dev \
  ceph-common \
  • Ceph 클러스터와 연동하기 위해 필요한 개발 헤더 및 라이브러리를 설치합니다.
  • Go의 CGO 기능을 활용해 librados를 사용하기 위한 필수 패키지입니다. 
RUN CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -tags no_encryption -o ceph-core-api ./cmd/api
  • CGO를 활성화하여 Ceph C 라이브러리와 연동 가능하게 빌드합니다.
  • -tags no_encryption은 필요한 경우 빌드 태그를 조정할 수 있습니다. (해당 태그가 없는 경우 빌드 에러)

실행

FROM --platform=linux/amd64 debian:bookworm-slim
  • 실행 이미지는 debian-slim 기반으로, 빌드 도구 없이 필요한 라이브러리만 포함해 이미지 크기를 최소화합니다.
  • Ceph 공식 컨테이너 이미지나 대부분의 Ceph 관련 컴포넌트는 linux/amd64를 기본으로 빌드됨
  • 호스트와 상관없이 항상 Ceph 클러스터와 호환되는 아키텍처로 이미지를 고정 (플랫폼을 맞춰주지 않는 경우 컨테이너 에러)
RUN apt-get update && apt-get install -y librados2 ceph-common
  • 런타임에서 librados를 활용하기 위해 필요한 패키지를 설치합니다.
COPY --from=builder /app/ceph-core-api .
EXPOSE 9080
CMD ["./ceph-core-api"]
  • 빌드된 바이너리만 복사해 실행 환경을 구성하고, 9080 포트로 API를 제공하도록 설정합니다.

Dockerfile로 이미지를 빌드하고 컨테이너 허브에 push

docker buildx build --platform linux/amd64 -t harbor.tareun.kr/share/djlee/ceph-core-api:v1.0.3 --push .

현재 저는 맥북(arm64)을 사용하기 때문에 --platform 옵션 없이 빌드하면 arm64 아키텍처 이미지로 생성됩니다.

arm64 아키텍처로 Ceph 클러스터에 배포하면 컨테이너 실행이 실패합니다.

 

그럼 이제 실제 Cluster에서 Push한 컨테이너 이미지를 사용해서 배포를 진행하면 됩니다.

Spec 예시 및 옵션 (ceph-core-api.yml)

service_type: container
service_id: ceph-core-api
placement:
  hosts:
    - ceph152 
    - ceph153 
spec:
  image: harbor.xxx.kr/share/djlee/ceph-core-api:v1.0.4
  args:
    - "--net=host"
  ports:
    - 9080
  envs:
    - GIN_MODE=release
  bind_mounts:
    - ['type=bind', 'source=/etc/ceph', 'destination=/etc/ceph', 'ro=true']

 

배포

ceph orch apply -i ceph-core-api.yml

 

서비스 목록과 배포 상태 확인

 

결과

 curl http://121.141.64.152:9080/api/cluster/fsid
 
 {
  "status": "success",
  "data": {
    "fsid": "df5355e6-f66f-45c6-83b0-4680e086eff5"
  }
}

 

 

Prometheus 연동

  • Cephadm으로 관리되는 Prometheus에서 기본 Ceph exporter 외에 사용자 정의 메트릭 엔드포인트 수집하기 위함
  • 기존 Ceph 모듈(ceph, ceph-exporter, node-exporter)의 scrape 설정 유지, 새로운 job 추가

1. 템플릿 파일 작성 (prometheus.yml.j2)

기존 job 설정을 모두 포함하지 않으면 기존 수집 항목이 사라질 수 있으니, 반드시 기존 job도 포함해야 함.

: 템플릿을 작성하기 전에, 현재 Cephadm에서 Prometheus가 수집 중인 모듈(job)확인 필수!

global:
  scrape_interval: 15s
  evaluation_interval: 15s

scrape_configs:
  - job_name: 'ceph'
    static_configs:
      - targets: ['ceph155:9283']

  - job_name: 'ceph-exporter'
    static_configs:
      - targets:
          - 'xxx.xxx.xx.xxx:9926'
          - 'xxx.xxx.xx.xxx:9926'
          - 'xxx.xxx.xx.xxx:9926'
          - 'xxx.xxx.xx.xxx:9926'

  - job_name: 'node'
    static_configs:
      - targets:
          - 'xxx.xxx.xx.xxx:9100'
          - 'xxx.xxx.xx.xxx:9100'
          - 'xxx.xxx.xx.xxx:9100'
          - 'xxx.xxx.xx.xxx:9100'

  - job_name: 'ceph-core-api'
    static_configs:
      - targets:
          - 'localhost:9080'

 

2. config-key로 등록

ceph config-key set mgr/cephadm/services/prometheus/prometheus.yml -i prometheus.yml.j2

 

3. Prometheus 서비스 재배포

ceph orch redeploy promoetheus

 

4. 결과

 

반응형
저작자표시 (새창열림)

'dev > Ceph' 카테고리의 다른 글

Ceph 장애가 발생했을 때, 왜 BE가 느려졌을까?  (0) 2026.03.31
'dev/Ceph' 카테고리의 다른 글
  • Ceph 장애가 발생했을 때, 왜 BE가 느려졌을까?
:j
:j
ddongjunn@gmail.com
  • :j
    dev.j
    :j
  • 전체
    오늘
    어제
    • :j
      • dev
        • Ceph
        • CS
        • Spring
        • k8s
        • Java
        • JPA
        • Web
        • CCNA
        • 코딩테스트
        • JavaScript
        • XML
        • JSON
        • CSS
        • html
        • jQuery
        • Mssql
        • Oracle
      • 회고
      • :j story
  • 블로그 메뉴

    • 홈
    • 태그
    • github
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    다형성
    항해플러스백앤드
    CustomContainer
    항해백앤드
    ceph
    HAVING
    오버로딩
    group by
    지역변수
    멤버변수
    id
    class
    항해99
    appendChild
    <br>
    Name
    오버라이딩
    항해플러스
    Queue
    MSSQL
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
:j
[Ceph] Custom Container 배포를 해보자! (+Prometheus 연동)
상단으로

티스토리툴바