eventing icon indicating copy to clipboard operation
eventing copied to clipboard

Question: Is it possible to broadcast events to all replicas of a target?

Open oEscal opened this issue 1 year ago • 4 comments

For instance, imagine I have a Trigger whose subscriber is a Knative Service. It seems that the expected behavior is that when there is a new event, it is sent to one of the replicas of that Service. However, would it be possible to send that event to all replicas of that Service?

oEscal avatar Sep 19 '24 16:09 oEscal

cc @pierDipi

Cali0707 avatar Oct 05 '24 16:10 Cali0707

the way I would do it is to have an init container in your subscriber service creating a pod-specific trigger with subscriber uri: <pod_ip>, for example:

apiVersion: eventing.knative.dev/v1
kind: Trigger
metadata:
  name: <pod_name>
  namespace: <pod_namespace>
  ownerReferences: # This configures garbage collection, when the pod is deleted the trigger will be deleted
  - apiVersion: v1
    kind: Pod
    name: <pod_name>
    uid: <pod_uid>
    controller: true
    blockOwnerDeletion: false
spec:
  broker: my-broker
  subscriber:
    uri: http://<pod_ip>:<your_subscriber_pod_port>

you can inject the various variables <pod_ip>, <pod_name> into the init container environment variables using the k8s downward API: https://kubernetes.io/docs/concepts/workloads/pods/downward-api/#downwardapi-fieldRef

For example: (I didn't check the syntax but it should give you an idea)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: subscriber-deployment
spec:
  selector:
    matchLabels:
      app: subscriber
  template:
    metadata:
      labels:
        app: subscriber
    spec:
      serviceAccountName: <service_account> # Ensure this service account has permissions to create Knative triggers
      initContainers:
      - name: init-trigger
        image: bitnami/kubectl:latest
        command:
          - sh
          - -c
          - |
            cat <<EOF | kubectl apply -f -
            apiVersion: eventing.knative.dev/v1
            kind: Trigger
            metadata:
              name: $(POD_NAME)
              namespace: $(POD_NAMESPACE)
              ownerReferences:
              - apiVersion: v1
                kind: Pod
                name: $(POD_NAME)
                uid: $(POD_UID)
                controller: true
                blockOwnerDeletion: false
            spec:
              broker: my-broker
              subscriber:
                uri: http://$(POD_IP):80
            EOF
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        - name: POD_UID
          valueFrom:
            fieldRef:
              fieldPath: metadata.uid
        - name: POD_IP
          valueFrom:
            fieldRef:
              fieldPath: status.podIP
      containers:
      - name: subscriber
        image: nginx
        ports:
        - containerPort: 80

This way each pod (instance) will get all events from the broker my-broker

pierDipi avatar Oct 10 '24 15:10 pierDipi

in addition, I'd wait for the created trigger to become ready in the init container

kubectl wait triggers.eventing.knative.dev --for=condition=Ready=true -n $(POD_NAMESPACE)  $(POD_NAME) --timeout=20m

pierDipi avatar Oct 10 '24 15:10 pierDipi

With a Knative Service that scales from 0 might not be possible though, as the real receiver when scaling from 0 to 1 needs to be the activator https://github.com/knative/serving/blob/main/docs/scaling/SYSTEM.md

pierDipi avatar Oct 10 '24 15:10 pierDipi

Closing this issue for now, re-open in case the above doesn't work for you

pierDipi avatar Oct 24 '24 15:10 pierDipi