Search

Istio Tasks; Traffic Management - Mirroring

준비

이번에도 httpbin을 사용할 것이다. v1과 v2 두 deployment를 만들어 v1으로 향하는 모든 트래픽을 v2로 미러링할 것이다:
httpbin-v1/v2를 만들고 같은 서비스로 노출한다. 또 curl을 쓰기 위한 sleep 파드도 배포한다:
--- apiVersion: apps/v1 kind: Deployment metadata: name: httpbin-v1 spec: replicas: 1 selector: matchLabels: app: httpbin version: v1 template: metadata: labels: app: httpbin version: v1 spec: containers: - image: docker.io/kennethreitz/httpbin imagePullPolicy: IfNotPresent name: httpbin command: ["gunicorn", "--access-logfile", "-", "-b", "0.0.0.0:80", "httpbin:app"] ports: - containerPort: 80 --- apiVersion: apps/v1 kind: Deployment metadata: name: httpbin-v2 spec: replicas: 1 selector: matchLabels: app: httpbin version: v2 template: metadata: labels: app: httpbin version: v2 spec: containers: - image: docker.io/kennethreitz/httpbin imagePullPolicy: IfNotPresent name: httpbin command: ["gunicorn", "--access-logfile", "-", "-b", "0.0.0.0:80", "httpbin:app"] ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: httpbin labels: app: httpbin spec: ports: - name: http port: 8000 targetPort: 80 selector: app: httpbin --- apiVersion: apps/v1 kind: Deployment metadata: name: sleep spec: replicas: 1 selector: matchLabels: app: sleep template: metadata: labels: app: sleep spec: containers: - name: sleep image: curlimages/curl command: ["/bin/sleep","3650d"] imagePullPolicy: IfNotPresent
YAML
복사
기본적인 virutalservice와 destinationrule로 트래픽 라우팅을 구성한다. 우선 모든 트래픽은 v1으로 향하게 한다:
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: httpbin spec: hosts: - httpbin http: - route: - destination: host: httpbin subset: v1 weight: 100 --- apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: httpbin spec: host: httpbin subsets: - name: v1 labels: version: v1 - name: v2 labels: version: v2
YAML
복사
sleep에서 httpbin으로 요청한다. 로그를 통해 v1으로만 요청이 들어 오는 것을 확인한다(kiali로도 확인할 수 있다):
❯ k exec $(k get po -l app=sleep -oyaml | yq .items[0].metadata.name) -c sleep -- curl -sS http://httpbin:8000/headers { "headers": { "Accept": "*/*", "Host": "httpbin:8000", "User-Agent": "curl/8.5.0", "X-B3-Parentspanid": "ec56eb535fd80806", "X-B3-Sampled": "0", "X-B3-Spanid": "451ae65e56d0fdf4", "X-B3-Traceid": "cd1609e289db9f3cec56eb535fd80806", "X-Envoy-Attempt-Count": "1", "X-Forwarded-Client-Cert": "By=spiffe://cluster.local/ns/default/sa/default;Hash=6096145df3f8a0d6982a8d7be0109e4ea0632910db60c2ba8f83a1e8a527d804;Subject=\"\";URI=spiffe://cluster.local/ns/default/sa/default" } } # v1 logs ❯ k logs $(k get po -l app=httpbin,version=v1 -oyaml | yq .items[0].metadata.name) [2024-01-07 00:57:28 +0000] [1] [INFO] Starting gunicorn 19.9.0 [2024-01-07 00:57:28 +0000] [1] [INFO] Listening at: http://0.0.0.0:80 (1) [2024-01-07 00:57:28 +0000] [1] [INFO] Using worker: sync [2024-01-07 00:57:28 +0000] [8] [INFO] Booting worker with pid: 8 127.0.0.6 - - [07/Jan/2024:00:57:31 +0000] "GET /headers HTTP/1.1" 200 524 "-" "curl/8.5.0" # v2 logs ❯ k logs $(k get po -l app=httpbin,version=v2 -oyaml | yq .items[0].metadata.name) [2024-01-07 00:57:28 +0000] [1] [INFO] Starting gunicorn 19.9.0 [2024-01-07 00:57:28 +0000] [1] [INFO] Listening at: http://0.0.0.0:80 (1) [2024-01-07 00:57:28 +0000] [1] [INFO] Using worker: sync [2024-01-07 00:57:28 +0000] [9] [INFO] Booting worker with pid: 9
Shell
복사

미러링

v1의 모든 트래픽이 v2로 미러링 되도록 virtualservice를 수정한다:
$ k apply -f - <<EOF apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: httpbin spec: hosts: - httpbin http: - route: - destination: host: httpbin subset: v1 weight: 100 mirror: host: httpbin subset: v2 mirrorPercentage: value: 100.0 EOF
Shell
복사
❯ k diff -f - <<EOF apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: httpbin spec: hosts: - httpbin http: - route: - destination: host: httpbin subset: v1 weight: 100 mirror: host: httpbin subset: v2 mirrorPercentage: value: 100.0 EOF diff -u -N /var/folders/4s/w6k_cdvd52s1hst64dr_yw540000gn/T/LIVE-4019362111/networking.istio.io.v1alpha3.VirtualService.default.httpbin /var/folders/4s/w6k_cdvd52s1hst64dr_yw540000gn/T/MERGED-1971230782/networking.istio.io.v1alpha3.VirtualService.default.httpbin --- /var/folders/4s/w6k_cdvd52s1hst64dr_yw540000gn/T/LIVE-4019362111/networking.istio.io.v1alpha3.VirtualService.default.httpbin 2024-01-07 10:03:19.879651504 +0900 +++ /var/folders/4s/w6k_cdvd52s1hst64dr_yw540000gn/T/MERGED-1971230782/networking.istio.io.v1alpha3.VirtualService.default.httpbin 2024-01-07 10:03:19.879870879 +0900 @@ -5,7 +5,7 @@ kubectl.kubernetes.io/last-applied-configuration: | {"apiVersion":"networking.istio.io/v1alpha3","kind":"VirtualService","metadata":{"annotations":{},"name":"httpbin","namespace":"default"},"spec":{"hosts":["httpbin"],"http":[{"route":[{"destination":{"host":"httpbin","subset":"v1"},"weight":100}]}]}} creationTimestamp: "2024-01-07T00:57:14Z" - generation: 1 + generation: 2 name: httpbin namespace: default resourceVersion: "289751" @@ -14,7 +14,12 @@ hosts: - httpbin http: - - route: + - mirror: + host: httpbin + subset: v2 + mirrorPercentage: + value: 100 + route: - destination: host: httpbin subset: v1
Diff
복사
이렇게 구성하면 실제 v1으로 가는 요청의 Host/Authority 헤더 뒤에 -shadow 를 붙인 요청이 v2로 가게 된다(미러링을 쉐도잉이라고도 한다).
# v1 logs ❯ k logs $(k get po -l app=httpbin,version=v1 -oyaml | yq .ite ms[0].metadata.name) [2024-01-07 11:36:03 +0000] [1] [INFO] Starting gunicorn 19.9.0 [2024-01-07 11:36:03 +0000] [1] [INFO] Listening at: http://0.0.0.0:80 (1) [2024-01-07 11:36:04 +0000] [1] [INFO] Using worker: sync [2024-01-07 11:36:04 +0000] [9] [INFO] Booting worker with pid: 9 127.0.0.6 - - [07/Jan/2024:11:36:13 +0000] "GET /headers HTTP/1.1" 200 524 "-" "curl/8.5.0" 127.0.0.6 - - [07/Jan/2024:11:37:51 +0000] "GET /headers HTTP/1.1" 200 524 "-" "curl/8.5.0"
Shell
복사
# v2 logs ❯ k logs $(k get po -l app=httpbin,version=v2 -oyaml | yq .items[0].metadata.name) [2024-01-07 11:36:04 +0000] [1] [INFO] Starting gunicorn 19.9.0 [2024-01-07 11:36:04 +0000] [1] [INFO] Listening at: http://0.0.0.0:80 (1) [2024-01-07 11:36:04 +0000] [1] [INFO] Using worker: sync [2024-01-07 11:36:04 +0000] [9] [INFO] Booting worker with pid: 9 127.0.0.6 - - [07/Jan/2024:11:37:51 +0000] "GET /headers HTTP/1.1" 200 564 "-" "curl/8.5.0"
Shell
복사
로그에서 두번째 요청부턴 초단위론 같은 시각에 v2에도 요청이 처리됨을 확인할 수 있다. 다만, kiali 그래프에선 v2로 향하는 heathy edge를 확인할 순 없고, virtualservice에 Mirroring 뱃지만 생긴다.

습득 교훈

virtualservice 명세로 트래픽 미러링이 가능하다.
spec.hosts[].mirrorDestination 선언과
spec.hosts[].mirrorPercentagePercent 선언
미러링 역시, Host 헤더에 -shadow 접미사를 붙인다는 것으로 보아, envoy 구현을 사용한다고 볼 수 있다.