fix formatting in mirroring task (#15446)

* fix formatting in mirroring task

Signed-off-by: Peter Jausovec <peter.jausovec@solo.io>

* fix linting issues

Signed-off-by: Peter Jausovec <peter.jausovec@solo.io>

* updated snips

Signed-off-by: Peter Jausovec <peter.jausovec@solo.io>

* add namespace label back

Signed-off-by: Peter Jausovec <peter.jausovec@solo.io>

* ugh

Signed-off-by: Peter Jausovec <peter.jausovec@solo.io>

* getting there ...

Signed-off-by: Peter Jausovec <peter.jausovec@solo.io>

* remove the ns label at the end of the test

Signed-off-by: Peter Jausovec <peter.jausovec@solo.io>

* Update content/en/docs/tasks/traffic-management/mirroring/index.md

Co-authored-by: Michael <haifeng.yao@daocloud.io>

* indent the tab sections

Signed-off-by: Peter Jausovec <peter.jausovec@solo.io>

* pr feedback

Signed-off-by: Peter Jausovec <peter.jausovec@solo.io>

* typo fix

---------

Signed-off-by: Peter Jausovec <peter.jausovec@solo.io>
Co-authored-by: Michael <haifeng.yao@daocloud.io>
This commit is contained in:
Peter Jausovec 2024-07-29 02:41:35 -07:00 committed by GitHub
parent 4971bb33a1
commit e6ab3f286f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 287 additions and 295 deletions

View File

@ -21,97 +21,93 @@ you will apply a rule to mirror a portion of traffic to `v2`.
## Before you begin
* Set up Istio by following the instructions in the
[Installation guide](/docs/setup/).
1. Set up Istio by following the [Installation guide](/docs/setup/).
1. Start by deploying two versions of the [httpbin]({{< github_tree >}}/samples/httpbin) service that have access logging enabled:
* Start by deploying two versions of the [httpbin]({{< github_tree >}}/samples/httpbin) service that have access logging enabled:
1. Deploy `httpbin-v1`:
**httpbin-v1:**
{{< text bash >}}
$ cat <<EOF | istioctl kube-inject -f - | kubectl create -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpbin-v1
spec:
replicas: 1
selector:
matchLabels:
app: httpbin
version: v1
template:
{{< text bash >}}
$ kubectl create -f - <<EOF
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
EOF
{{< /text >}}
1. Deploy `httpbin-v2`:
{{< text bash >}}
$ kubectl create -f - <<EOF
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
EOF
{{< /text >}}
1. Deploy the `httpbin` Kubernetes service:
{{< text bash >}}
$ kubectl create -f - <<EOF
apiVersion: v1
kind: Service
metadata:
name: httpbin
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
EOF
{{< /text >}}
**httpbin-v2:**
{{< text bash >}}
$ cat <<EOF | istioctl kube-inject -f - | kubectl create -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpbin-v2
spec:
replicas: 1
selector:
matchLabels:
app: httpbin
version: v2
template:
metadata:
labels:
ports:
- name: http
port: 8000
targetPort: 80
selector:
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
EOF
{{< /text >}}
EOF
{{< /text >}}
**httpbin Kubernetes service:**
1. Deploy the `sleep` workload you'll use to send requests to the `httpbin` service:
{{< text bash >}}
$ kubectl create -f - <<EOF
apiVersion: v1
kind: Service
metadata:
name: httpbin
labels:
app: httpbin
spec:
ports:
- name: http
port: 8000
targetPort: 80
selector:
app: httpbin
EOF
{{< /text >}}
* Start the `sleep` service so you can use `curl` to provide load:
**sleep service:**
{{< text bash >}}
$ cat <<EOF | istioctl kube-inject -f - | kubectl create -f -
$ cat <<EOF | kubectl create -f -
apiVersion: apps/v1
kind: Deployment
metadata:
@ -139,100 +135,99 @@ you will apply a rule to mirror a portion of traffic to `v2`.
By default Kubernetes load balances across both versions of the `httpbin` service.
In this step, you will change that behavior so that all traffic goes to `v1`.
1. Create a default route rule to route all traffic to `v1` of the service:
1. Create a default route rule to route all traffic to `v1` of the service:
{{< tabset category-name="config-api" >}}
{{< tabset category-name="config-api" >}}
{{< tab name="Istio APIs" category-value="istio-apis" >}}
{{< tab name="Istio APIs" category-value="istio-apis" >}}
{{< text bash >}}
$ kubectl 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
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: httpbin
spec:
host: httpbin
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
EOF
{{< /text >}}
{{< text bash >}}
$ kubectl 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
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: httpbin
spec:
host: httpbin
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
EOF
{{< /text >}}
{{< /tab >}}
{{< /tab >}}
{{< tab name="Gateway API" category-value="gateway-api" >}}
{{< tab name="Gateway API" category-value="gateway-api" >}}
{{< text bash >}}
$ kubectl apply -f - <<EOF
apiVersion: v1
kind: Service
metadata:
name: httpbin-v1
spec:
ports:
- port: 80
name: http
selector:
app: httpbin
version: v1
---
apiVersion: v1
kind: Service
metadata:
name: httpbin-v2
spec:
ports:
- port: 80
name: http
selector:
app: httpbin
version: v2
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: httpbin
spec:
parentRefs:
- group: ""
{{< text bash >}}
$ kubectl apply -f - <<EOF
apiVersion: v1
kind: Service
name: httpbin
port: 8000
rules:
- backendRefs:
- name: httpbin-v1
port: 80
EOF
{{< /text >}}
metadata:
name: httpbin-v1
spec:
ports:
- port: 80
name: http
selector:
app: httpbin
version: v1
---
apiVersion: v1
kind: Service
metadata:
name: httpbin-v2
spec:
ports:
- port: 80
name: http
selector:
app: httpbin
version: v2
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: httpbin
spec:
parentRefs:
- group: ""
kind: Service
name: httpbin
port: 8000
rules:
- backendRefs:
- name: httpbin-v1
port: 80
EOF
{{< /text >}}
{{< /tab >}}
{{< /tab >}}
{{< /tabset >}}
{{< /tabset >}}
2) Now, with all traffic directed to `httpbin:v1`, send a request to the service:
1. Now, with all traffic directed to `httpbin:v1`, send a request to the service:
{{< text bash json >}}
$ export SLEEP_POD=$(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name})
$ kubectl exec "${SLEEP_POD}" -c sleep -- curl -sS http://httpbin:8000/headers
$ kubectl exec deploy/sleep -c sleep -- curl -sS http://httpbin:8000/headers
{
"headers": {
"Accept": "*/*",
@ -249,153 +244,150 @@ EOF
}
{{< /text >}}
3) Check the logs for `v1` and `v2` of the `httpbin` pods. You should see access
log entries for `v1` and none for `v2`:
1. Check the logs from `httpbin-v1` and `httpbin-v2` pods. You should see access log entries for `v1` and none for `v2`:
{{< text bash >}}
$ export V1_POD=$(kubectl get pod -l app=httpbin,version=v1 -o jsonpath={.items..metadata.name})
$ kubectl logs "$V1_POD" -c httpbin
$ kubectl logs deploy/httpbin-v1 -c httpbin
127.0.0.1 - - [07/Mar/2018:19:02:43 +0000] "GET /headers HTTP/1.1" 200 321 "-" "curl/7.35.0"
{{< /text >}}
{{< text bash >}}
$ export V2_POD=$(kubectl get pod -l app=httpbin,version=v2 -o jsonpath={.items..metadata.name})
$ kubectl logs "$V2_POD" -c httpbin
$ kubectl logs deploy/httpbin-v2 -c httpbin
<none>
{{< /text >}}
## Mirroring traffic to v2
## Mirroring traffic to `httpbin-v2`
1. Change the route rule to mirror traffic to v2:
1. Change the route rule to mirror traffic to `httpbin-v2`:
{{< tabset category-name="config-api" >}}
{{< tabset category-name="config-api" >}}
{{< tab name="Istio APIs" category-value="istio-apis" >}}
{{< text bash >}}
$ kubectl 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
{{< /text >}}
This route rule sends 100% of the traffic to `v1`. The last stanza specifies
that you want to mirror (i.e., also send) 100% of the same traffic to the
`httpbin:v2` service. When traffic gets mirrored,
the requests are sent to the mirrored service with their Host/Authority headers
appended with `-shadow`. For example, `cluster-1` becomes `cluster-1-shadow`.
Also, it is important to note that these requests are mirrored as "fire and
forget", which means that the responses are discarded.
You can use the `value` field under the `mirrorPercentage` field to mirror a fraction of the traffic,
instead of mirroring all requests. If this field is absent, all traffic will be mirrored.
{{< /tab >}}
{{< tab name="Gateway API" category-value="gateway-api" >}}
{{< text bash >}}
$ kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: httpbin
spec:
parentRefs:
- group: ""
kind: Service
name: httpbin
port: 8000
rules:
- filters:
- type: RequestMirror
requestMirror:
backendRef:
name: httpbin-v2
port: 80
backendRefs:
- name: httpbin-v1
port: 80
EOF
{{< /text >}}
This route rule sends 100% of the traffic to `v1`. The `RequestMirror` filter
specifies that you want to mirror (i.e., also send) 100% of the same traffic to the
`httpbin:v2` service. When traffic gets mirrored,
the requests are sent to the mirrored service with their Host/Authority headers
appended with `-shadow`. For example, `cluster-1` becomes `cluster-1-shadow`.
Also, it is important to note that these requests are mirrored as "fire and
forget", which means that the responses are discarded.
{{< /tab >}}
{{< /tabset >}}
2) Send in traffic:
{{< tab name="Istio APIs" category-value="istio-apis" >}}
{{< text bash >}}
$ kubectl exec "${SLEEP_POD}" -c sleep -- curl -sS http://httpbin:8000/headers
$ kubectl 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
{{< /text >}}
This route rule sends 100% of the traffic to `v1`. The last stanza specifies
that you want to mirror (i.e., also send) 100% of the same traffic to the
`httpbin:v2` service. When traffic gets mirrored,
the requests are sent to the mirrored service with their Host/Authority headers
appended with `-shadow`. For example, `cluster-1` becomes `cluster-1-shadow`.
Also, it is important to note that these requests are mirrored as "fire and
forget", which means that the responses are discarded.
You can use the `value` field under the `mirrorPercentage` field to mirror a fraction of the traffic,
instead of mirroring all requests. If this field is absent, all traffic will be mirrored.
{{< /tab >}}
{{< tab name="Gateway API" category-value="gateway-api" >}}
{{< text bash >}}
$ kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: httpbin
spec:
parentRefs:
- group: ""
kind: Service
name: httpbin
port: 8000
rules:
- filters:
- type: RequestMirror
requestMirror:
backendRef:
name: httpbin-v2
port: 80
backendRefs:
- name: httpbin-v1
port: 80
EOF
{{< /text >}}
This route rule sends 100% of the traffic to `v1`. The `RequestMirror` filter
specifies that you want to mirror (i.e., also send) 100% of the same traffic to the
`httpbin:v2` service. When traffic gets mirrored,
the requests are sent to the mirrored service with their Host/Authority headers
appended with `-shadow`. For example, `cluster-1` becomes `cluster-1-shadow`.
Also, it is important to note that these requests are mirrored as "fire and
forget", which means that the responses are discarded.
{{< /tab >}}
{{< /tabset >}}
1. Send the traffic:
{{< text bash >}}
$ kubectl exec deploy/sleep -c sleep -- curl -sS http://httpbin:8000/headers
{{< /text >}}
Now, you should see access logging for both `v1` and `v2`. The access logs
created in `v2` are the mirrored requests that are actually going to `v1`.
{{< text bash >}}
$ kubectl logs "$V1_POD" -c httpbin
$ kubectl logs deploy/httpbin-v1 -c httpbin
127.0.0.1 - - [07/Mar/2018:19:02:43 +0000] "GET /headers HTTP/1.1" 200 321 "-" "curl/7.35.0"
127.0.0.1 - - [07/Mar/2018:19:26:44 +0000] "GET /headers HTTP/1.1" 200 321 "-" "curl/7.35.0"
{{< /text >}}
{{< text bash >}}
$ kubectl logs "$V2_POD" -c httpbin
$ kubectl logs deploy/httpbin-v2 -c httpbin
127.0.0.1 - - [07/Mar/2018:19:26:44 +0000] "GET /headers HTTP/1.1" 200 361 "-" "curl/7.35.0"
{{< /text >}}
## Cleaning up
1. Remove the rules:
1. Remove the rules:
{{< tabset category-name="config-api" >}}
{{< tabset category-name="config-api" >}}
{{< tab name="Istio APIs" category-value="istio-apis" >}}
{{< tab name="Istio APIs" category-value="istio-apis" >}}
{{< text bash >}}
$ kubectl delete virtualservice httpbin
$ kubectl delete destinationrule httpbin
{{< /text >}}
{{< text bash >}}
$ kubectl delete virtualservice httpbin
$ kubectl delete destinationrule httpbin
{{< /text >}}
{{< /tab >}}
{{< /tab >}}
{{< tab name="Gateway API" category-value="gateway-api" >}}
{{< tab name="Gateway API" category-value="gateway-api" >}}
{{< text bash >}}
$ kubectl delete httproute httpbin
$ kubectl delete svc httpbin-v1 httpbin-v2
{{< /text >}}
{{< text bash >}}
$ kubectl delete httproute httpbin
$ kubectl delete svc httpbin-v1 httpbin-v2
{{< /text >}}
{{< /tab >}}
{{< /tab >}}
{{< /tabset >}}
{{< /tabset >}}
2) Shutdown the [httpbin]({{< github_tree >}}/samples/httpbin) service and client:
1. Delete `httpbin` and `sleep` deployments and `httpbin` service:
{{< text bash >}}
$ kubectl delete deploy httpbin-v1 httpbin-v2 sleep

View File

@ -22,7 +22,7 @@
source "content/en/boilerplates/snips/gateway-api-support.sh"
snip_before_you_begin_1() {
cat <<EOF | istioctl kube-inject -f - | kubectl create -f -
kubectl create -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
@ -50,7 +50,7 @@ EOF
}
snip_before_you_begin_2() {
cat <<EOF | istioctl kube-inject -f - | kubectl create -f -
kubectl create -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
@ -96,7 +96,7 @@ EOF
}
snip_before_you_begin_4() {
cat <<EOF | istioctl kube-inject -f - | kubectl create -f -
cat <<EOF | kubectl create -f -
apiVersion: apps/v1
kind: Deployment
metadata:
@ -195,8 +195,7 @@ EOF
}
snip_creating_a_default_routing_policy_3() {
export SLEEP_POD=$(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name})
kubectl exec "${SLEEP_POD}" -c sleep -- curl -sS http://httpbin:8000/headers
kubectl exec deploy/sleep -c sleep -- curl -sS http://httpbin:8000/headers
}
! IFS=$'\n' read -r -d '' snip_creating_a_default_routing_policy_3_out <<\ENDSNIP
@ -217,8 +216,7 @@ kubectl exec "${SLEEP_POD}" -c sleep -- curl -sS http://httpbin:8000/headers
ENDSNIP
snip_creating_a_default_routing_policy_4() {
export V1_POD=$(kubectl get pod -l app=httpbin,version=v1 -o jsonpath={.items..metadata.name})
kubectl logs "$V1_POD" -c httpbin
kubectl logs deploy/httpbin-v1 -c httpbin
}
! IFS=$'\n' read -r -d '' snip_creating_a_default_routing_policy_4_out <<\ENDSNIP
@ -226,15 +224,14 @@ kubectl logs "$V1_POD" -c httpbin
ENDSNIP
snip_creating_a_default_routing_policy_5() {
export V2_POD=$(kubectl get pod -l app=httpbin,version=v2 -o jsonpath={.items..metadata.name})
kubectl logs "$V2_POD" -c httpbin
kubectl logs deploy/httpbin-v2 -c httpbin
}
! IFS=$'\n' read -r -d '' snip_creating_a_default_routing_policy_5_out <<\ENDSNIP
<none>
ENDSNIP
snip_mirroring_traffic_to_v2_1() {
snip_mirroring_traffic_to_httpbinv2_1() {
kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
@ -257,7 +254,7 @@ spec:
EOF
}
snip_mirroring_traffic_to_v2_2() {
snip_mirroring_traffic_to_httpbinv2_2() {
kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
@ -282,24 +279,24 @@ spec:
EOF
}
snip_mirroring_traffic_to_v2_3() {
kubectl exec "${SLEEP_POD}" -c sleep -- curl -sS http://httpbin:8000/headers
snip_mirroring_traffic_to_httpbinv2_3() {
kubectl exec deploy/sleep -c sleep -- curl -sS http://httpbin:8000/headers
}
snip_mirroring_traffic_to_v2_4() {
kubectl logs "$V1_POD" -c httpbin
snip_mirroring_traffic_to_httpbinv2_4() {
kubectl logs deploy/httpbin-v1 -c httpbin
}
! IFS=$'\n' read -r -d '' snip_mirroring_traffic_to_v2_4_out <<\ENDSNIP
! IFS=$'\n' read -r -d '' snip_mirroring_traffic_to_httpbinv2_4_out <<\ENDSNIP
127.0.0.1 - - [07/Mar/2018:19:02:43 +0000] "GET /headers HTTP/1.1" 200 321 "-" "curl/7.35.0"
127.0.0.1 - - [07/Mar/2018:19:26:44 +0000] "GET /headers HTTP/1.1" 200 321 "-" "curl/7.35.0"
ENDSNIP
snip_mirroring_traffic_to_v2_5() {
kubectl logs "$V2_POD" -c httpbin
snip_mirroring_traffic_to_httpbinv2_5() {
kubectl logs deploy/httpbin-v2 -c httpbin
}
! IFS=$'\n' read -r -d '' snip_mirroring_traffic_to_v2_5_out <<\ENDSNIP
! IFS=$'\n' read -r -d '' snip_mirroring_traffic_to_httpbinv2_5_out <<\ENDSNIP
127.0.0.1 - - [07/Mar/2018:19:26:44 +0000] "GET /headers HTTP/1.1" 200 361 "-" "curl/7.35.0"
ENDSNIP

View File

@ -25,7 +25,7 @@ GATEWAY_API="${GATEWAY_API:-false}"
# @setup profile=default
kubectl label namespace default istio-injection- --overwrite
kubectl label namespace default istio-injection=enabled
# create the httpbin service
snip_before_you_begin_3
@ -67,9 +67,9 @@ _verify_contains send_request_and_get_v1_log "GET /headers HTTP/1.1"
_verify_not_contains snip_creating_a_default_routing_policy_5 "GET /headers HTTP/1.1"
if [ "$GATEWAY_API" == "true" ]; then
snip_mirroring_traffic_to_v2_2
snip_mirroring_traffic_to_httpbinv2_2
else
snip_mirroring_traffic_to_v2_1
snip_mirroring_traffic_to_httpbinv2_1
# wait for config
_wait_for_istio virtualservice default httpbin
@ -81,8 +81,8 @@ export V1_POD=$(kubectl get pod -l app=httpbin,version=v1 -o jsonpath={.items..m
export V2_POD=$(kubectl get pod -l app=httpbin,version=v2 -o jsonpath={.items..metadata.name})
send_request_and_get_v2_log() {
_verify_contains snip_mirroring_traffic_to_v2_3 "headers"
out=$(snip_mirroring_traffic_to_v2_5)
_verify_contains snip_mirroring_traffic_to_httpbinv2_3 "headers"
out=$(snip_mirroring_traffic_to_httpbinv2_5)
echo "$out"
}
_verify_contains send_request_and_get_v2_log "GET /headers HTTP/1.1"
@ -92,3 +92,6 @@ if [ "$GATEWAY_API" != "true" ]; then
snip_cleaning_up_1
snip_cleaning_up_3
fi
# Remove the label, otherwise the test fails (before/after snapshots won't match)
kubectl label namespace default istio-injection-