Zabbix 인프라 모니터링 구축 – 09. Dell 하드웨어: iDRAC 8 Redfish API 모니터링 (R730xd·스토리지)

2026.10.01

·

8편에서 HP iLO Redfish API를 구현했다면, 이번 편에서는 Dell iDRAC 8을 다룹니다. Redfish는 동일한 표준이지만 제조사마다 API 경로와 응답 구조가 다릅니다. iLO 코드를 그대로 쓰면 동작하지 않습니다.


iDRAC과 iLO의 차이

iDRAC(Integrated Dell Remote Access Controller)은 Dell 서버의 원격 관리 인터페이스로, HP의 iLO에 해당합니다. Redfish 표준을 따르지만 경로가 다릅니다:

항목HP iLO 4Dell iDRAC 8
시스템/redfish/v1/Systems/1/redfish/v1/Systems/System.Embedded.1
섀시 Thermal/redfish/v1/Chassis/1/Thermal/redfish/v1/Chassis/System.Embedded.1/Thermal
섀시 Power/redfish/v1/Chassis/1/Power/redfish/v1/Chassis/System.Embedded.1/Power
스토리지/redfish/v1/Systems/1/SmartStorage/redfish/v1/Systems/System.Embedded.1/Storage

가장 크게 다른 부분은 리소스 ID입니다. HP는 숫자(1)를, Dell은 System.Embedded.1 형태의 식별자를 사용합니다. 스토리지 경로명도 다릅니다(SmartStorage vs Storage).

Sponsored


SSL 처리

iDRAC 8도 구형 펌웨어에서 동일한 SSL 문제가 발생합니다. 8편에서 구현한 LegacySSLAdapter를 그대로 재사용합니다:

class LegacySSLAdapter(HTTPAdapter):
    def init_poolmanager(self, *args, **kwargs):
        ctx = ssl.create_default_context()
        ctx.set_ciphers("DEFAULT:@SECLEVEL=1")
        ctx.check_hostname = False
        ctx.verify_mode = ssl.CERT_NONE
        kwargs["ssl_context"] = ctx
        super().init_poolmanager(*args, **kwargs)

def idrac_get(cfg, path):
    s = requests.Session()
    s.auth = (cfg["idrac_user"], cfg["idrac_pass"])
    s.verify = False
    s.headers.update({"Accept": "application/json"})
    if cfg.get("legacy_ssl"):
        s.mount("https://", LegacySSLAdapter())
    r = s.get(f"https://{cfg['idrac_host']}{path}", timeout=15)
    if r.status_code == 200:
        return r.json()
    return None

호스트 설정

HOSTS = {
    "pbs01": {
        "idrac_host":  "10.0.92.191",
        "idrac_user":  "관리자계정",
        "idrac_pass":  "비밀번호",
        "zabbix_host": "pbs-idc-01-idrac",
        "legacy_ssl":  True,
    },
}

시스템 헬스 수집

iDRAC의 시스템 엔드포인트는 iLO와 응답 구조가 유사합니다:

system = idrac_get(cfg, "/redfish/v1/Systems/System.Embedded.1")
if system:
    sl("idrac.health.system", health_int(system.get("Status", {}).get("Health")))
    sl("idrac.power.state",   1 if system.get("PowerState") == "On" else 0)

    proc = system.get("ProcessorSummary", {})
    sl("idrac.health.cpu", health_int(proc.get("Status")))
    if proc.get("Count") is not None:
        sl("idrac.cpu.count", proc["Count"])

    mem = system.get("MemorySummary", {})
    sl("idrac.health.memory", health_int(mem.get("Status")))
    if mem.get("TotalSystemMemoryGiB") is not None:
        sl("idrac.memory.total_gb", mem["TotalSystemMemoryGiB"])

iLO와 비교했을 때 키 이름만 ilo. → idrac.으로 바뀌고 로직은 동일합니다.


Thermal 수집

thermal = idrac_get(cfg, "/redfish/v1/Chassis/System.Embedded.1/Thermal")
if thermal:
    for temp in thermal.get("Temperatures", []):
        st = temp.get("Status", {})
        if st.get("State") not in ("Enabled", "Absent"):
            continue
        reading = temp.get("ReadingCelsius")
        if reading is None:
            continue
        k = key_norm(temp.get("Name", "unknown"))
        sl(f"idrac.temp.{k}", reading)

    for fan in thermal.get("Fans", []):
        st = fan.get("Status", {})
        if st.get("State") != "Enabled":
            continue
        name = fan.get("FanName") or fan.get("Name", "")
        k = key_norm(name)
        reading = fan.get("ReadingRPM") or fan.get("Reading")
        if reading is not None:
            sl(f"idrac.fan.{k}.rpm", reading)
        sl(f"idrac.fan.{k}.health", health_int(st))

Dell PowerEdge R730xd의 주요 온도 센서:

센서명위치
Inlet Temp서버 흡입구
Exhaust Temp서버 배출구
CPU1 TempCPU 1번
CPU2 TempCPU 2번

팬은 FAN 1A, FAN 1B 형태로 이름이 붙으며, R730xd는 팬 모듈당 두 개의 팬(A/B)이 있습니다.


전력 수집

power = idrac_get(cfg, "/redfish/v1/Chassis/System.Embedded.1/Power")
if power:
    for pc in power.get("PowerControl", []):
        consumed = pc.get("PowerConsumedWatts")
        if consumed is not None:
            sl("idrac.power.consumed", consumed)
        cap = pc.get("PowerCapacityWatts")
        if cap is not None:
            sl("idrac.power.capacity", cap)
        break

    for i, psu in enumerate(power.get("PowerSupplies", []), 1):
        st = psu.get("Status", {})
        if st.get("State") == "Absent":
            continue
        sl(f"idrac.power.ps{i}.health", health_int(st))
        out = psu.get("PowerOutputWatts") or psu.get("LastPowerOutputWatts")
        if out is not None:
            sl(f"idrac.power.ps{i}.output", out)
        volt = psu.get("LineInputVoltage")
        if volt is not None:
            sl(f"idrac.power.ps{i}.voltage", volt)

iLO와 동일한 구조입니다. Dell 서버도 PSU 이중화 구성이 일반적이며, PSU 하나가 Critical이면 즉시 교체가 필요합니다.


스토리지 수집 — iLO와 가장 다른 부분

iDRAC의 스토리지 수집은 iLO와 구조가 다릅니다. iDRAC은 컨트롤러 → 드라이브로 계층적으로 탐색합니다:

storage = idrac_get(cfg, "/redfish/v1/Systems/System.Embedded.1/Storage")
if storage:
    for member in storage.get("Members", []):
        mpath = member.get("@odata.id", "")
        ctrl = idrac_get(cfg, mpath)
        if not ctrl:
            continue

        ctrl_id = key_norm(ctrl.get("Id", mpath.rstrip("/").split("/")[-1]))
        sl(f"idrac.storage.ctrl.{ctrl_id}.health", health_int(ctrl.get("Status")))

        for drive_ref in ctrl.get("Drives", []):
            dpath = drive_ref.get("@odata.id", "")
            drive = idrac_get(cfg, dpath)
            if not drive:
                continue
            slot = key_norm(drive.get("Id", dpath.rstrip("/").split("/")[-1]))
            sl(f"idrac.storage.pd.{slot}.health", health_int(drive.get("Status")))

탐색 흐름:

/Storage
  └── Members[]
        └── @odata.id → 컨트롤러 경로
              └── Drives[]
                    └── @odata.id → 드라이브 경로

컨트롤러 목록을 먼저 가져오고, 각 컨트롤러의 드라이브를 순서대로 탐색합니다. 컨트롤러와 드라이브 수만큼 API 호출이 발생하므로 서버당 수집 시간이 길어질 수 있습니다.

수집 키 예시:

idrac.storage.ctrl.boss_a1.health       → 0 (OK)
idrac.storage.pd.disk_0_0_0.health      → 0 (OK)
idrac.storage.pd.disk_0_1_0.health      → 0 (OK)

컨트롤러 ID와 드라이브 슬롯 ID는 key_norm()으로 정규화해 Zabbix 키에 사용합니다.


iLO vs iDRAC 수집 항목 비교

수집 항목HP iLO 4Dell iDRAC 8
시스템 헬스✅✅
전원 상태✅✅
CPU 요약 헬스✅✅
메모리 요약 헬스✅✅
온도 센서✅✅
팬 RPM/헬스✅✅
소비 전력✅✅
PSU별 헬스/출력✅✅
스토리지 컨트롤러 헬스✅ (SmartStorage)✅ (Storage)
물리 드라이브 헬스✅ (Smart Array만)✅ (RAID 컨트롤러 연결)

수집 항목은 거의 동일하지만 API 경로와 탐색 방식이 다릅니다. 코드를 재사용하려면 경로만 교체 가능하도록 설계하는 것이 좋습니다.


crontab 등록

# Dell iDRAC 수집 (5분)
*/5 * * * * /usr/bin/python3 /data/zabbix/scripts/idrac_collector.py --site all >> /var/log/zabbix-collector.log 2>&1

마치며

이번 편에서 다룬 핵심 포인트입니다:

  • Redfish 표준이지만 iLO와 iDRAC은 API 경로가 다름 — 혼용 불가
  • 핵심 차이: 리소스 ID(1 vs System.Embedded.1), 스토리지 경로
  • iDRAC 스토리지는 컨트롤러 → 드라이브 계층 탐색 구조
  • key_norm()으로 센서/드라이브 ID를 Zabbix 키로 정규화

다음 편에서는 iLO와 iDRAC 모니터링을 위한 Zabbix 호스트, 아이템, 트리거를 Zabbix API로 자동 생성하는 방법을 다룹니다. 수십 개의 아이템을 UI에서 수동으로 만드는 대신 스크립트 한 번으로 일괄 등록하는 구조를 설명합니다.


MORE POSTS

다른 글 보기

테크 랩

PMBOK 완독기 – 00. 오리엔테이션: 왜 정석을 완독하나 + 6판·7판 지도

PMBOK을 목차대로 완독하며 IT 현장에 번역하는 시리즈 시작. 6판(10지식영역)·7판(원칙·테일러링) 지도와 15편 로드맵.
2026.10.22
guniq 인사이트 썸네일 — 중소기업 OpenLDAP 통합 인증 구축 – 07. 백업·로그·운영 자동화: 장애 없는 LDAP 서버 유지하기
테크 랩

중소기업 OpenLDAP 통합 인증 구축 – 07. 백업·로그·운영 자동화: 장애 없는 LDAP 서버 유지하기

LDAP 서버는 설치 후가 더 중요합니다. 데이터 유실을 막는 백업 전략(daily/weekly/monthly), slapd 로그 관리와 logrotate 설정, 헬스체크 자동화까지 — 실제 운영 중인 스크립트를 바탕으로 LDAP 서버를 안정적으로 유지하는 방법을 정리합니다.
2026.10.21
guniq 인사이트 썸네일 — 중소기업 OpenLDAP 통합 인증 구축 – 06. Synology NAS LDAP 연동: DSM 설정과 그룹 권한 매핑
테크 랩

중소기업 OpenLDAP 통합 인증 구축 – 06. Synology NAS LDAP 연동: DSM 설정과 그룹 권한 매핑

Synology DSM의 LDAP 클라이언트를 커스텀 프로파일로 설정하는 방법을 정리합니다. groupPosixAux 필터, memberUid 매핑, LDAPS 인증서 처리까지 — 표준을 지킨 LDAP 구조가 NAS 연동을 얼마나 단순하게 만드는지 확인합니다.
2026.10.20

프로젝트 문의 환영합니다

기획부터 개발, 운영까지 함께 만들어 드립니다.

무료 3분 자가진단

우리 회사, 자체 클라우드가 답일까?

AWS vs 자체 인프라 · 11개 항목 3분 체크