ルーティング規則と復元力の設定を書く
한국어 원문으로 표시합니다.
목표
VirtualService 로 요청을 조건에 따라 나누고, DestinationRule 로 대상의 성질과 복원력을 정하는 감각을 손에 넣습니다.
왜 중요한가
두 리소스의 역할 분리는 취향이 아니라 운영 구조입니다. 배포 파이프라인이 매번 건드리는 것은 라우팅(VirtualService)이고, 서비스 소유자가 한 번 정해 오래 두는 것은 대상의 성질(DestinationRule)입니다. 이 경계를 흐리면 배포 때마다 연결 풀 설정까지 함께 흔들립니다. 그리고 매칭 순서와 subset 의 라벨 일치, 이 두 가지가 메시 트러블슈팅의 절반입니다. 조건 없는 기본 경로를 위에 두면 아래 규칙이 죽고, subset 라벨이 파드 라벨과 어긋나면 엔드포인트가 비어 503(UH)이 납니다. 복원력 설정도 감으로 정하면 안 됩니다 — 전체 타임아웃이 시도 시간의 합보다 짧으면 재시도는 한 번도 못 하고 끝나고, 격리 상한이 없으면 서킷 브레이커가 전면 장애를 만듭니다.
이 환경에서는 패킷이 흐르지 않으므로, 채점은 매니페스트의 구조와 istioctl analyze 결과를 봅니다.
단계
시작 전 준비. 실습 파드는 실습마다 새로 뜨므로 앞 실습에서 설치한 메시 설정은 남아 있지 않습니다. kubectl get crd virtualservices.networking.istio.io 가 비어 있으면 먼저 istioctl manifest generate --set profile=minimal > /root/istio/manifest.yaml 로 매니페스트를 만들고 kubectl apply -f /root/istio/manifest.yaml 을 두 번 실행하세요(CRD 가 먼저 등록된 뒤에야 나머지가 붙습니다). 그다음 kubectl create ns mesh-lab && kubectl label ns mesh-lab istio-injection=enabled 로 네임스페이스를 준비합니다.
/opt/lab/fixtures/istio/workload-v1v2.yaml을mesh-lab네임스페이스에 적용하세요. Servicereviews의 첫 포트 이름은http여야 하고, Deploymentreviews-v1·reviews-v2의 파드 라벨은 각각app: reviews와version: v1/version: v2여야 합니다.mesh-lab에 DestinationRulereviews를 만드세요.spec.host는reviews이고,spec.subsets에 이름이v1(labels: {version: v1})과v2(labels: {version: v2})인 subset 두 개를 두세요.mesh-lab에 VirtualServicereviews를 만드세요.spec.hosts에reviews를 두고,spec.http의 마지막 항목에는match를 넣지 말고 destination 을host: reviews,subset: v1로 두세요.- 같은 VirtualService 의 앞쪽에 조건부 라우트를 추가하세요. 조건은 헤더
end-user가 정확히labhub-tester인 경우이고, 목적지는subset: v2입니다. 이 라우트는 마지막 기본 경로보다 위에 있어야 합니다. mesh-lab에 ratings 워크로드를 만드세요 — Serviceratings(포트 이름http, 포트 9080)와 Deploymentratings-v1(파드 라벨app: ratings,version: v1). 그다음 VirtualServiceratings를 만들어match의uri.prefix를/api/ratings로,rewrite.uri를/ratings로 두고 destination 은host: ratings로 하세요.- 같은 VirtualService
ratings의 라우트에timeout: 3s와retries를 붙이세요.attempts: 3,perTryTimeout: 1s,retryOn에는5xx,connect-failure를 포함하세요. 그리고/root/istio/traffic/out/retry-note.txt에 멱등하지 않은 요청(POST 등)을 재시도하면 왜 위험한지 적으세요. mesh-lab에 DestinationRuleratings를 만들고trafficPolicy.outlierDetection에consecutive5xxErrors: 5,interval: 10s,baseEjectionTime: 30s,maxEjectionPercent: 50을 넣으세요. 또 VirtualServiceratings에fault.delay를 추가해percentage.value: 10,fixedDelay: 2s로 두세요.istioctl analyze -n mesh-lab결과를/root/istio/traffic/out/analyze.txt에 저장하세요(Error [가 남으면 안 됩니다). 그리고/root/istio/traffic/out/routes.json을 만드세요.routes배열의 길이는 실제 VirtualServicereviews의spec.http항목 수와 같아야 하고, 배열의 마지막 원소에는match키를 넣지 마세요.default_subset키의 값은v1입니다.mesh-lab에는 VirtualService 가 2개 이상이어야 합니다.
참고
- 실습 파드는 실습마다 새로 뜨므로 앞 실습의 클러스터 상태는 남아 있지 않습니다. 그래서 메시 설정을 매니페스트로 남겨 두는 것이 곧 재현 가능성입니다. 선언적 설정의 가치가 추상적인 원칙이 아니라 이 실습에서 바로 체감되는 이유입니다.
kubectl apply -f - -n mesh-lab로 표준 입력에서 바로 적용할 수 있습니다. 적용 뒤에는kubectl get virtualservice reviews -n mesh-lab -o yaml로 실제 저장된 모습을 확인하세요.- 8번의 라우트 개수는
kubectl get virtualservice reviews -n mesh-lab -o json | jq '.spec.http | length'로 뽑으면 실수가 없습니다. - 5번에서 대상 워크로드를 만들지 않고 VirtualService 만 만들면 정적 분석이 "참조한 호스트를 찾을 수 없음" 오류를 냅니다. 8번이 그 오류를 잡아냅니다.
- 흔한 실수 1: 조건부 라우트를 배열 맨 뒤에 두는 것. 기본 경로가 먼저 잡아채 버려 조건이 무의미해집니다.
- 흔한 실수 2: subset 에
labels를 빠뜨리고 이름만 적는 것. 이름은 Envoy 클러스터 이름에 쓰일 뿐, 파드를 고르는 것은 라벨입니다.
대상 워크로드와 버전 라벨 올리기
/opt/lab/fixtures/istio/workload-v1v2.yaml 을 mesh-lab 네임스페이스에 적용하세요. Service reviews 의 첫 포트 이름은 http 여야 하고, Deployment reviews-v1·reviews-v2 의 파드 라벨은 각각 app: reviews 와 version: v1/version: v2 여야 합니다.
픽스처를 그대로 적용하면 됩니다. 다만 Service 포트에 이름이 있는지, 파드 템플릿에 app 과 version 라벨이 모두 있는지 확인하세요. 메시는 포트 이름으로 프로토콜을 판단합니다.
버전별 subset 정의하기
mesh-lab 에 DestinationRule reviews 를 만드세요. spec.host 는 reviews 이고, spec.subsets 에 이름이 v1(labels: {version: v1})과 v2(labels: {version: v2})인 subset 두 개를 두세요.
subset 은 이름만으로 파드를 고르지 않습니다. 각 subset 에 어떤 라벨로 파드를 고를지 적어야 하고, 그 라벨은 실제 파드 라벨과 같아야 합니다.
기본 경로를 v1 으로 보내기
mesh-lab 에 VirtualService reviews 를 만드세요. spec.hosts 에 reviews 를 두고, spec.http 의 마지막 항목에는 match 를 넣지 말고 destination 을 host: reviews, subset: v1 로 두세요.
조건 없는 라우트가 하나 있어야 매칭에 실패한 요청이 갈 곳이 생깁니다. 그 라우트는 배열의 맨 끝에 두세요.
헤더 조건으로 v2 로 보내기
같은 VirtualService 의 앞쪽에 조건부 라우트를 추가하세요. 조건은 헤더 end-user 가 정확히 labhub-tester 인 경우이고, 목적지는 subset: v2 입니다. 이 라우트는 마지막 기본 경로보다 위에 있어야 합니다.
매칭은 위에서 아래로 내려오며 처음 걸리는 것을 씁니다. 조건부 라우트가 기본 경로보다 아래에 있으면 영원히 실행되지 않습니다.
경로 접두어 매칭과 재작성
mesh-lab 에 ratings 워크로드를 만드세요 — Service ratings(포트 이름 http, 포트 9080)와 Deployment ratings-v1(파드 라벨 app: ratings, version: v1). 그다음 VirtualService ratings 를 만들어 match 의 uri.prefix 를 /api/ratings 로, rewrite.uri 를 /ratings 로 두고 destination 은 host: ratings 로 하세요.
바깥에 노출하는 경로와 뒷단이 아는 경로가 다를 때 씁니다. 대상 서비스가 클러스터에 없으면 정적 분석이 오류를 내니 워크로드도 함께 만드세요.
타임아웃과 재시도 붙이기
같은 VirtualService ratings 의 라우트에 timeout: 3s 와 retries 를 붙이세요. attempts: 3, perTryTimeout: 1s, retryOn 에는 5xx, connect-failure 를 포함하세요. 그리고 /root/istio/traffic/out/retry-note.txt 에 멱등하지 않은 요청(POST 등)을 재시도하면 왜 위험한지 적으세요.
재시도가 의미를 가지려면 전체 타임아웃 안에 시도들이 들어가야 합니다. 그리고 재시도해도 안전한 요청인지부터 따지세요.
이상치 감지와 결함 주입
mesh-lab 에 DestinationRule ratings 를 만들고 trafficPolicy.outlierDetection 에 consecutive5xxErrors: 5, interval: 10s, baseEjectionTime: 30s, maxEjectionPercent: 50 을 넣으세요. 또 VirtualService ratings 에 fault.delay 를 추가해 percentage.value: 10, fixedDelay: 2s 로 두세요.
격리에는 반드시 상한을 둡니다. 전부 빼 버리면 서비스가 통째로 죽습니다. 결함 주입도 비율을 지정해야 실험이 됩니다.
설정 검증하고 라우트 순서 정리하기
istioctl analyze -n mesh-lab 결과를 /root/istio/traffic/out/analyze.txt 에 저장하세요(Error [ 가 남으면 안 됩니다). 그리고 /root/istio/traffic/out/routes.json 을 만드세요. routes 배열의 길이는 실제 VirtualService reviews 의 spec.http 항목 수와 같아야 하고, 배열의 마지막 원소에는 match 키를 넣지 마세요. default_subset 키의 값은 v1 입니다. mesh-lab 에는 VirtualService 가 2개 이상이어야 합니다.
라우트 개수는 손으로 세지 말고 실제 리소스에서 뽑으세요. 기본 경로에는 조건이 없다는 사실이 정리 파일에도 드러나야 합니다.