iLO와 iDRAC 수집 스크립트를 만들었다면, 다음은 Zabbix에 호스트와 수십 개의 아이템·트리거를 등록하는 작업입니다. UI에서 하나씩 클릭하는 대신 Zabbix API를 활용하면 스크립트 한 번으로 전체 구성을 완성할 수 있습니다.
Zabbix API 구조
Zabbix API는 JSON-RPC 2.0 프로토콜을 사용합니다. 모든 요청은 단일 엔드포인트로 전송됩니다:
POST https://zabbix서버:8080/api_jsonrpc.php
Content-Type: application/json
요청 형식:
{
"jsonrpc": "2.0",
"method": "host.create",
"params": { ... },
"auth": "인증토큰",
"id": 1
}
인증 토큰 발급
import requests
ZABBIX_URL = "http://localhost:8080/api_jsonrpc.php"
def zabbix_api(method, params, token=None):
payload = {
"jsonrpc": "2.0",
"method": method,
"params": params,
"id": 1,
}
if token:
payload["auth"] = token
r = requests.post(ZABBIX_URL, json=payload, timeout=10)
result = r.json()
if "error" in result:
raise RuntimeError(f"API Error: {result['error']}")
return result["result"]
# 로그인
token = zabbix_api("user.login", {
"username": "Admin",
"password": "비밀번호"
})
Zabbix 7.0부터 user 대신 username 파라미터를 사용합니다. 구버전 자료를 참고할 때 주의하세요.
호스트 생성
def create_host(token, hostname, ip, group_id):
return zabbix_api("host.create", {
"host": hostname,
"name": hostname,
"interfaces": [{
"type": 1, # 1=Agent (Trapper는 인터페이스 타입 무관)
"main": 1,
"useip": 1,
"ip": ip,
"dns": "",
"port": "10050"
}],
"groups": [{"groupid": str(group_id)}],
}, token)
호스트 그룹 ID는 환경마다 다릅니다. 먼저 조회합니다:
groups = zabbix_api("hostgroup.get", {"output": ["groupid", "name"]}, token)
for g in groups:
print(g["groupid"], g["name"])
아이템 생성
def create_item(token, hostid, key, name, vtype=0):
params = {
"hostid": hostid,
"name": name,
"key_": key,
"type": 2, # 2 = Zabbix trapper
"value_type": vtype, # 0=float, 1=string, 3=unsigned, 4=text
"history": "30d",
"delay": 0, # Trapper는 수집 주기 없음
}
# 문자열 타입은 trends 저장 불가 — 파라미터 자체를 제외해야 함
if vtype not in (1, 4):
params["trends"] = "365d"
return zabbix_api("item.create", params, token)
trends 파라미터 주의: value_type이 1(string) 또는 4(text)인 아이템에 trends 파라미터를 포함하면 API가 오류를 반환합니다. 조건부로 제외해야 합니다.
value_type 값:
| 값 | 타입 | 용도 |
|---|---|---|
| 0 | Numeric (float) | 온도, 전력, 비율 |
| 1 | Character (string) | 짧은 문자열 |
| 3 | Numeric (unsigned) | 카운터, 상태값 |
| 4 | Text | 긴 문자열, JSON |
iLO 아이템 일괄 생성 예시
ILO_ITEMS = [
("ilo.health.system", "시스템 전체 헬스", 3),
("ilo.power.state", "전원 상태", 3),
("ilo.health.cpu", "CPU 헬스", 3),
("ilo.cpu.count", "CPU 수", 3),
("ilo.health.memory", "메모리 헬스", 3),
("ilo.memory.total_gb", "메모리 전체 (GB)", 0),
("ilo.power.consumed", "소비 전력 (W)", 0),
("ilo.power.capacity", "전력 용량 (W)", 0),
("ilo.power.ps1.health", "PSU 1 헬스", 3),
("ilo.power.ps1.output", "PSU 1 출력 (W)", 0),
("ilo.power.ps2.health", "PSU 2 헬스", 3),
("ilo.power.ps2.output", "PSU 2 출력 (W)", 0),
]
host_result = create_host(token, "proxmox-idc-02-ilo", "10.0.92.112", group_id=27)
hostid = host_result["hostids"][0]
for key, name, vtype in ILO_ITEMS:
create_item(token, hostid, key, name, vtype)
print(f" [OK] {key}")
온도·팬 센서처럼 서버마다 이름이 다른 동적 아이템은 수집 스크립트가 처음 데이터를 전송할 때 Zabbix에서 자동으로 인식되지 않습니다. 이 경우 먼저 스크립트를 한 번 실행해 어떤 키로 데이터가 전송되는지 확인한 뒤, 해당 키로 아이템을 등록합니다.
트리거 생성
Zabbix 7.0에서 트리거 생성 시 두 가지 함정이 있습니다.
함정 1: hostid 파라미터 불가
구버전 자료를 보면 trigger.create에 hostid를 넣는 예시가 있습니다. Zabbix 7.0에서는 이 파라미터가 없습니다. 호스트 정보는 expression 안에 포함됩니다:
# 잘못된 코드
zabbix_api("trigger.create", {
"hostid": hostid, # 오류: unexpected parameter
"expression": "...",
...
})
# 올바른 코드
zabbix_api("trigger.create", {
"expression": "last(/proxmox-idc-02-ilo/ilo.health.system) >= 2",
...
}, token)
함정 2: 트리거 표현식 포맷
3편에서 다뤘던 것처럼 Zabbix 7.0은 새 포맷만 허용합니다:
def create_trigger(token, hostname, key, name, expr, severity=2):
# severity: 0=미분류, 1=정보, 2=경고, 3=보통, 4=심각, 5=재해
return zabbix_api("trigger.create", {
"description": name,
"expression": expr.format(host=hostname),
"priority": severity,
"status": 0, # 0=활성화
}, token)
# 사용 예시
create_trigger(
token,
hostname="proxmox-idc-02-ilo",
key="ilo.health.system",
name="iLO: 시스템 헬스 이상",
expr="last(/{host}/ilo.health.system) >= 2",
severity=4, # High
)
iLO/iDRAC 공통 트리거 목록
COMMON_TRIGGERS = [
# (이름, 표현식, 심각도)
("시스템 헬스 Critical",
"last(/{host}/ilo.health.system) >= 2", 4), # High
("전원 OFF",
"last(/{host}/ilo.power.state) = 0", 4), # High
("CPU 헬스 이상",
"last(/{host}/ilo.health.cpu) >= 1", 3), # Average
("메모리 헬스 이상",
"last(/{host}/ilo.health.memory) >= 1", 3), # Average
("PSU 1 이상",
"last(/{host}/ilo.power.ps1.health) >= 1", 4), # High
("PSU 2 이상",
"last(/{host}/ilo.power.ps2.health) >= 1", 4), # High
("소비 전력 과다 (500W 초과)",
"last(/{host}/ilo.power.consumed) > 500", 2), # Warning
]
iLO와 iDRAC의 키 이름 앞부분(ilo. / idrac.)만 다르고 구조는 동일합니다. 공통 트리거 목록을 만들고 prefix만 교체하면 재사용할 수 있습니다.
전체 자동화 흐름
def setup_ilo_host(token, site_key, cfg, group_id):
hostname = cfg["zabbix_host"]
ip = cfg["ilo_host"]
# 1. 호스트 생성
result = create_host(token, hostname, ip, group_id)
hostid = result["hostids"][0]
print(f"[OK] 호스트 생성: {hostname} (ID: {hostid})")
# 2. 아이템 생성
for key, name, vtype in ILO_ITEMS:
create_item(token, hostid, key, name, vtype)
print(f"[OK] 아이템 {len(ILO_ITEMS)}개 생성")
# 3. 트리거 생성
for tname, expr, severity in COMMON_TRIGGERS:
create_trigger(token, hostname, "", tname,
expr.replace("{host}", hostname), severity)
print(f"[OK] 트리거 {len(COMMON_TRIGGERS)}개 생성")
# 실행
token = zabbix_api("user.login", {"username": "Admin", "password": "pw"})
for site_key, cfg in HOSTS.items():
setup_ilo_host(token, site_key, cfg, group_id=27)
API 사용 시 자주 보는 오류
| 오류 메시지 | 원인 | 해결 |
|---|---|---|
No permissions to referred object | 해당 호스트/그룹 접근 권한 없음 | Admin 계정 사용 확인 |
unexpected parameter "hostid" | trigger.create에 hostid 포함 | 파라미터 제거 |
Invalid parameter "trends" | string 타입 아이템에 trends 설정 | vtype 1·4이면 trends 제외 |
Invalid parameter "username" | 구버전 user 파라미터 사용 | username으로 변경 |
Trigger expression ... is incorrect | 구버전 트리거 표현식 포맷 | 신규 포맷으로 변경 |
마치며
이번 편에서 다룬 핵심 포인트입니다:
- Zabbix API는 JSON-RPC 2.0 — 단일 엔드포인트로 모든 요청
string/text타입 아이템은trends파라미터 제외 필수trigger.create에hostid파라미터 없음 — 표현식에 호스트명 직접 포함- Zabbix 7.0 트리거 표현식:
last(/hostname/key) >= 값 - iLO와 iDRAC은 키 prefix만 다르고 트리거 구조 동일 — 재사용 가능
다음 편에서는 OPNsense 방화벽 모니터링을 다룹니다.