Loading the catalog…
Loading the catalog…
아침에 눈을 떴는데 슬랙과 로그에 찍힌 섬뜩한 메시지: *"치명적: 헬스체크 실패로 인한 자동 롤백까지 실패했습니다. 서비스 중단 위험!"* 심장이 철렁해서 급히 EC2 운영 서버를 확인했더니... 서비스는 1시간 전부터 아무 문제 없이 평온하게 200 OK를 뱉고 있었습니다. 멀쩡한 새 버전 배포를 '실패'로 오판하고 불필요한 롤백 지옥에 빠뜨렸던 범인, macOS 배터리 모드의 'Power Nap'과 장기 실행 SSH 파이프의 함정 을 파헤친 기록입니다. 🚨 1. 증상: 아침을 공포로 몰아넣은 새벽 배포 로그 새벽 3시 자동 배포 파이프라인의 로그( allteachers-nightly-deploy.log )를 열어보았을 때 등골이 서늘해졌습니다: [03:15:22] 새 버전(v1.0.72) 배포 완료, 헬스체크 대기 중... [03:16:10] Connection to ec2-... broken pipe [03:16:10] ❌ 헬스체크 실패! 자동 롤백을 시도합니다... [03:16:45] 💥 치명적: 롤백 스크립트 실행 중 응답 없음. 서비스가 중단된 상태일 수 있습니다! 즉시 서버 터미널을 열고 상태를 확인했습니다: $ sudo systemctl status my-app ● my-app.service - Backend Service Active: active (running) since Thu 2026-09-17 03:15:30 KST; 4h ago Main PID: 12489 (java) 실제 서버 상태 : v1.0.72 버전이 배포 직후부터 4시간 내내 CPU를 정상 점유하며 완벽하게 떠 있었음. 진실 : 서버는 너무나 잘 배포되었는데, 로컬 배포 스크립트가 혼자 "서버 죽었다!"라고 착각(오탐) 해서 멀쩡한 배포를 롤백시키려 난리를 쳤던 것입니다. 🔍 2. 원인 분석: caffeinate 를 켰는데 왜 맥북이 잠들었을까? 이미 이전 트러블슈팅을 통해 배포 도중 맥북이 잠들지 않도록 caffeinate -i 명령어를 스크립트에 물려둔 상태였습니다. 그런데 왜 새벽에 연결이 끊겼을까요? pmset -g log 로 새벽 03시~05시 사이의 맥북 전원 시스템 로그를 까보았습니다: 2026-09-17 03:16:02 +0900 DarkWake DarkWake [CDN] due to EC.PowerNap/Maintenance: Using Batt (Charge:62%) 2026-09-17 03:16:12 +0900 Sleep Entering Sleep state due to 'Maintenance Sleep': Using Batt 범인은 배터리 모드의 'Power Nap (Maintenance Sleep)' caffeinate -i 의 맹점 : 사용자의 입력 유휴(Idle)로 인한 슬립만 막을 뿐, macOS 시스템이 주기적으로 도는 '유지보수 슬립/파워냅(Power Nap) 사이클' 은 막아주지 못합니다. 특히 맥북이 배터리( Using Batt )로 구동 중 일 때는 전력 절약을 위해 15분 주기로 찰나의 순간 잠들었다 깨어나는 동작을 반복합니다. 더 치명적이었던 배포 스크립트의 구조적 결함 당시 배포 스크립트의 헬스체크 로직은 다음과 같았습니다: # ❌ 기존 위험한 구조: 단 하나의 SSH 세션 안에서 150초 동안 루프 돌기 ssh -i $KEY $HOST " for i in {1..30}; do curl -sf http://localhost:8080/health && exit 0 sleep 5 done exit 1 " 헬스체크를 위해 단 하나의 SSH 연결을 최대 150초 동안 열어두고 원격 루프 를 돌렸습니다. 그 150초 사이에 맥북이 파워냅 주기로 0.5초만 네트워크를 끊어도, SSH는 즉시 Broken pipe 를 뱉고 튕겨 나옵니다. 스크립트는 이 Broken pipe 에러 코드를 보고 "헬스체크 30번 다 돌았는데 서버가 안 떴구나!"라고 오판 하여 즉시 롤백 루틴을 발동시킨 것입니다. 🛠️ 3. 해결책: "안 끊기게" 하지 말고 "끊겨도 다시 시도하게" 네트워크와 로컬 전원 상태는 언제든 튈 수 있습니다. 핵심은 단일 SSH 세션에 의존하지 않는 멱등한 재시도 구조 로 전환하는 것이었습니다. 1 헬스체크를 '개별 독립 SSH 요청'으로 분리 # 🚀 개선된 구조: 매 시도마다 새로운 독립 SSH 세션 생성 restart_and_wait_healthy() { local max_retries=30 local retry_count=0 echo "🚀 서비스 재시작 후 헬스체크 시작..." while [ $retry_count -lt $max_retries ]; do # 짧은 타임아웃을 가진 1회성 단발 SSH 호출 if ssh -o ConnectTimeout=10 -o BatchMode=yes $SSH_TARGET "curl -sf http://localhost:8080/health" > /dev/null 2>&1; then echo "✅ 헬스체크 통과! 정상 서비스 중입니다." return 0 fi retry_count=$((retry_count + 1)) echo "⏳ 헬스체크 대기 중... ($retry_count/$max_retries)" sleep 5 done echo "❌ 헬스체크 최종 실패" return 1 } 이제 헬스체크 도중 와이파이나 맥북 전원이 1~2초 끊겨도, 해당 1회의 핑만 실패할 뿐 다음 5초 뒤 루프에서 새로운 SSH 연결을 맺고 재검증 합니다. 특정 원인(Power Nap이든, 공유기 재부팅이든)에 구애받지 않는 강력한 내성을 확보했습니다. 2 SSH 접속 자체 타임아웃 명시 ( ConnectTimeout=10 ) 네트워크 순단 시 SSH 클라이언트가 무한정 멈추지 않고 10초 만에 깨끗하게 빠져나와 다음 시도로 넘어가도록 강제했습니다. 3 배포 시작 전 배터리 전원 상태 경고 로그 if pmset -g batt | grep -q "InternalBattery"; then echo "⚠️ 경고: 맥북이 배터리로 구동 중입니다. 슬립 방지를 위해 전원 어댑터 연결을 권장합니다." fi 💡 이번 트러블슈팅을 통해 얻은 교훈 로그를 맹신하지 말고 '실제 원격 상태'를 교차 검증하라 : 배포 모니터링 스크립트 자체가 버그를 일으킬 수 있습니다. 롤백 에러가 떴다고 당황하지 말고 서버의 systemd 저널과 실제 JAR 체크섬을 확인하는 습관이 중요합니다. 긴 세션 하나보다 짧은 세션 여러 개가 낫다 : 무인 자동화 환경에서 하나의 원격 커넥션을 오래 물고 있는 것은 시한폭탄입니다. 매 시도를 분리하고 멱등하게 만드세요. "안 끊기게 막는 것"보다 "끊겨도 다시 이어붙이는 설계"가 언제나 승리합니다.
What RADAR observed and classified to build this opportunity. It is what the source published, not a verification that the offer is still active.
[DevOps] 멀쩡히 성공한 새벽 배포가 왜 롤백됐을까? (macOS PowerNap과 SSH 끊김 오탐 해결기). 아침에 눈을 떴는데 슬랙과 로그에 찍힌 섬뜩한 메시지: *"치명적: 헬스체크 실패로 인한 자동 롤백까지 실패했습니다. 서비스 중단 위험!"* 심장이 철렁해서 급히 EC2 운영 서버를 확인했더니... 서비스는 1시간 전부터 아무 문제 없이 평온하게 200 OK를 뱉고 있었습니다. 멀쩡한 새 버전 배포를 '실패'로 오판하고 불필요한 롤백 지옥에 빠뜨렸던 범인, macOS 배터리 모드의 'Power Nap'과 장기 실행 SSH 파이프의 함정 을 파헤친 기록입니다. 🚨 1. 증상: 아침을 공포로 몰아넣은 새벽 배포 로그 새벽 3시 자동 배포 파이프라인의 로그(…
Open source