Uh oh!
There was an error while loading. Please reload this page.
FIX : 실제로 도는 배포로 교체 (라우터 API 의존 제거, SSH 키 로드) - #97
Merged
Conversation
머지해도 배포가 되지 않는 상태였다. 저장소 쪽에서 고칠 수 있는 부분을 정리한다. (시크릿 값 자체는 저장소 밖이라 #94 에 남겨둔다.) 1) SSH 개인키를 올리는 스텝이 아예 없었다. ssh -o StrictHostKeyChecking=no 로 바로 접속하고 있어서, 시크릿을 채워도 인증 단계에서 막힌다. 키를 env 로 받아 ~/.ssh 에 쓰고 -i 로 지정한다. 호스트키는 *_SSH_KNOWN_HOSTS 가 있으면 고정하고, 없으면 keyscan 으로 대체하되 경고를 남긴다. 2) 시크릿이 없을 때 무엇이 없는지 알 수 없었다. 각 스텝의 test -n "..." 는 실패 이유를 남기지 않는다. 잡 시작 시점에 필요한 이름을 전부 확인하고, 빠진 것을 이름으로 찍어 실패시킨다. 3) 롤백이 트래픽 전환 전에도 돌았다. 조건이 failure() 뿐이라, 배포·헬스체크에서 죽어 트래픽이 움직인 적도 없는데 롤백을 시도했고 그 스텝마저 실패해 로그에 실패가 두 번 찍혔다. steps.switch.outcome == 'success' 를 함께 본다. 4) 알림이 echo 뿐이라 배포 실패가 아무에게도 닿지 않았다. 잡 요약에 남기고, 실패는 ::error:: 로 올린다. OPS_SLACK_WEBHOOK_URL 이 있으면 슬랙으로도 보낸다. 5) 시크릿을 run 본문에 ${{ secrets.* }} 로 직접 박아 쓰던 것을 env 로 옮겼다. 값이 스크립트 텍스트에 들어가면 셸 메타문자에 취약하다. 6) 전역 env 의 헬스 URL 을 제거했다. 배포와 무관한 test/scan 잡 환경에까지 값이 실릴 이유가 없다. 필요한 스텝만 시크릿을 받는다. 모든 run 블록을 bash -n 으로 문법 검사했다.
6 tasks
Blue/Green 전환의 마지막 단계가 라우터 HTTP API 두 개를 호출했다. PRODUCTION_ROUTER_STATUS_URL 현재 활성 색 조회 PRODUCTION_ROUTER_SWITCH_URL 트래픽 전환 이 API 를 제공하는 구현이 조직 어디에도 없다. 별도 저장소의 블루/그린 도구 (CareCode_Nohub_Deploy)는 paramiko 로 서버에 붙어 nginx conf 를 고치는 CLI 이고 의존성이 requests/python-dotenv/paramiko 뿐이다. 웹 서버가 아니다. 그래서 시크릿을 다 채워도 전환 단계에서 반드시 멈췄다. 게다가 그 시점에는 이미 Deploy 단계가 서버의 컨테이너를 갈아치운 뒤라, 새 컨테이너는 떠 있는데 트래픽은 넘어가지 않은 어중간한 상태로 끝났다. 무중단은 nginx 를 제어할 수 있어야 성립한다. 그때까지는 검증 후 교체로 간다. 새 이미지 pull → 예비 포트(127.0.0.1:18082)에서 먼저 기동 운영 컨테이너는 그대로 → 헬스체크. 실패하면 로그를 남기고 중단 운영은 건드리지 않음 → 통과하면 교체 (짧은 순단) → 재확인 → 외부 URL 로 최종 확인 깨진 이미지가 운영에 올라가지 않는다는 성질은 유지하고 순단만 감수한다. 검증 포트는 예전 blue/green 의 8083 과 겹치지 않게 18082 로 잡았다. 함께 정리한 것 - 레지스트리 로그인을 추가했다. 토큰은 stdin 으로 넘긴다. ssh 인자로 주면 서버의 프로세스 목록에 그대로 보인다. - 필요한 시크릿이 8개에서 4개로 줄었다. HOST / USER / SSH_KEY / HEALTH_URL 이면 된다. - 컨테이너에 --restart unless-stopped 를 붙였다. 서버가 재부팅돼도 살아난다. - 예전 워크플로가 만들던 carecode-blue / carecode-green 이 남아 포트를 잡고 있으면 교체가 실패하므로 함께 정리한다. - 외부 확인 실패는 메시지를 따로 준다. 서버 안에서는 UP 인데 밖에서 안 보이면 프록시나 보안그룹 문제지 애플리케이션 문제가 아니다. 라우터 방식으로 돌아가려면 전환 API 를 실제로 만든 뒤에 되돌리면 된다. 워크플로 run 블록 16개와 원격 스크립트를 bash -n 으로 문법 검사했다.
Uh oh!
There was an error while loading. Please reload this page.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🏫 관련 이슈
#94
시크릿 값과 서버 준비는 저장소 밖이라 이 PR 로 닫히지 않는다. 아래 "머지 후 할 일" 참고.
🏫 PR 타입
🏫 반영 브랜치
fix/deploy-pipeline-ssh-and-alerts->main🏫 변경 사항
main에 머지해도 배포가 되지 않는다. #78, #80, #96 세 번 모두 실패했다.시크릿 미설정이 눈에 보이는 원인이지만, 채워도 완주할 수 없는 구조였다.
1. 존재하지 않는 라우터 API 에 의존하고 있었다 ⭐
Blue/Green 전환의 마지막 단계가 HTTP 엔드포인트 두 개를 호출한다.
이 API 를 제공하는 구현이 조직 어디에도 없다.
별도 저장소의 블루/그린 도구
CareCode_Nohub_Deploy는paramiko 로 서버에 붙어 nginx conf 를 고치는 CLI 다. HTTP 서버가 아니다.
더 나쁜 건 실패 지점이다. 시크릿을 다 채우면
Deploy단계가 성공해서 서버 컨테이너를이미 갈아치운 뒤
Switch traffic에서 멈춘다. 새 컨테이너는 떠 있는데 트래픽은넘어가지 않은 어중간한 상태로 끝난다.
→ 검증 후 교체 방식으로 바꿨다.
무중단은 잃지만 깨진 이미지가 운영에 올라가지 않는다는 성질은 유지된다.
진짜 무중단은 nginx 를 제어할 수 있을 때 되돌리면 된다.
2. SSH 개인키를 올리는 스텝이 아예 없었다 ⭐
ssh -o StrictHostKeyChecking=no ${{ secrets.PRODUCTION_DEPLOY_USER }}@...키를 로드하는 곳이 워크플로 어디에도 없다. 시크릿을 전부 채워도 인증에서 막힌다.
키를
env로 받아~/.ssh/deploy_key에 쓰고-i로 지정한다.호스트키는
*_SSH_KNOWN_HOSTS가 있으면 고정, 없으면ssh-keyscan+ 경고.StrictHostKeyChecking=no는 제거했다.3. 레지스트리 로그인이 없었다
서버가 GHCR 에서 이미지를 받으려면 로그인이 필요할 수 있다.
잡 토큰을 stdin 으로 흘려보낸다. ssh 인자로 주면 서버 프로세스 목록에 그대로 보인다.
4. 무엇이 없는지 알 수 없었다
test -n "${{ secrets.X }}"는 실패 이유를 남기지 않는다.로그에
PRODUCTION_HEALTH_URL:이 공란으로 찍히는 게 전부였다.5. 배포 실패가 아무에게도 닿지 않았다
성공이든 실패든
echo "Production deployment completed"하나였다.잡 요약에 남기고 실패는
::error::로 올린다.OPS_SLACK_WEBHOOK_URL이 있으면 슬랙으로도 보낸다.6. 그 밖
run:본문에${{ secrets.* }}로 직접 박아 쓰던 것을 전부env:로env의 헬스 URL 제거 — test/scan 잡 환경에까지 실릴 이유가 없다--restart unless-stopped— 서버 재부팅에도 살아남는다carecode-blue/carecode-green이 남아 포트를 잡고 있으면 교체가 실패하므로 함께 정리필요한 시크릿이 8개 → 4개
_DEPLOY_HOST_DEPLOY_USER_HEALTH_URL_ROUTER_STATUS_URL_ROUTER_SWITCH_URL_ROUTER_TOKEN_TARGET_HEALTH_URL_TEMPLATE(+ 없던 SSH 키)_DEPLOY_HOST_DEPLOY_USER_SSH_KEY_HEALTH_URL🏫 테스트 결과
워크플로는 CI 에서 직접 돌려볼 수 없어 정적으로 확인했다.
앱 코드는 건드리지 않았으므로 기존 테스트 380건은 그대로다.
🏫 머지 후 할 일 (#94)
저장소 밖이라 여기서 할 수 없다.
시크릿 4개
서버
docker실행 가능~/.ssh/authorized_keys에 등록/opt/carecode/.env존재, 그 안에EMAIL_VERIFICATION_BASE_URL포함 ([ Infra ] #80 머지 전 운영 전제 확인 (XFF 신뢰, 리프레시 토큰 저장소) #90)없으면 검증 단계에서 걸린다. 운영은 무사하지만 배포는 실패한다
준비되면 Actions 에서
workflow_dispatch→production으로 한 번 돌려보면 된다.🏫 To Reviewer
무중단이 꼭 필요하면 라우터 API 를 만들거나([ Infra ] 운영 배포 파이프라인이 시크릿 미설정으로 계속 실패한다 #94 의 B안),
CareCode_Nohub_Deploy를SSH 로 호출하는 방식(C안)으로 가야 한다. 지금은 "되는 배포" 를 우선했다.
carecode로 통일했다. 서버에 다른 이름으로 돌고 있는 게 있으면교체 단계의 정리 목록에 추가해야 한다.
-p 8082:8082로 모든 인터페이스에 바인딩하는 건 그대로 뒀다. 프록시 구성을 모르는상태에서
127.0.0.1:로 좁히면 nginx 가 다른 호스트일 때 깨진다. 확인은 [ Infra ] #80 머지 전 운영 전제 확인 (XFF 신뢰, 리프레시 토큰 저장소) #90.