Rails6 업데이트를 Production에 발표하면 실례에 의해 죽습니다

6595 단어 Rails
눈에 잘 띄지 않고 소박하게 기능이 추가되어 살해되었다

좋아!Rails6 업데이트 발표!


실행bundle update rails, 수정 테스트를 모두 통과하고 워닝을 격파하며 Staging으로 동작을 꼼꼼히 확인했습니다.
그리고 이제 문제 없어!나와도 돼요!발행 시기가 갈수록 높아질 때 사건이 발생했다.

제품이지만 회사 내부의 폐쇄적인 환경에 발표되다


전체 프로덕션에 발표하기 전에 회사 내부에 격리된 프로덕션 환경을 발표했다.
순조롭게 발매됐는데, "흥, 괜찮겠지?"갑자기 503개의 오류가 발생해서 별로 말이 없어졌다.
오류 모니터링(Sentry)을 봐도 적용 오류가 발생한 흔적은 없습니다.
나는 또 무슨 일이 일어난 줄 알고 급히 응용 서버에 ssh를 보내고 응용 로그를 보았다.
그러나 특별히 뚜렷한 오류는 발견되지 않았다.
원인을 조사할 때 ssh가 갑자기 차단되었다.
실례가terminate에 걸린 것 같은데...

예?왜 난리야?


역시 급해요.
사내용으로 폐쇄된 환경이라 영향 범위가 사내에만 한정된 것은 불행 중 다행이다.
직원 여러분에 대한 조사를 계속할 수 없습니다.
AWS 콘솔에서terminate 인스턴스에 대한 정보를 보면 CPU 사용률과 메모리 사용률 등도 이상 상승하지 않았다.
그리고 회사 내에서도 회복된 것 같다는 목소리가 나온다.

어?나 아무것도 안 했어???


이유도 모르고 아무것도 안 했는데 확실히 회복됐어요.
terminate에 의한 실례를 대체하는 것 같습니다. 새로운 실례가 생겼습니다.
새로운 실례가 정신적으로 요구를 판매하고 있다.
새 인스턴스는 Rais6을 업데이트하기 전에 수행됩니다.

Auto Scaling?


아무렇게나 일어나, Auto Scoling이야?
그렇게 생각하면서 Auto Scoling을 봤습니다.
확실히 활동 역사상 테미나팅의 역사가 있다.
원인으로 보아

system health check failure.
Auto Scalling(ELB)으로부터의 건강검진에 응하지 않아 unhealty로 취급되는 실례terminate의 절차인 것 같다.
응, 그렇구나...근데 왜??

nginx의 접근 로그 보기


나는 응용 프로그램 오류가 원인이 아닌 것 같다는 것을 안다.
그럼, 무슨 이유일까요?
건강검진에 응하지 못하는데, 원래 건강검진의 요구는 무엇입니까?나는nginx의 방문 로그를 보았다고 생각한다.
나는 새로 일어난 건강 실례를 보고nginx의 방문 로그를 보았다.
time:<アクセス時間> host:192.168.0.54       uri:/health     status:200      size:33 reqsize:-       method:GET      referer:-       ua:ELB-HealthChecker/2.0        reqtime:0.008   apptime:0.008   upstream:127.0.0.1:8080 vhost:192.168.8.12
time:<アクセス時間> host:192.168.2.116      uri:/health     status:200      size:33 reqsize:-       method:GET      referer:-       ua:ELB-HealthChecker/2.0        reqtime:0.013   apptime:0.012   upstream:127.0.0.1:8080 vhost:192.168.8.12
time:<アクセス時間> host:192.168.1.89       uri:/health     status:200      size:33 reqsize:-       method:GET      referer:-       ua:ELB-HealthChecker/2.0        reqtime:0.007   apptime:0.000   upstream:127.0.0.1:8080 vhost:192.168.8.12
이런 느낌으로 건강검진 요청이 들어왔습니다.status:200가 돌아왔다.
그나저나 레일스 앱의 동작을 확인하기 위해 건강검진 요청을 받을 수 있는 엔드포인트를 준비했다.
config/routes.rb
get '/health' => 'health_statuses#show'
이 상태에서 Rails6 업데이트를 다시 발표했습니다.

아, 역시 또 떨어졌구나


순조롭게 발행된 후,nginx의 방문 로그
time:<アクセス時間> host:192.168.0.54       uri:/health     status:403      size:1187       reqsize:-       method:GET      referer:-       ua:ELB-HealthChecker/2.0        reqtime:0.024   apptime:0.024   upstream:127.0.0.1:8080 vhost:192.168.8.12
time:<アクセス時間> host:192.168.2.116      uri:/health     status:403      size:1187       reqsize:-       method:GET      referer:-       ua:ELB-HealthChecker/2.0        reqtime:0.005   apptime:0.008   upstream:127.0.0.1:8080 vhost:192.168.8.12
time:<アクセス時間> host:192.168.1.89       uri:/health     status:403      size:1187       reqsize:-       method:GET      referer:-       ua:ELB-HealthChecker/2.0        reqtime:0.002   apptime:0.000   upstream:127.0.0.1:8080 vhost:192.168.8.12
오, 바뀌었어status:403.
이 상태에서 몇 십 초가 지나자 아까와 마찬가지로 실례terminate가 ssh를 차단했습니다.
테미네이트가 헬스를 하는 실례에 의해 ELB 측에서 503을 잃어버렸기 때문이다.

Rails6에서 403 오류를 반환하는 변경 사항


네, ActionDispatch::HostAuthorization 그렇죠?
제품 환경에서 다음은config입니다.hosts를 설정했습니다.
config.hosts << '.example.com'
ELB로부터의 건강검진은 host:192.168.0.54처럼 IP 주소를 지정한 형태여서 ActionDispatch::HostAuthorization 검사에서 403 오류가 발생했다.

어떻게 회피했어


다음은 config입니다.hosts 설정이 완료되었습니다.
config.hosts.clear
이렇게 하면 ActionDispatch::HostAuthorization 검사를 비활성화할 수 있습니다.(어렵게 추가한 기능이 무효화되어 마음이 아프다...
나중에 찾아보니 config였어요.hosts를 설정하지 않으면 기본적으로 개발자 환경 이외에 검사되지 않습니다.
In other environments Rails.application.config.hosts is empty and no Host header checks will be done.
우선 건강검진에 호응해 회사 내부용 프로덕션 환경에 발표할 수 있다.
이후에도 전체 프로덕션에 순조롭게 발매

총결산


ELB의 건강 검진을 사용할 때 주의하십시오ActionDispatch::HostAuthorization.
이번에 ELB는 제품iod라는 인프라 시설만 다르기 때문에 Staging은 눈치채지 못했다.
각 환경의 차이를 잘 고려할 필요가 있다.
원래 제품과 Staging 인프라 구성도 완전히 일치해야 한다.
하지만 여러 가지 일 때문에 하지 못하는 경우도 있어 어렵다.
그리고 Staging과 제품 사이에 버퍼링이 하나 더 있는데 회사 내부에 폐쇄된 제품 환경이 정말 큰 도움이 됐어요.
갑자기 전체 프로덕션에 발표되면 전체 실례가 사망하고 서비스가 정지되는 최악의 사태가 발생할 것이다
선인의 지혜와 노력에 감사 드립니다

좋은 웹페이지 즐겨찾기