준비
이번에도 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 명세로 트래픽 미러링이 가능하다.
◦
◦
•
미러링 역시, Host 헤더에 -shadow 접미사를 붙인다는 것으로 보아, envoy 구현을 사용한다고 볼 수 있다.