Producer and Consumer policies
With namespace scoped policies in Kuma you can have fine-grained control over policies and how they apply to your workloads. Moreover, this empowers app owners to take advantage of Kubernetes RBAC for policy configuration.
To fully utilize power of namespace scoped policies we need to get familiar with producer consumer model. This guide will help you get comfortable with producer consumer model.
Prerequisites
- Completed quickstart to set up a zone control plane with demo application
Basic setup
In order to be able to fully utilize namespace scoped policies you need to use MeshService. To enable MeshService resource generation on Mesh level we need to run:
echo "apiVersion: kuma.io/v1alpha1
kind: Mesh
metadata:
name: default
spec:
meshServices:
mode: Exclusive
mtls:
enabledBackend: ca-1
backends:
- name: ca-1
type: builtin" | kubectl apply -f -
To make sure that traffic works in our examples let’s configure MeshTrafficPermission to allow all traffic:
echo "apiVersion: kuma.io/v1alpha1
kind: MeshTrafficPermission
metadata:
namespace: kuma-system
name: mtp
spec:
targetRef:
kind: Mesh
from:
- targetRef:
kind: Mesh
default:
action: Allow" | kubectl apply -f -
To finish the setup we need to create two additional namespaces with sidecar injection for clients we will be using to communicate with our demo-app:
echo "apiVersion: v1
kind: Namespace
metadata:
name: first-consumer
labels:
kuma.io/sidecar-injection: enabled
---
apiVersion: v1
kind: Namespace
metadata:
name: second-consumer
labels:
kuma.io/sidecar-injection: enabled" | kubectl apply -f -
Now we can create deployment we will be using to communicate with our demo-app from a first-consumer namespace:
kubectl run consumer --image nicolaka/netshoot -n first-consumer --command -- /bin/bash -c "ping -i 60 localhost"
and from the second-consumer namespace:
kubectl run consumer --image nicolaka/netshoot -n second-consumer --command -- /bin/bash -c "ping -i 60 localhost"
You can make now make a couple of requests to our demo app to check if everything is working:
kubectl exec -n first-consumer consumer -- curl -s -XPOST demo-app.kuma-demo:5000/increment
You should see something similar to:
{"counter":"1","zone":"local","err":null}
At this moment our setup looks like this:
flowchart LR subgraph first-consumer-ns first-consumer end subgraph second-consumer-ns second-consumer end subgraph kuma-demo-ns kuma-demo redis end kuma-demo --> redis first-consumer --> kuma-demo second-consumer --> kuma-demo
Namespace scoped policies
Now that we have our setup we can start playing with policies. Let’s create a simple MeshTimeout policy in kuma-demo
namespace:
echo "apiVersion: kuma.io/v1alpha1
kind: MeshTimeout
metadata:
name: producer-timeout
namespace: kuma-demo
labels:
kuma.io/mesh: default
kuma.io/origin: zone
spec:
to:
- targetRef:
kind: MeshService
name: demo-app
default:
http:
requestTimeout: 1s" | kubectl apply -f -
We can now inspect applied policy labels:
kubectl get meshtimeout -n kuma-demo producer-timeout -o jsonpath='{.metadata.labels}'
We should see output like:
{
"k8s.kuma.io/namespace": "kuma-demo",
"kuma.io/env": "kubernetes",
"kuma.io/mesh": "default",
"kuma.io/origin": "zone",
"kuma.io/policy-role": "producer",
"kuma.io/zone": "default"
}
Kuma is adding custom labels to our policy. The one that interests us most at the moment is kuma.io/policy-role
.
This label indicates the policy role. Possible values of this label are:
system
- policies applied in system namespaceworkload-owner
- policies that don’t specifyspec.from
andspec.to
sections or specify onlyspec.from
sectionconsumer
- policies targetingMeshServices
from different namespace inspec.to
section or targetingMeshService
by labelsproducer
- policies defined in the same namespace as the MeshService they are targeting in theirspec.to[]
.
Producer consumer model
With namespace scoped policies we’ve introduced a producer/consumer model for policies.
A producer is someone who authors and operates a service. A producer can create policies that will be applied by default to any communication with their services.
Producer policies will be created in the same namespace as MeshService
they target. Producer policies will be synced to other zones.
A consumer is the client of a service. Consumer policies will be applied in the consumer namespace and may target MeshService from different namespaces. Consumer policies take effect only in the consumer namespace. Consumer policies will override producer policies.
Testing producer policy
To test MeshTimeout that we’ve applied in previous steps we need to simulate delays on our requests. To do this we need
add header x-set-response-delay-ms
to our requests.
We can now make few requests to our demo-app, and we should see timeouts:
kubectl exec -n first-consumer consumer -- curl -s -XPOST demo-app.kuma-demo:5000/increment -H "x-set-response-delay-ms: 2000"
Example output:
upstream request timeout
We should see the same results when making requests from second-consumer namespace:
kubectl exec -n second-consumer consumer -- curl -s -XPOST demo-app.kuma-demo:5000/increment -H "x-set-response-delay-ms: 2000"
Output:
upstream request timeout
Producer policy will be applied on all traffic to kuma-demo
as we can see on this diagram:
flowchart LR subgraph first-consumer-ns first-consumer end subgraph second-consumer-ns second-consumer end subgraph kuma-demo-ns kuma-demo redis end kuma-demo --> redis first-consumer --producer-timeout--> kuma-demo second-consumer --producer-timeout--> kuma-demo
Utilizing consumer policy
Until now, we were relying on producer policy created previously. Let’s assume that we don’t mind waiting a little longer for the response from demo-app, and we would like to override the timeout just for our namespace. To do so we need to create new policy:
echo "apiVersion: kuma.io/v1alpha1
kind: MeshTimeout
metadata:
name: consumer-timeout
namespace: first-consumer
labels:
kuma.io/mesh: default
kuma.io/origin: zone
spec:
to:
- targetRef:
kind: MeshService
labels:
k8s.kuma.io/service-name: demo-app
default:
http:
requestTimeout: 3s" | kubectl apply -f -
When we now make requests from the first-consumer namespace all the requests should succeed, but they will take longer:
kubectl exec -n first-consumer consumer -- curl -s -XPOST demo-app.kuma-demo:5000/increment -H "x-set-response-delay-ms: 2000"
We have just applied a consumer policy. The timeout will only be applied in the first-consumer
namespace.
We can test this by making requests from our second-consumer namespace:
kubectl exec -n second-consumer consumer -- curl -s -XPOST demo-app.kuma-demo:5000/increment -H "x-set-response-delay-ms: 2000"
We should still see timeouts:
upstream request timeout
To better visualize this we can look again at our diagram and see that only traffic from first-consumer
will be affected.
flowchart LR subgraph first-consumer-ns first-consumer end subgraph second-consumer-ns second-consumer end subgraph kuma-demo-ns kuma-demo redis end kuma-demo --> redis first-consumer --consumer-timeout--> kuma-demo second-consumer --producer-timeout--> kuma-demo
What we’ve learnt?
- How to apply policy on a namespace
- What are policy roles and what types can you encounter
- What are producer and consumer policies
- How producer and consumer policies interact with each other
Next steps
- Read more about producer/consumer policies
- Check out Federate zone control plane guide