= Service Virtualization and Istio include::_attributes.adoc[] [IMPORTANT] .Before Start ==== You should have NO virtualservice nor destinationrule (in `tutorial` namespace) `kubectl get virtualservice` `kubectl get destinationrule` if so run: [source, bash] ---- ./scripts/clean.sh ---- ==== We'll create version 2 of preferences service. But in this case instead of communicating with recommendation service, we are going to communicate with a virtualized recommendation service. Service virtualization can be understood as something similar as mocking where instead of mocking components (classes), you are mocking remote services. For this concrete case, virtualized recommendation service will return `recommendation v2 from 'virtualized': 2`. [#deploypreferencev2] == Deploy Preference:v2 Move to preference directory: [source, bash] ---- cd preference/java/springboot ---- Change `PreferencesController.java` like the following and creating a "v2" docker image. [source,java] ---- private static final String RESPONSE_STRING_FORMAT = "PREFERENCE => %s\n"; ---- The "v2" tag during the Docker build is significant. There is also a second `deployment.yml` file to label things correctly === Docker build (if you have access to Docker daemon) [source, bash] ---- mvn clean package docker build -t example/preference:v2 . ---- IMPORTANT: We have a 2nd Deployment to manage the v2 version of preference. [source,bash,subs="+macros,+attributes"] ---- oc apply -f <(istioctl kube-inject -f link:{github-repo}/{preference-repo}/kubernetes/Deployment-v2.yml[../../kubernetes/Deployment-v2.yml]) -n tutorial oc get pods -w cd ../../.. ---- === OpenShift S2I strategy (if you DON’T have access to Docker daemon) [source, bash] ---- mvn clean package -f preference/java/springboot oc new-app -l app=preference,version=v2 --name=preference-v2 --context-dir=preference/java/springboot -e JAEGER_SERVICE_NAME=preference JAEGER_ENDPOINT=http://jaeger-collector.istio-system.svc:14268/api/traces JAEGER_PROPAGATION=b3 JAEGER_SAMPLER_TYPE=const JAEGER_SAMPLER_PARAM=1 JAVA_OPTIONS='-Xms128m -Xmx256m -Djava.net.preferIPv4Stack=true' fabric8/s2i-java~https://github.com/redhat-developer-demos/istio-tutorial -o yaml > preference-v2.yml oc apply -f <(istioctl kube-inject -f preference-v2.yml) -n tutorial oc cancel-build bc/preference-v2 oc delete svc/preference-v2 oc start-build preference-v2 --from-dir=. --follow ---- === Wait for v2 to be deployed Wait for those pods to show "2/2", the istio-proxy/envoy sidecar is part of that pod ---- NAME READY STATUS RESTARTS AGE customer-3647816848-j5xd5 2/2 Running 25 14d preference-v1-406256754-8v7x5 2/2 Running 12 2h preference-v2-3602772496-wmkvl 2/2 Running 12 2h recommendation-v1-2409176097-kcjsr 2/2 Running 8 14d recommendation-v2-1275713543-2bs5k 2/2 Running 4 2d ---- and test the customer endpoint [source, bash] ---- curl customer-tutorial.$(minishift ip).nip.io ---- you likely see "customer => preference => recommendation v2 from '2819441432-5v22s': 1" as by default you get round-robin load-balancing when there is more than one Pod behind a Service Send several requests to see their responses [source, bash] ---- ./scripts/run.sh ---- The default Kubernetes/OpenShift behavior is to round-robin load-balance across all available pods behind a single Service. So after running several times you'll get some combinations of: ---- customer => preference => recommendation v1 from '2409176097-kcjsr': 3 customer => PREFERENCE => recommendation v1 from '2409176097-kcjsr': 4 customer => preference => recommendation v2 from '1275713543-2bs5k': 3 customer => PREFERENCE => recommendation v2 from '1275713543-2bs5k': 3 ---- [#servicevirtualization] == Adding Service Virtualization We'll create a Docker image with Hoverfly (Service Virtualization tool) with some canned requests/answers for recommendation service. [source, bash,subs="+macros,+attributes"] ---- cd recommendation/virtualized docker build -t example/recommendation:virtualized . docker images | grep recommendation oc apply -f <(istioctl kube-inject -f link:{github-repo}/{preference-repo}/kubernetes/Deployment-virtualized.yml[../../kubernetes/Deployment-virtualized.yml]) -n tutorial oc get pods -w cd ../.. ---- After this step, you should have three versions of recommendation service (v1, v2 and virtualized). ---- NAME READY STATUS RESTARTS AGE customer-3647816848-j5xd5 2/2 Running 25 14d preference-v1-406256754-8v7x5 2/2 Running 12 2h preference-v2-3602772496-wmkvl 2/2 Running 12 2h recommendation-v1-2409176097-kcjsr 2/2 Running 8 14d recommendation-v2-1275713543-2bs5k 2/2 Running 4 2d recommendation-virtualized-2649197284-rp9cg 2/2 Running 2 3h ---- Send several requests to see their responses [source, bash] ---- ./scripts/run.sh ---- The default Kubernetes/OpenShift behavior is to round-robin load-balance across all available pods behind a single Service. So after running several times you'll get some combinations of: ---- customer => preference => recommendation v1 from '2409176097-kcjsr': 3 customer => PREFERENCE => recommendation v1 from '2409176097-kcjsr': 2 customer => preference => recommendation v1 from 'virtualized': 2 customer => PREFERENCE => recommendation v1 from 'virtualized': 2 customer => preference => recommendation v2 from '1275713543-2bs5k' customer => PREFERENCE => recommendation v2 from '1275713543-2bs5k' customer => preference => recommendation v2 from 'virtualized': 2 customer => PREFERENCE => recommendation v2 from 'virtualized': 2 ---- Notice that now the `v2` reaches all recommendation services. Let's avoid this by just sending traffic that comes from preference v2 service to the virtualized recommendation service. [source, bash,subs="+macros,+attributes"] ---- istioctl create -f link:{github-repo}/{istiofiles-dir}/destination-rule-recommendation-v1.yml[istiofiles/destination-rule-recommendation-v1.yml] -n tutorial istioctl create -f link:{github-repo}/{istiofiles-dir}/virtual-service-recommendation-virtualized.yml[istiofiles/virtual-service-recommendation-virtualized.yml] -n tutorial ---- Then do again some requests and you'll get something like: ---- customer => preference => recommendation v1 from '2409176097-kcjsr': 5 customer => PREFERENCE => recommendation v1 from 'virtualized': 2 customer => preference => recommendation v2 from '1275713543-2bs5k': 6 customer => PREFERENCE => recommendation v2 from 'virtualized': 2 ---- Now all requests that are from preference v2 are redirected to virtualized recommendation service. In this way when you deploy a new service, you can mirror the traffic without worrying about side-effects on other services, since the requests are redirected to a virtualized instance instead of a production one. [#cleanup] == Clean up [source,bash,subs="+macros,+attributes"] ---- istioctl delete -f istiofiles/destination-rule-recommendation-v1.yml -n tutorial istioctl delete -f istiofiles/virtual-service-recommendation-virtualized.yml -n tutorial oc delete all -l app=preference,version=v2 oc delete all -l app=recommendation,version=virtualized ----