-
[Cloud Run][운영] startup probe port가 맞지 않을 때 앱은 떴는데 revision이 준비되지 않는 이유기타개발지식/풀스택개발 2026. 6. 28. 09:16
IT 리서치 노트
[Cloud Run][운영] startup probe port가 맞지 않을 때 앱은 떴는데 revision이 준비되지 않는 이유
Cloud Run에서 앱 로그는 정상인데 revision이 계속 ready로 못 올라오면 path만 확인하고 넘어가는 경우가 많다. 하지만 2026년 6월 28일 기준 Cloud Run 공식 문서를 다시 보면 startup probe는 path뿐 아니라 port와 컨테이너의 실제 listen port까지 맞아야 한다. 이 글은 앱은 떴는데 revision이 준비되지 않는 상황을 port mismatch 기준으로 좁혀 정리한다.
1. 개요
결론부터 말하면 앱이 떴다는 로그와 revision이 준비됐다는 사실은 다를 수 있다. startup probe가 보는 port와 앱이 실제로 listen하는 port가 다르면 Cloud Run은 startup probe를 통과시키지 못하고, liveness와 readiness도 그 뒤로 밀린다. 그래서 이 증상은 timeout보다 먼저
PORT,containerPort,startupProbe.port를 함께 봐야 한다.Cloud Run은 기본적으로 8080으로 요청을 보낸다고 문서가 설명하고, local testing guide는 앱이 PORT 환경 변수를 기준으로 listen해야 한다고 적고 있다. 즉 앱 코드가 하드코딩된 3000을 듣고 있거나, 반대로 service 설정은 3000인데 probe는 8080을 때리는 구조면 revision은 계속 준비되지 않을 수 있다.
이미 startup probe path mismatch 글이 endpoint 이름 축을 다뤘다면, 이번 글은 port 축이다.
2. 어디서 실제로 막히는가
실무에서 흔한 증상은 세 가지다. 첫째, 앱 로그에는
listening on :3000같은 문장이 보이는데 revision은 ready로 못 올라온다. 둘째, startup probe path는 맞게 보이는데 connection refused가 반복된다. 셋째, 로컬에서는 잘 돌던 앱이 Cloud Run 배포 뒤에만 startup 단계에서 막힌다.이 문제는 path mismatch와 다르게 endpoint 자체가 없는 것이 아니라, probe가 틀린 port를 보고 있다는 점이 핵심이다. Cloud Run 가이드는 기본적으로 8080으로 요청을 보내고, 앱은 PORT 환경 변수에 맞춰 listen해야 한다고 설명한다. sample startup probe도 probe block에 port를 명시한다. 즉 코드와 설정이 한 문서 안에서 한 값으로 맞아야 한다.
특히 Express, FastAPI, Rails 같은 앱을 로컬 개발 습관대로 3000 또는 5000으로만 띄우는 경우가 흔하다. Cloud Run 쪽 container port는 8080으로 두고, startupProbe.port도 8080인데, 앱 코드만 3000을 듣고 있으면 앱은 떠도 probe는 계속 실패한다. 이때 timeout을 올려도 포트가 맞지 않으면 아무 일도 바뀌지 않는다.
- 증상: 앱 boot 로그는 정상인데 revision이 ready가 되지 않는다.
- 실패: path만 맞추고 port는 기본값이라고 가정한다.
- 막힘: 앱 listen port와 startupProbe.port를 같은 표로 놓고 보지 않는다.
- 누락: 앱 코드가 PORT 환경 변수를 읽는지 확인하지 않는다.
증상 먼저 볼 곳 판단 기준 connection refused PORT와 startupProbe.port 앱과 probe가 같은 port를 보는지 본다 404 또는 다른 endpoint 응답 startupProbe.path path mismatch를 의심한다 늦게라도 성공한다 timeoutSeconds와 failureThreshold slow startup인지 본다 3. 실무에서 적용하는 순서
점검 순서는 다섯 단계가 가장 빠르다. 먼저 앱 코드가
process.env.PORT또는 동등한 환경 변수를 실제로 읽는지 본다. 두 번째로 Cloud Run 서비스의 container port와 startupProbe.port를 나란히 확인한다. 세 번째로 앱이 실제 listen한 port 로그와 probe 실패 로그를 같은 시간순으로 본다. 네 번째로 로컬에서도-e PORT=8080같은 방식으로 같은 설정을 재현해 본다. 마지막으로 port가 맞는 것이 확인된 뒤에만 timeout 계열 값을 조정한다.- 앱 코드가 PORT 환경 변수를 읽는지 확인한다.
- container port와 startupProbe.port를 같은 값으로 맞춘다.
- 앱 listen 로그와 probe 실패 로그를 같은 타임라인으로 읽는다.
- 로컬에서도 같은 PORT 값을 주고 재현한다.
- port mismatch가 아닌 것이 확인된 뒤 timeout을 조정한다.
이 순서로 보면 설정 미스매치를 빨리 자를 수 있다. 예를 들어 앱이 3000을 듣고 있으면 service 설정을 3000으로 바꿀지, 아니면 앱을 PORT 기반으로 바꿔 8080을 따르게 할지 선택지가 선명해진다. 운영 관점에서는 후자가 재현성과 이식성이 더 좋다.
팀 문서에는 path와 port를 따로 적어 두는 편이 좋다. startup probe failure가 나면 endpoint 이름부터 볼지, port부터 볼지, timeout부터 볼지를 정해 두면 배포 중단 시간을 줄일 수 있다.
4. 공식 문서와 예시 화면으로 확인하기
첫 화면은 startup probe가 health check 체인의 맨 앞이라는 설명이다. revision이 준비되지 않을 때 liveness 문제로 먼저 오해하지 않기 위해 이 문장을 먼저 확인한다.
즉 앱 로그가 정상처럼 보여도 startup probe가 다른 port를 보고 있으면 revision은 계속 준비되지 않을 수 있다. 앱이 떴다는 감각과 probe가 성공했다는 사실은 다르다.
두 번째 자료는 공식 HTTP startup probe 샘플이다. 샘플 YAML을 보면 path뿐 아니라 port가 probe 블록 안에서 명시된다는 점이 보인다.
실무에서는 endpoint 이름만 맞추고 port는 기본값 8080으로 두는 경우가 많다. 하지만 앱이 실제로 3000이나 다른 port로 떠 있으면 probe는 계속 빗나간다.
세 번째 화면은 기존 웹 서비스를 Cloud Run으로 옮기는 가이드다. 여기서는 Cloud Run이 기본적으로 8080으로 요청을 보낸다고 설명한다.
이 문장을 놓치면 로컬에서는 3000으로 잘 돌던 앱이 Cloud Run에서만 readiness와 startup 단계에서 막히는 이유를 이해하기 어렵다. 기본 port와 앱 listen port를 같은 문서에서 맞춰 봐야 한다.
네 번째 자료는 local testing guide다. 문서는 PORT 환경 변수가 애플리케이션이 실제로 들어야 할 port라고 설명한다.
즉 probe port만 바꿀 문제가 아니라, 앱 코드가 PORT를 읽고 있는지부터 봐야 한다. probe가 8080을 때리고 있는데 앱은 하드코딩된 3000만 듣고 있으면 revision은 준비되지 않는다.
다섯 번째 화면은 container runtime contract다. 서비스 컨테이너는 요청을 받을 수 있도록 올바른 port에서 listen해야 한다는 계약을 다시 확인할 수 있다.
이 계약을 기준으로 보면 startup probe port mismatch는 단순 probe 옵션 문제가 아니라 컨테이너 계약 미스매치에 가깝다. 설정과 코드 둘 다 같이 봐야 하는 이유가 여기 있다.
설정 diff를 한 장으로 보면 실수가 빨리 드러난다. 앱은 3000을 듣고 있는데 Cloud Run 서비스와 probe는 8080을 보는 상황이 대표적이다.
이미 path mismatch 글을 읽었다면, 이번 diff는 path가 아니라 port 축이다.
로그를 시간순으로 놓으면 slow startup과 port mismatch가 나뉜다. 앱은 떠 있지만 probe는 계속 connection refused나 wrong port 신호를 낼 수 있다.
또 startup probe timeout 글과 비교하면, 이번 경우는 늦게 200이 오는 문제가 아니라 잘못된 port를 향하는 문제라는 점이 보인다.
마지막 자료는 triage 표다. path mismatch, port mismatch, slow startup은 모두 revision이 준비되지 않는다는 같은 증상으로 보이지만 먼저 볼 값이 다르다.
이 표를 기준으로 보면 503이 보인다고 무조건 timeout부터 올리거나 path만 수정하는 실수를 줄일 수 있다. 비용 영향까지 보려면 health check 비용 글도 같이 보는 편이 좋다.
5. 주의사항과 리스크
첫 번째 리스크는 앱 코드가 PORT 환경 변수를 무시하는 것이다. 두 번째 리스크는 service container port는 바꿨는데 startupProbe.port는 예전 값을 그대로 두는 것이다. 세 번째 리스크는 connection refused를 slow startup으로 오해해 timeout만 키우는 것이다.
또 framework별 기본 port도 함정이다. 로컬 개발 서버 습관 때문에 3000이나 5000을 하드코딩하면 Cloud Run 배포 때마다 비슷한 문제가 반복될 수 있다. 초기화 직후 바로 200을 주는 endpoint 설계가 readiness와 섞이지 않는지도 함께 봐야 한다.
- 앱은 PORT 환경 변수 기준으로 listen하도록 맞춘다.
- container port와 startupProbe.port를 따로 바꿨는지 점검한다.
- connection refused는 timeout보다 port mismatch를 먼저 의심한다.
6. 결론
Cloud Run에서 앱은 떠 있는데 revision이 준비되지 않는다면 startup probe port mismatch를 먼저 의심할 가치가 크다. path와 timeout만 보는 습관보다 앱의 실제 listen port, PORT 환경 변수, startupProbe.port를 한 표로 맞춰 보는 편이 훨씬 빠르다.
- 앱 listen port와 probe port를 같은 값으로 맞춘다.
- PORT 환경 변수를 읽는지 코드에서 먼저 확인한다.
- port가 맞는 뒤에만 timeout 조정으로 넘어간다.
7. 참고 링크
- https://docs.cloud.google.com/run/docs/configuring/healthchecks
- https://docs.cloud.google.com/run/docs/container-contract
- https://docs.cloud.google.com/run/docs/migrate/a-web-service
- https://docs.cloud.google.com/run/docs/testing/local
- https://docs.cloud.google.com/run/docs/samples/cloudrun-healthchecks-startup-probe-http
'기타개발지식 > 풀스택개발' 카테고리의 다른 글