Integrate Dapr with OSM

Dapr OSM Walkthrough

This document walks you through the steps of getting Dapr working with OSM on a Kubernetes cluster.

  1. Install Dapr on your cluster with mTLS disabled:

    1. Dapr has a quickstart repository to help users get familiar with dapr and its features. For this integration demo we will be leveraging the hello-kubernetes quickstart. As we would like to integrate this Dapr example with OSM, there are a few modifications required and they are as follows:

      • The hello-kubernetes demo installs Dapr with mtls enabled (by default), we would not want mtls from Dapr and would like to leverage OSM for this. Hence while installing Dapr on your cluster, make sure to disable mtls by passing the flag : --enable-mtls=false during the installation

      • Further hello-kubernetes sets up everything in the default namespace, it is strongly recommended to set up the entire hello-kubernetes demo in a specific namespace (we will later join this namespace to OSM’s mesh). For the purpose of this integration, we have the namespace as dapr-test

        1. $ kubectl create namespace dapr-test
        2. namespace/dapr-test created
      • The redis state store, redis.yaml, node.yaml and python.yaml need to be deployed in the dapr-test namespace

      • Since the resources for this demo are set up in a custom namespace. We will need to add an rbac rule on the cluster for Dapr to have access to the secrets. Create the following role and role binding:

        1. kubectl apply -f - <<EOF
        2. ---
        3. apiVersion: rbac.authorization.k8s.io/v1
        4. kind: Role
        5. metadata:
        6. name: secret-reader
        7. namespace: dapr-test
        8. rules:
        9. - apiGroups: [""]
        10. resources: ["secrets"]
        11. verbs: ["get", "list"]
        12. ---
        13. kind: RoleBinding
        14. apiVersion: rbac.authorization.k8s.io/v1
        15. metadata:
        16. name: dapr-secret-reader
        17. namespace: dapr-test
        18. subjects:
        19. - kind: ServiceAccount
        20. name: default
        21. roleRef:
        22. kind: Role
        23. name: secret-reader
        24. apiGroup: rbac.authorization.k8s.io
        25. EOF
    2. Ensure the sample applications are running with Dapr as desired.

  2. Install OSM:

    1. $ osm install
    2. OSM installed successfully in namespace [osm-system] with mesh name [osm]
  3. Enable permissive mode in OSM:

    1. $ kubectl patch meshconfig osm-mesh-config -n osm-system -p '{"spec":{"traffic":{"enablePermissiveTrafficPolicyMode":true}}}' --type=merge
    2. meshconfig.config.openservicemesh.io/osm-mesh-config patched

    This is necessary, so that the hello-kubernetes example works as is and no SMI policies are needed from the get go.

  4. Exclude kubernetes API server IP from being intercepted by OSM’s sidecar:

    1. Get the kubernetes API server cluster IP:

      1. $ kubectl get svc -n default
      2. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
      3. kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 1d
    2. Add this IP to the MeshConfig so that outbound traffic to it is excluded from interception by OSM’s sidecar

      1. $ kubectl patch meshconfig osm-mesh-config -n osm-system -p '{"spec":{"traffic":{"outboundIPRangeExclusionList":["10.0.0.1/32"]}}}' --type=merge
      2. meshconfig.config.openservicemesh.io/osm-mesh-config patched

    It is necessary to exclude the Kubernetes API server IP in OSM because Dapr leverages Kubernetes secrets to access the redis state store in this demo.

    Note: If you have hardcoded the password in the Dapr component file, you may skip this step.

  5. Globally exclude ports from being intercepted by OSM’s sidecar:

    1. Get the ports of Dapr’s placement server (dapr-placement-server):

      1. $ kubectl get svc -n dapr-system
      2. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
      3. dapr-api ClusterIP 10.0.172.245 <none> 80/TCP 2h
      4. dapr-dashboard ClusterIP 10.0.80.141 <none> 8080/TCP 2h
      5. dapr-placement-server ClusterIP None <none> 50005/TCP,8201/TCP 2h
      6. dapr-sentry ClusterIP 10.0.87.36 <none> 80/TCP 2h
      7. dapr-sidecar-injector ClusterIP 10.0.77.47 <none> 443/TCP 2h
    2. Get the ports of your redis state store from the redis.yaml, 6379incase of this demo

    3. Add these ports to the MeshConfig so that outbound traffic to it is excluded from interception by OSM’s sidecar

      1. $ kubectl patch meshconfig osm-mesh-config -n osm-system -p '{"spec":{"traffic":{"outboundPortExclusionList":[50005,8201,6379]}}}' --type=merge
      2. meshconfig.config.openservicemesh.io/osm-mesh-config patched

    It is necessary to globally exclude Dapr’s placement server (dapr-placement-server) port from being intercepted by OSM’s sidecar, as pods having Dapr on them would need to talk to Dapr’s control plane. The redis state store also needs to be excluded so that Dapr’s sidecar can route the traffic to redis, without being intercepted by OSM’s sidecar.

    Note: Globally excluding ports would result in all pods in OSM’s mesh from not interceting any outbound traffic to the specified ports. If you wish to exclude the ports selectively only on pods that are running Dapr, you may omit this step and follow the step mentioned below.

  6. Exclude ports from being intercepted by OSM’s sidecar at pod level:

    1. Get the ports of Dapr’s api and sentry (dapr-sentry and dapr-api):

      1. $ kubectl get svc -n dapr-system
      2. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
      3. dapr-api ClusterIP 10.0.172.245 <none> 80/TCP 2h
      4. dapr-dashboard ClusterIP 10.0.80.141 <none> 8080/TCP 2h
      5. dapr-placement-server ClusterIP None <none> 50005/TCP,8201/TCP 2h
      6. dapr-sentry ClusterIP 10.0.87.36 <none> 80/TCP 2h
      7. dapr-sidecar-injector ClusterIP 10.0.77.47 <none> 443/TCP 2h
    2. Update the pod spec in both nodeapp (node.yaml) and pythonapp (python.yaml) to contain the following annotation: openservicemesh.io/outbound-port-exclusion-list: "80"

    Adding the annotation to the pod excludes Dapr’s api (dapr-api) and sentry (dapr-sentry) port’s from being intercepted by OSM’s sidecar, as these pods would need to talk to Dapr’s control plane.

  7. Make OSM monitor the namespace that was used for the Dapr hello-kubernetes demo setup:

    1. $ osm namespace add dapr-test
    2. Namespace [dapr-test] successfully added to mesh [osm]
  8. Delete and re-deploy the Dapr hello-kubernetes pods:

    1. $ kubectl delete -f ./deploy/node.yaml
    2. service "nodeapp" deleted
    3. deployment.apps "nodeapp" deleted
    1. $ kubectl delete -f ./deploy/python.yaml
    2. deployment.apps "pythonapp" deleted
    1. $ kubectl apply -f ./deploy/node.yaml
    2. service "nodeapp" created
    3. deployment.apps "nodeapp" created
    1. $ kubectl apply -f ./deploy/python.yaml
    2. deployment.apps "pythonapp" created

    The pythonapp and nodeapp pods on restart will now have 3 containers each, indicating OSM’s proxy sidecar has been successfully injected

    1. $ kubectl get pods -n dapr-test
    2. NAME READY STATUS RESTARTS AGE
    3. my-release-redis-master-0 1/1 Running 0 2h
    4. my-release-redis-slave-0 1/1 Running 0 2h
    5. my-release-redis-slave-1 1/1 Running 0 2h
    6. nodeapp-7ff6cfb879-9dl2l 3/3 Running 0 68s
    7. pythonapp-6bd9897fb7-wdmb5 3/3 Running 0 53s
  9. Verify the Dapr hello-kubernetes demo works as expected:

    1. Verify the nodeapp service using the steps documented here

    2. Verify the pythonapp documented here

  10. Applying SMI Traffic Policies:

    The demo so far illustrated permissive traffic policy mode in OSM whereby application connectivity within the mesh is automatically configured by osm-controller, therefore no SMI policy was required for the pythonapp to talk to the nodeapp.

    In order to see the same demo work with an SMI Traffic Policy, follow the steps outlined below:

    1. Disable permissive mode:

      1. $ kubectl patch meshconfig osm-mesh-config -n osm-system -p '{"spec":{"traffic":{"enablePermissiveTrafficPolicyMode":false}}}' --type=merge
      2. meshconfig.config.openservicemesh.io/osm-mesh-config patched
    2. Verify the pythonapp documented here no longer causes the order ID to increment.

    3. Create a service account for nodeapp and pythonapp:

      1. $ kubectl create sa nodeapp -n dapr-test
      2. serviceaccount/nodeapp created
      1. $ kubectl create sa pythonapp -n dapr-test
      2. serviceaccount/pythonapp created
    4. Update the role binding on the cluster to contain the newly created service accounts:

      1. kubectl apply -f - <<EOF
      2. ---
      3. kind: RoleBinding
      4. apiVersion: rbac.authorization.k8s.io/v1
      5. metadata:
      6. name: dapr-secret-reader
      7. namespace: dapr-test
      8. subjects:
      9. - kind: ServiceAccount
      10. name: default
      11. - kind: ServiceAccount
      12. name: nopdeapp
      13. - kind: ServiceAccount
      14. name: pythonapp
      15. roleRef:
      16. kind: Role
      17. name: secret-reader
      18. apiGroup: rbac.authorization.k8s.io
      19. EOF
    5. Apply the following SMI access control policies:

      Deploy SMI TrafficTarget

      1. kubectl apply -f - <<EOF
      2. ---
      3. kind: TrafficTarget
      4. apiVersion: access.smi-spec.io/v1alpha3
      5. metadata:
      6. name: pythodapp-traffic-target
      7. namespace: dapr-test
      8. spec:
      9. destination:
      10. kind: ServiceAccount
      11. name: nodeapp
      12. namespace: dapr-test
      13. rules:
      14. - kind: HTTPRouteGroup
      15. name: nodeapp-service-routes
      16. matches:
      17. - new-order
      18. sources:
      19. - kind: ServiceAccount
      20. name: pythonapp
      21. namespace: dapr-test
      22. EOF

      Deploy HTTPRouteGroup policy

      1. kubectl apply -f - <<EOF
      2. ---
      3. apiVersion: specs.smi-spec.io/v1alpha4
      4. kind: HTTPRouteGroup
      5. metadata:
      6. name: nodeapp-service-routes
      7. namespace: dapr-test
      8. spec:
      9. matches:
      10. - name: new-order
      11. EOF
    6. Update the pod spec in both nodeapp (node.yaml) and pythonapp (python.yaml) to contain their respective service accounts. Delete and re-deploy the Dapr hello-kubernetes pods

    7. Verify the Dapr hello-kubernetes demo works as expected, shown here

  11. Cleanup:

    1. To clean up the Dapr hello-kubernetes demo, clean the dapr-test namespace

      1. $ kubectl delete ns dapr-test
    2. To uninstall Dapr, run

      1. $ dapr uninstall --kubernetes
    3. To uninstall OSM, run

      1. $ osm uninstall mesh
    4. To remove OSM’s cluster wide resources after uninstallation, run the following command. See the uninstall guide for more context and information.

      1. $ osm uninstall mesh --delete-cluster-wide-resources