Deploy sample apps

You can install two sample apps in your demo setup: Bookinfo and httpbin. You might also install additional tools such as Keycloak as an OpenID Connect provider. These sample apps are used throughout the documentation to help test connectivity, such as in the policy guides.

Deploy Bookinfo

To test out microservice traffic management, deploy different versions of the Bookinfo sample app to both of the workload clusters. cluster1 runs the app with versions 1 and 2 of the reviews service (reviews-v1 and reviews-v2), and cluster2 runs version 3 of the reviews service (reviews-v3).

  1. Save the Istio revision that your istiod control planes run as an environment variable.

    export REVISION=$(kubectl get pod -L app=istiod -n istio-system --context $REMOTE_CONTEXT1 -o jsonpath='{.items[0].metadata.labels.istio\.io/rev}')
    echo $REVISION
    
  2. Create the bookinfo namespace in each cluster, and label the workload cluster namespaces for Istio injection so that the services become part of the service mesh.

    kubectl create ns bookinfo --context $MGMT_CONTEXT
    
    kubectl create ns bookinfo --context $REMOTE_CONTEXT1
    kubectl label ns bookinfo istio.io/rev=$REVISION --overwrite=true --context $REMOTE_CONTEXT1
    
    kubectl create ns bookinfo --context $REMOTE_CONTEXT2
    kubectl label ns bookinfo istio.io/rev=$REVISION --overwrite=true --context $REMOTE_CONTEXT2
    
  3. Deploy Bookinfo with the details, productpage, ratings, reviews-v1, and reviews-v2 services in cluster1.

    # deploy bookinfo application components for all versions less than v3
    kubectl -n bookinfo apply -f https://raw.githubusercontent.com/istio/istio/1.17.2/samples/bookinfo/platform/kube/bookinfo.yaml -l 'app,version notin (v3)' --context $REMOTE_CONTEXT1
    # deploy an updated product page with extra container utilities such as 'curl' and 'netcat'
    kubectl -n bookinfo apply -f https://raw.githubusercontent.com/solo-io/gloo-mesh-use-cases/main/policy-demo/productpage-with-curl.yaml
    # deploy all bookinfo service accounts --context $REMOTE_CONTEXT1
    kubectl -n bookinfo apply -f https://raw.githubusercontent.com/istio/istio/1.17.2/samples/bookinfo/platform/kube/bookinfo.yaml -l 'account' --context $REMOTE_CONTEXT1
    
  4. Deploy Bookinfo with the ratings and reviews-v3 services in cluster2.

    # deploy reviews and ratings services
    kubectl -n bookinfo apply -f https://raw.githubusercontent.com/istio/istio/1.17.2/samples/bookinfo/platform/kube/bookinfo.yaml -l 'service in (reviews)' --context $REMOTE_CONTEXT2
    # deploy reviews-v3
    kubectl -n bookinfo apply -f https://raw.githubusercontent.com/istio/istio/1.17.2/samples/bookinfo/platform/kube/bookinfo.yaml -l 'app in (reviews),version in (v3)' --context $REMOTE_CONTEXT2
    # deploy ratings
    kubectl -n bookinfo apply -f https://raw.githubusercontent.com/istio/istio/1.17.2/samples/bookinfo/platform/kube/bookinfo.yaml -l 'app in (ratings)' --context $REMOTE_CONTEXT2
    # deploy reviews and ratings service accounts
    kubectl -n bookinfo apply -f https://raw.githubusercontent.com/istio/istio/1.17.2/samples/bookinfo/platform/kube/bookinfo.yaml -l 'account in (reviews, ratings)' --context $REMOTE_CONTEXT2
    
  5. Verify that the Bookinfo pods have a status of Running in each cluster. If not, try Troubleshooting Bookinfo apps.

    kubectl get pods -n bookinfo --context $REMOTE_CONTEXT1
    kubectl get pods -n bookinfo --context $REMOTE_CONTEXT2
    

Deploy httpbin

The httpbin sample app is a simple tool to test HTTP requests and responses. Unlike curl, you can see not only the response headers, but also the request headers.

  1. Save the Istio revision that your istiod control planes run as an environment variable.

    export REVISION=$(kubectl get pod -L app=istiod -n istio-system --context $REMOTE_CONTEXT1 -o jsonpath='{.items[0].metadata.labels.istio\.io/rev}')
    echo $REVISION
    
  2. Create an httpbin namespace in cluster1, and label the namespace for Istio injection so that the services in the namespace become part of the service mesh.

    kubectl create ns httpbin --context $REMOTE_CONTEXT1
    kubectl label ns httpbin istio.io/rev=$REVISION --overwrite=true --context $REMOTE_CONTEXT1
    
  3. Deploy the httpbin app.

    kubectl -n httpbin apply -f https://raw.githubusercontent.com/solo-io/gloo-mesh-use-cases/main/policy-demo/httpbin.yaml --context $REMOTE_CONTEXT1
    
  4. Verify that the httpbin app is running.

    kubectl -n httpbin get pods --context $REMOTE_CONTEXT1
    

Deploy hello world

The hello world sample app is a simple way to test responses for different app versions. The following examples install two versions of hello world in one cluster, and two versions in the other workload cluster.

  1. Save the Istio revision that your istiod control planes run as an environment variable.

    export REVISION=$(kubectl get pod -L app=istiod -n istio-system --context $REMOTE_CONTEXT1 -o jsonpath='{.items[0].metadata.labels.istio\.io/rev}')
    echo $REVISION
    
  2. Create the helloworld namespace in each workload cluster, and label the namespaces for Istio injection so that the services become part of the service mesh.

    kubectl create ns helloworld --context $REMOTE_CONTEXT1
    kubectl label ns helloworld istio.io/rev=$REVISION --overwrite=true --context $REMOTE_CONTEXT1
    
    kubectl create ns helloworld --context $REMOTE_CONTEXT2
    kubectl label ns helloworld istio.io/rev=$REVISION --overwrite=true --context $REMOTE_CONTEXT2
    
  3. Deploy hello world v1 and v2 to cluster1.

    kubectl -n helloworld apply --context $REMOTE_CONTEXT1 -l 'service=helloworld' -f https://raw.githubusercontent.com/solo-io/gloo-mesh-use-cases/main/policy-demo/helloworld.yaml 
    kubectl -n helloworld apply --context $REMOTE_CONTEXT1 -l 'app=helloworld,version in (v1, v2)' -f https://raw.githubusercontent.com/solo-io/gloo-mesh-use-cases/main/policy-demo/helloworld.yaml 
    
  4. Deploy hello world v3 and v4 to cluster2.

    kubectl -n helloworld apply --context $REMOTE_CONTEXT2 -l 'service=helloworld' -f https://raw.githubusercontent.com/solo-io/gloo-mesh-use-cases/main/policy-demo/helloworld.yaml 
    kubectl -n helloworld apply --context $REMOTE_CONTEXT2 -l 'app=helloworld,version in (v3, v4)' -f https://raw.githubusercontent.com/solo-io/gloo-mesh-use-cases/main/policy-demo/helloworld.yaml 
    
  5. Verify that the hello world apps are running.

    kubectl -n helloworld get pods --context $REMOTE_CONTEXT1
    kubectl -n helloworld get pods --context $REMOTE_CONTEXT2
    

Install Keycloak

You might want to test how to restrict access to your applications to authenticated users, such as with external auth or JWT policies. You can install Keycloak in your cluster as an OpenID Connect (OIDC) provider.

The following steps install Keycloak in your cluster, and configure two user credentials as follows.

Install and configure Keycloak:

  1. Create a namespace for your Keycloak deployment.

    kubectl --context ${MGMT_CONTEXT} create namespace keycloak
    
  2. Create the Keycloak deployment.

    kubectl --context ${MGMT_CONTEXT} -n keycloak apply -f https://raw.githubusercontent.com/solo-io/workshops/master/gloo-mesh-2-3/all/data/steps/deploy-keycloak/keycloak.yaml
    
  3. Wait for the Keycloak rollout to finish.

    kubectl --context ${MGMT_CONTEXT} -n keycloak rollout status deploy/keycloak
    
  4. Set the Keycloak endpoint details from the load balancer service.

    export ENDPOINT_KEYCLOAK=$(kubectl --context ${MGMT_CONTEXT} -n keycloak get service keycloak -o jsonpath='{.status.loadBalancer.ingress[0].*}'):8080
    export HOST_KEYCLOAK=$(echo ${ENDPOINT_KEYCLOAK} | cut -d: -f1)
    export PORT_KEYCLOAK=$(echo ${ENDPOINT_KEYCLOAK} | cut -d: -f2)
    export KEYCLOAK_URL=http://${ENDPOINT_KEYCLOAK}/auth
    echo $KEYCLOAK_URL
    
  5. Set the Keycloak admin token. If you see a parsing error, try running the curl command by itself. You might notice that your network is blocking the requests, which might require updating the security settings so that the request can be processed.

    export KEYCLOAK_TOKEN=$(curl -d "client_id=admin-cli" -d "username=admin" -d "password=admin" -d "grant_type=password" "$KEYCLOAK_URL/realms/master/protocol/openid-connect/token" | jq -r .access_token)
    echo $KEYCLOAK_TOKEN
    
  6. Use the admin token to configure Keycloak with the two users for testing purposes. If you get a 401 Unauthorized error, run the previous command and try again.

    # Create initial token to register the client
    read -r client token <<<$(curl -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -X POST -H "Content-Type: application/json" -d '{"expiration": 0, "count": 1}' $KEYCLOAK_URL/admin/realms/master/clients-initial-access | jq -r '[.id, .token] | @tsv')
    export KEYCLOAK_CLIENT=${client}
    
    # Register the client
    read -r id secret <<<$(curl -X POST -d "{ \"clientId\": \"${KEYCLOAK_CLIENT}\" }" -H "Content-Type:application/json" -H "Authorization: bearer ${token}" ${KEYCLOAK_URL}/realms/master/clients-registrations/default| jq -r '[.id, .secret] | @tsv')
    export KEYCLOAK_SECRET=${secret}
    
    # Add allowed redirect URIs
    curl -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -X PUT -H "Content-Type: application/json" -d '{"serviceAccountsEnabled": true, "directAccessGrantsEnabled": true, "authorizationServicesEnabled": true, "redirectUris": ["'https://${ENDPOINT_HTTPS_GW_CLUSTER1}'/callback"]}' $KEYCLOAK_URL/admin/realms/master/clients/${id}
    
    # Add the group attribute in the JWT token returned by Keycloak
    curl -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -X POST -H "Content-Type: application/json" -d '{"name": "group", "protocol": "openid-connect", "protocolMapper": "oidc-usermodel-attribute-mapper", "config": {"claim.name": "group", "jsonType.label": "String", "user.attribute": "group", "id.token.claim": "true", "access.token.claim": "true"}}' $KEYCLOAK_URL/admin/realms/master/clients/${id}/protocol-mappers/models
    
    # Create first user
    curl -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -X POST -H "Content-Type: application/json" -d '{"username": "user1", "email": "user1@example.com", "enabled": true, "attributes": {"group": "users"}, "credentials": [{"type": "password", "value": "password", "temporary": false}]}' $KEYCLOAK_URL/admin/realms/master/users
    
    # Create second user
    curl -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -X POST -H "Content-Type: application/json" -d '{"username": "user2", "email": "user2@solo.io", "enabled": true, "attributes": {"group": "users"}, "credentials": [{"type": "password", "value": "password", "temporary": false}]}' $KEYCLOAK_URL/admin/realms/master/users
    

Next

Set up multicluster routing for the sample apps.