Oracle Cloud 서버 접속 지연, 범인을 찾아 헤맨 기록

증상

운영 중인 서비스 사이트 접속이 눈에 띄게 느려졌습니다. 페이지 하나 뜨는 데 5초 가까이 걸렸고, 어떤 요청은 응답이 아예 안 오다시피 했습니다. 서버는 Oracle Cloud 인스턴스에서 Docker로 여러 서비스를 함께 돌리고 있었고, 최근에 딱히 뭔가를 바꾸지도 않은 상태였습니다.

원인을 좁혀나간 과정

1. 구간별로 나눠서 시간을 재기

막연히 “느리다”에서 시작하면 어디를 고쳐야 할지 알 수 없어서, curl로 구간별 시간을 하나씩 쪼개 쟀습니다.

curl -o /dev/null -s -w "dns:%{time_namelookup} connect:%{time_connect} tls:%{time_appconnect} ttfb:%{time_starttransfer} total:%{time_total}\n" https://내사이트주소/

로그인 리다이렉트를 거치는 구간까지 하나씩 홉을 나눠 쟀는데, 앞단의 개별 구간들은 모두 0.2~0.3초로 정상이었습니다. 그런데 전체는 5초가 넘었습니다. 개별 구간은 멀쩡한데 합치면 느린, 애매한 상황이었습니다.

2. 서버 자원 점검 — netdata 발견

서버 안에서 free -h, docker stats로 컨테이너별 자원 사용량을 봤습니다. 대부분 정상이었는데, 모니터링 도구로 띄워둔 netdata 컨테이너 하나가 눈에 띄었습니다.

  • CPU 사용률 73%
  • 메모리 한도(1GiB)의 99.99% 사용
  • 누적 디스크 I/O가 읽기 365GB, 쓰기 336GB (다른 컨테이너와 비교가 안 될 정도로 큼)

vmstat으로 들여다보니 swap 영역을 초당 10~16MB씩 계속 읽고 쓰고 있었고, 디스크 I/O 대기 비율도 23~26%나 됐습니다. 서버 전체 메모리는 14GB나 남아 있었는데도요.

원인은 docker-compose.yml에서 memswap_limit을 지정하지 않은 것이었습니다. Docker는 이 값을 따로 안 주면 mem_limit의 2배까지 자동으로 swap을 허용하는데, netdata가 1GiB 한도에 걸리자 메모리를 늘리는 대신 디스크의 swap 영역을 계속 오가며 버티고 있었던 것입니다.

docker stop netdata로 잠깐 꺼봤더니 swap 입출력이 즉시 0으로 떨어졌고, 사이트 응답 시간도 5초에서 1.8초로 줄었습니다. 그래서 이렇게 조치했습니다.

mem_limit: 2g
memswap_limit: 2g   # mem_limit과 동일하게 지정해 swap 사용을 아예 차단
mem_reservation: 512m

메모리 한도를 올리고, swap 자체를 못 쓰게 막아서 한도를 넘으면 디스크로 밀리는 대신 컨테이너가 재시작되도록 바꿨습니다.

3. 그런데 조치 후에도 여전히 느렸다

여기서 끝났으면 깔끔했을 텐데, netdata를 고친 뒤에도 브라우저로 확인해보니 일부 요청이 여전히 느렸습니다. 개발자 도구(Network 탭)에서는 정적 파일 요청이 응답을 못 받고 걸려 있었고, 없는 페이지(404)조차 1초 넘게 걸리는 경우가 있었습니다.

서버 내부에서 애플리케이션 컨테이너에 직접 요청해보면 언제나 1ms 수준으로 빨랐습니다. 즉 애플리케이션이나 nginx 설정 자체는 문제가 아니었습니다. 그런데 외부(PC)에서 반복 측정했을 때 간헐적으로 40~70초씩 걸리거나, Cloudflare가 origin 서버와 SSL 연결을 맺지 못했을 때 뜨는 525 에러가 튀어나왔습니다.

이때부터는 사이트가 이미 정상으로 돌아온 뒤라, 문제가 재현되지 않아 원인을 확정할 수 없었습니다.

결론: 두 가지가 겹쳤던 것으로 추정

지금 시점에서 정리하면 이렇습니다.

  • netdata의 swap 스래싱은 확실한 보조 원인이었습니다. 껐다 켜는 것만으로 응답 시간이 실측으로 줄어드는 것을 확인했으니, 적어도 지연을 키운 요인 중 하나는 맞습니다. 다만 이것만으로 5초라는 지연 전체를 설명하기엔 부족했습니다.
  • 더 크게 작용했을 것으로 보이는 원인은 Cloudflare와 서버(origin) 사이의 네트워크 문제였던 것 같습니다. 525 에러나 수십 초 단위의 지연은 애플리케이션이나 nginx가 아니라 이 구간에서만 나타날 수 있는 증상이기 때문입니다. 다만 이 부분은 로그나 지표로 명확히 잡아낸 게 아니라 정황상 추정입니다.
  • 문제가 자연적으로 가라앉았을 가능성도 있습니다. netdata 조치 이후 며칠 지켜보는 동안 재현되지 않았는데, 이게 조치의 효과인지 아니면 Cloudflare나 Oracle 네트워크 쪽의 일시적 문제가 그냥 지나간 것인지는 구분할 수 없었습니다. 즉 “완전히 해결했다”기보다는 “지금은 괜찮다” 쪽에 가깝습니다.

정리

단계확인한 것결과
구간별 curl 측정어느 구간에서 시간이 새는지앞단 홉은 정상, 합치면 느림
서버 자원 점검docker stats, vmstatnetdata의 swap 스래싱 발견 (보조 원인)
netdata 조치memswap_limit 추가일부 개선되었으나 완전 해결은 아님
추가 증상 발견외부 curl에서 40~70초 지연, 525 에러Cloudflare-서버 간 네트워크 문제로 추정
현재 상태재현 안 됨원인 미확정, 자연 정상화 가능성도 있어 계속 관찰 중

교훈: 지연의 원인이 하나라고 단정하지 않는 것이 중요했습니다. netdata 문제를 고쳤을 때 상황이 나아지긴 했지만 완전히 사라지지는 않았고, 그 사실 자체가 다른 원인이 더 있다는 신호였습니다. 지금도 원인을 100% 확정하지 못한 채로, 재발 여부를 지켜보는 중입니다. 인프라 문제는 “고쳤다”보다 “지금은 안 보인다” 정도로 겸손하게 접근하는 게 맞는 것 같습니다.