DevOps / 감사 2026년 5월 15일

2026-05-15 렌탈 ProxyMac Mac mini의 OpenClaw LaunchAgent: ThrottleInterval·KeepAlive·SuccessfulExit로 크래시 루프를 모델 장애로 오인하지 않기

ProxyMac 엔지니어링 팀 2026-05-15 약 18분 읽기

홍콩·일본·한국·싱가포르·미국에 있는 렌탈 Mac mini M4에서 OpenClawLaunchAgent로 상주시키면 흔한 패턴은 게이트웨이가 종료되고 launchd가 1초 안에 다시 띄우며 추론 API가 429나 빈 스트림을 돌려주고 팀은 곧바로 「모델」 탓을 합니다. 본문은 운영·플랫폼 엔지니어를 위해 (1) 대상과 정량 게이트, (2) 크래시 루프와 공급자 측 스로틀의 증상 분리, (3) ThrottleInterval·KeepAlive·SuccessfulExit4행 결정 표, (4) 재시작 복구개발/스테이징/프로덕션 분리에 맞춘9단계 런북, (5) HTTP 429 버스트의시나리오 표, (6) ThrottleInterval0으로 둔 함정을 정리합니다. ulimit·메모리, 무인 작업, 기업 HTTP 프록시 plist와 함께 읽으세요. SKU는 요금, 인시던트 템플릿은 도움말, 일회성 GUI 신뢰 대화상자는 VNC를 사용합니다.

OpenClaw에서 ThrottleInterval과 KeepAlive를 반드시 다뤄야 하는 경우

게이트웨이가모델 품질과 무관하게 종료될 때—손상된 설정 JSON, MCP 자식 세그폴트, TLS MITM CA 로테이션, 배포 중 순간적으로 사라진 토큰 파일—plist를 점검해야 합니다. ThrottleInterval을 명시하지 않으면 macOS가 SSH에서 사람이 재시도하는 것보다 빠른 자동 재시작을 허용할 수 있습니다. 반대로 KeepAlive만 켜고 종료 의미를 적지 않으면 「성공한」 유지보수 중단 직후 의도치 않게 다시 기동될 수 있습니다.

  • 정량 게이트:log show --predicate 'process == "launchd"' --last 15m에서 동일 Label 시작이 12회를 넘으면 크래시 루프 구간입니다.
  • 공급자 게이트:429가 재시작 타임스탬프와 ±5초 안에서 상관되면 먼저 자동 재시작을 늦추고 온도 조정은 나중입니다.
  • 분리 게이트:여러 환경이 plist Label을 공유하지 않도록—스로틀을 바꾸기 전 분리 가이드의 환경당 하나 Label을 지킵니다.

증상: 크래시 루프 vs 공급자 측 스로틀

크래시 루프는 CPU 톱니 패턴이 전형적입니다: 0% 유휴에서 약 8초 안에 180%까지 올라가 OpenClaw를 부팅하고 하드 종료를 반복합니다. 공급자 측 제한은 CPU가 비교적 평탄하고 로그에 retry-after나 지수 백오프 힌트가 나타납니다. JSONL 첫 배너가 많은 파일에서 동일하면 프로세스가 정상 상태에 들지 못했을 가능성이 큽니다. 벤더 티켓을 열기 전에 stat -f '%m' ~/Library/LaunchAgents/com.example.openclaw.plist로 plist 변경 시각을 맞추고 JSONL 진단과 대조하세요.

증거 세트:(1) launchctl print의 최종 종료 상태, (2) 게이트웨이 로그의 HTTP 상태 히스토그램, (3) MCP 자식 종료 코드—MCP가 안정적이고 HTTP가 429 위주면 먼저 자동 재시작을 늦춥니다.

결정 표: ThrottleInterval·KeepAlive·SuccessfulExit

제어 내용 올리거나/켤 때기 잘못 설정 시 주요 위험
ThrottleInterval(초) 종료 후 자동 재시작 사이 최소 간격 임의 429 폭풍 또는 롤아웃 중 불안정 MCP 너무 크면 장애 시 실제 복구가 가려짐
KeepAlive true 작업 종료 시 plist 의미에 따른 자동 재기동 재부팅 후에도 상주해야 하는 장수명 게이트웨이 스로틀 없이 무한 기동은 쿼터를 태움
SuccessfulExit false KeepAlive와 조합해 종료 0을 자동 재시작하지 않는 성공으로 처리 유지보수용 센티널 스크립트 불리언을 반대로 쓰면 좀비 재시작이 남음
수동 launchctl kickstart -k 운영 주도 재시작으로 스로틀 주기 우회 plist 검증 후 통제된 릴리스 자동화가 kickstart를 타이트 루프로 부르면 폭풍 재현

9단계 안정화 런북

  1. Label 감사:프로덕션 OpenClaw는 plist 하나만 소유, 환경 분리를 따릅니다.
  2. 종료 폭풍 수집:Label로 필터한 unified log 최근 200줄을보냅니다.
  3. 기준 스로틀:개발은 10초부터, 프로덕션은 첫 429 클러스터 후 30초로 올립니다.
  4. SuccessfulExit 정의:업그레이드 스크립트에서 종료 0을 정상 종료로 문서화합니다.
  5. 메모리 상한 정렬:ulimit 글과 맞춰 OOM이 네트 장애로 위장되지 않게 합니다.
  6. Webhook 억제:Slack Webhook을 쓰면 스로틀이 프로세스를 냉각하는 동안 알림을 디바운스합니다.
  7. 장애 주입:비밀이 아닌 설정 파일을 잠시 치워 재시작 간격이 ThrottleInterval을 지키는지 확인합니다.
  8. 소크:피크 병렬 40%45분 합성 트래픽을 돌려 숨은 외부 워치독이 이중 기동하지 않는지 봅니다.
  9. 사후 분석:plist diff와 재시작 히스토그램을 설정 버전 관리와 같은 Git에 보관합니다.
절대프로덕션 API 키가 붙은 공유 테넌트 mini에서 ThrottleInterval0으로 두지 마세요—당신의 크래시가 모두의 속도 제한 사고가 됩니다.

시나리오 표: HTTP 429 버스트와 launchd 동작

시나리오 관측 패턴 첫 레버
MCP 세그폴 루프 종료 코드 1392–4초 주기 ThrottleInterval을 30으로, MCP 경로 수정
배포 중 토큰 파일 경합 6번의 종료 78 뒤 성공 배포 뮤텍스 추가, ThrottleInterval ≥ 15
공급자 전역 스로틀 429와 Retry-After: 60 ThrottleInterval ≥ 60, 병렬 에이전트 축소
운영 kickstart -k 스크립트 결함 건강해도 60초마다 기동 cron 래퍼 제거, KeepAlive + 헬스 프로브로 전환

함정: ThrottleInterval이 0이고 이중 워치독

대화형 데몬용 템플릿에서 복사한 plist는 ThrottleInterval0으로 남기 쉽습니다. OpenClaw에 공격적인 KeepAlive를 겹치면 서브초로 파일 디스크립터가 고갈되어 MCP 24류 오류로 보입니다(도구 로직 문제가 아님). 또 하나는 KeepAlive가 true인데 외부 cron이 launchctl kickstart를 주기적으로 호출해 건강할 때 이중 기동하는 패턴입니다. 감독 계층은 하나만 둡니다.

defaults read /path/to.plist ThrottleInterval

FAQ

ThrottleInterval이 정상 배포를 늦추나요?종료 후 자동 재기동 사이의 최소 벽시계 간격만 제한합니다. 운영자가 launchctl kickstart로 수동 재시작하면 스로틀 밖입니다.

카나리 업그레이드 중 KeepAlive를 true로 둘까요?장기 게이트웨이는 보통 true이나 ThrottleInterval과 함께 써서 불량 바이너리의 즉시 재기동을 막습니다. 카나리는 별도 Label plist를 씁니다.

유지보수 중단에 SuccessfulExit로 어떤 코드를 쓰나요?래퍼가 약속한 센티넬—보통 0이 정상 종료—를 plist 옆에 문서화해 장애 시그니처와 혼동하지 않게 합니다.

왜 ProxyMac Mac mini에서 launchd 재시작 규율을 연습해야 하나

렌탈 Mac mini M4는 예측 가능한싱글 테넌트 CPU로 열 스로틀과 재시작 폭풍을 구분하기 쉽고, 개발자 노트북과 동일한네이티브 macOS syslog 동작을 얻습니다. HK / JP / KR / SG / US 리전 선택으로 지연 실험을 실제 사용자 분포에 가깝게 할 수 있습니다. 여기서 스로틀 산술을 검증한 뒤 같은 plist 조각을 요금이 투명한 두 번째 mini로 승격시키면, launchd 의미가 숨겨진 공유 CI 러너에서 추측할 필요가 없습니다.

쿼터가 물기 전에 OpenClaw launchd 강화

ThrottleInterval · KeepAlive · HK / JP / KR / SG / US