Add a Broken Upstream and Watch the Cluster
한국어 원문으로 표시합니다.
목표
엔드포인트를 알아내는 방법과 성한지 판단하는 방법을 따로 세워 보고, 성한 것이 모자랄 때 Envoy 가 택하는 두 가지 길을 직접 만들어 본다.
왜 중요한가
프록시 운영에서 실제로 자주 보는 화면은 라우트 표가 아니라 클러스터 목록이다 — 어디에 서버가 몇 대이고 그중 몇 대가 성한가. 그 숫자를 읽을 줄 알면 503 신고의 절반은 그 자리에서 끝난다. 특히 패닉 모드는 한 번 눈으로 보지 않으면 운영에서 처음 만났을 때 '다 죽었는데 왜 계속 보내지' 에서 멈추게 된다. 우선순위 넘김도 마찬가지로, 설정만 읽어서는 언제 아래 단계가 트래픽을 받는지 감이 오지 않는다.
단계
- 업스트림 넷을 띄우세요 —
8084·8086는ok,8085·8087는fail입니다./root/envd-cluster/cluster.yaml에STATIC클러스터pool(엔드포인트8084·8085·8086)과/pool라우트를 두고 띄우세요(관리 9941, 리스너127.0.0.1:10041)./clusters에서pool::로 시작하는 줄만 골라/root/envd-cluster/01-pool.txt에 저장하세요. STRICT_DNS클러스터bydns를 더하세요 — 주소는localhost, 포트는8084이고dns_lookup_family는V4_ONLY입니다./bydns라우트도 함께 두세요./config_dump?resource=static_clusters에서 클러스터마다이름 타입한 줄씩 뽑아/root/envd-cluster/02-types.txt에 저장하세요.pool에 능동 헬스 체크를 더하세요 —interval1초,timeout1초, 두 임계값 모두 1,http_health_check의 경로는/healthz입니다. 잠시 뒤/clusters에서pool엔드포인트의health_flags줄만 골라/root/envd-cluster/03-health.txt에 저장하세요./pool로 12번 요청해 어느 업스트림이 받았는지 세어,/root/envd-cluster/04-spread.txt에p8084=·p8085=·p8086=·total=네 줄로 적으세요(값은 받은 횟수).- 클러스터
panic을 더하세요 — 엔드포인트는8085·8087둘 다fail이고 같은 능동 헬스 체크를 겁니다./panic라우트도 두세요. 6번 요청한 뒤/root/envd-cluster/05-panic.txt에codes=(받은 HTTP 코드들을 공백으로),lb_healthy_panic=(같은 이름의 통계 값),membership_healthy=세 줄을 적으세요. - 클러스터
tiered를 더하세요 —priority: 0에8085(fail),priority: 1에8086(ok) 를 두고 같은 능동 헬스 체크를 겁니다./tiered라우트도 두고 6번 요청해/root/envd-cluster/06-priority.txt에served_by=(응답한 포트),count=(그 포트가 받은 횟수) 두 줄을 적으세요. /root/envd-cluster/07-inventory.txt에 클러스터마다 한 줄씩이름 타입 엔드포인트수 성한수네 값을 공백으로 띄워 적으세요(이름 순서로 정렬). 값은 눈으로 세지 말고/config_dump와/stats에서 뽑습니다./root/envd-cluster/08-report.md에healthy=(pool 의 성한 엔드포인트 수),total=(pool 의 전체 엔드포인트 수),panic_requests_sent=(패닉 모드에서 요청이 나갔으면 yes),failover_port=(6단계에서 실제로 응답한 포트) 네 줄을 적고, 그 아래 배운 것을 네 줄 이상 적으세요.
참고
- 업스트림은
python3 /opt/lab/envoy/upstream.py <포트> ok|fail로 띄웁니다.fail은 어떤 경로로 물어도 503 을 돌려주므로 헬스 체크도 함께 떨어집니다. - Envoy 를 띄울 때는
setsid --fork nohup envoy -c <파일> --log-level warn --concurrency 1 > <로그> 2>&1 </dev/null를 쓰고, 다시 띄우기 전에는pkill -x envoy로 정리하세요. - 헬스 체크 주기가 1초이므로 설정을 올린 직후에는 아직 판정이 없습니다. 고정
sleep대신 원하는 상태가/clusters나/stats에 나타날 때까지 도는 루프를 쓰세요. /clusters는 엔드포인트 하나에 스무 줄 넘게 내놓습니다.grep 'health_flags'처럼 필요한 줄만 골라 담으세요.- 흔한 실수 — 이상치 감지와 능동 헬스 체크를 같은 것으로 여기는 것. 이 실습은 능동 쪽입니다.
이름 하나에 주소 셋을 매단다
업스트림 넷을 띄우세요 — 8084·8086 는 ok, 8085·8087 는 fail 입니다. /root/envd-cluster/cluster.yaml 에 STATIC 클러스터 pool(엔드포인트 8084·8085·8086)과 /pool 라우트를 두고 띄우세요(관리 9941, 리스너 127.0.0.1:10041). /clusters 에서 pool:: 로 시작하는 줄만 골라 /root/envd-cluster/01-pool.txt 에 저장하세요.
클러스터는 '이 이름으로 부를 수 있는 서버들' 의 묶음입니다. STATIC 은 주소를 설정에 그대로 적는 가장 단순한 방식이고, 그래서 설정을 바꾸지 않으면 목록도 바뀌지 않습니다. 업스트림은 python3 /opt/lab/envoy/upstream.py <포트> ok|fail 로 띄웁니다 — fail 은 어떤 경로로 물어도 503 을 돌려줍니다. /clusters 는 엔드포인트마다 여러 줄을 내놓으니 grep 으로 걸러 담으세요.
주소를 적는 대신 이름을 적는다
STRICT_DNS 클러스터 bydns 를 더하세요 — 주소는 localhost, 포트는 8084 이고 dns_lookup_family 는 V4_ONLY 입니다. /bydns 라우트도 함께 두세요. /config_dump?resource=static_clusters 에서 클러스터마다 이름 타입 한 줄씩 뽑아 /root/envd-cluster/02-types.txt 에 저장하세요.
엔드포인트를 알아내는 방법이 곧 클러스터의 type 입니다. STATIC 은 설정에 적은 주소, STRICT_DNS 는 이름을 주기적으로 다시 해석해 응답에 담긴 주소 전부를 엔드포인트로 삼고, LOGICAL_DNS 는 그중 하나만 붙들고 갑니다. EDS 는 컨트롤 플레인이 목록을 밀어 넣는 방식입니다. jq -r '.configs[]?.cluster | "\(.name) \(.type)"' 로 두 값을 뽑을 수 있습니다.
요청과 따로 주기적으로 찔러 본다
pool 에 능동 헬스 체크를 더하세요 — interval 1초, timeout 1초, 두 임계값 모두 1, http_health_check 의 경로는 /healthz 입니다. 잠시 뒤 /clusters 에서 pool 엔드포인트의 health_flags 줄만 골라 /root/envd-cluster/03-health.txt 에 저장하세요.
이상치 감지(outlier detection)는 실제 요청이 실패하는 것을 보고 빼내지만, 능동 헬스 체크는 요청과 상관없이 따로 찔러 봅니다. 그래서 트래픽이 없는 시간에도 상태를 알고, 고장 난 서버로 첫 요청이 가지 않습니다. 대신 서버마다 주기적인 부하가 하나씩 더 생깁니다. /clusters 의 health_flags 는 성하면 healthy, 능동 검사에 떨어지면 /failed_active_hc 입니다. 검사 주기가 1초이므로 설정을 올린 직후에는 아직 판정이 없을 수 있습니다 — 플래그가 나올 때까지 기다리세요.
성하지 않은 곳에는 보내지 않는다
/pool 로 12번 요청해 어느 업스트림이 받았는지 세어, /root/envd-cluster/04-spread.txt 에 p8084=·p8085=·p8086=·total= 네 줄로 적으세요(값은 받은 횟수).
부하 분산은 성한 엔드포인트들 사이에서만 돕니다. 그래서 능동 검사에 떨어진 하나는 요청을 한 번도 받지 않아야 합니다. 응답 본문에 포트가 들어 있으니 그것으로 셉니다. --concurrency 1 로 띄웠다면 성한 둘에 정확히 반씩 갈 것입니다.
성한 곳이 하나도 없으면 어떻게 하나
클러스터 panic 을 더하세요 — 엔드포인트는 8085·8087 둘 다 fail 이고 같은 능동 헬스 체크를 겁니다. /panic 라우트도 두세요. 6번 요청한 뒤 /root/envd-cluster/05-panic.txt 에 codes=(받은 HTTP 코드들을 공백으로), lb_healthy_panic=(같은 이름의 통계 값), membership_healthy= 세 줄을 적으세요.
성한 비율이 임계값(기본 50%) 아래로 떨어지면 Envoy 는 건강 정보를 무시하고 전부에게 보냅니다. 이것을 패닉 모드라고 합니다. 이상해 보이지만 판단은 단순합니다 — 검사가 틀렸을 가능성이 있는데 아무 데도 안 보내면 확실히 장애이고, 보내면 일부라도 살 수 있습니다. 일어났는지는 cluster.<이름>.lb_healthy_panic 통계로 봅니다. curl -s localhost:<admin>/stats | grep ... 으로 값만 꺼내세요.
위가 다 죽으면 아래로 넘어간다
클러스터 tiered 를 더하세요 — priority: 0 에 8085(fail), priority: 1 에 8086(ok) 를 두고 같은 능동 헬스 체크를 겁니다. /tiered 라우트도 두고 6번 요청해 /root/envd-cluster/06-priority.txt 에 served_by=(응답한 포트), count=(그 포트가 받은 횟수) 두 줄을 적으세요.
엔드포인트 묶음마다 priority 를 줄 수 있습니다. 평소에는 0 순위만 씁니다. 0 순위의 성한 비율이 떨어지면 모자란 만큼을 1 순위가 받고, 0 순위가 전멸하면 전부 1 순위로 갑니다. 다른 지역의 예비 서버를 평소에는 놀리다가 장애 때만 쓰는 구성이 이렇게 만들어집니다. /clusters 출력에 엔드포인트마다 priority 줄이 있어 어느 단계인지 확인할 수 있습니다.
네 클러스터의 목록을 만든다
/root/envd-cluster/07-inventory.txt 에 클러스터마다 한 줄씩 이름 타입 엔드포인트수 성한수 네 값을 공백으로 띄워 적으세요(이름 순서로 정렬). 값은 눈으로 세지 말고 /config_dump 와 /stats 에서 뽑습니다.
운영에서 가장 먼저 보는 표가 이것입니다 — 어느 클러스터에 서버가 몇 대이고 그중 몇 대가 성한가. cluster.<이름>.membership_total 과 membership_healthy 두 통계가 그 두 숫자입니다. 타입은 /config_dump?resource=static_clusters 에서 나옵니다. 두 곳에서 뽑은 값을 클러스터 이름으로 이어 붙이면 됩니다.
클러스터 운영 메모를 남긴다
/root/envd-cluster/08-report.md 에 healthy=(pool 의 성한 엔드포인트 수), total=(pool 의 전체 엔드포인트 수), panic_requests_sent=(패닉 모드에서 요청이 나갔으면 yes), failover_port=(6단계에서 실제로 응답한 포트) 네 줄을 적고, 그 아래 배운 것을 네 줄 이상 적으세요.
값은 앞 단계에서 만든 파일에서 가져오세요 — 기억으로 적으면 어긋납니다. 설명 줄에는 '능동 헬스 체크와 이상치 감지의 차이' 처럼 다음에 설계할 때 쓸 문장을 적으세요.