# One Dapr sidecar per Function ## Motivation Currently, OpenFunction injects the dapr sidecar into each Function pod,which leads to following problems: - Function pod startup time is affected by the dapr sidecar, in my environment the startup time of the dapr sidecar is around 7 seconds. - The `one-sidecar-per-pod` mode is an blocking issue when we want to use the Function Pool to optimize the cold start speed of the Function (dapr runtime does not support dynamically loading components). - The `one-sidecar-per-pod` mode means more resource overhead, which is more asymmetric for simple Functions. So, OpenFunction should support `one dapr sidecar per function` mode. ## Goals - Function Pod startup time is no longer affected by the dapr sidecar. - Resolve blocking issue for OpenFunction's cold start optimization. - Reduce the resource overhead of Function. ## Proposal ### Function CR Once a Function CR with `dapr.io/inject-mode: "function"` in the `spec.serving.annotations` field is created, the function controller will: - Create Function Agent Deployment with `dapr injector` related annotations. Pass function address by Function Context. - Create Function Agent Service to accept dapr client request. - Create Function Deployment without `dapr injector` related annotations. Pass daprd address by Function Context. - Create Function Service to accept event(for async functions). - Generate `APP_API_TOKEN`, configure `dapr.io/app-token-secret: "app-api-token"` and Function Deployment's env ```yaml apiVersion: core.openfunction.io/v1beta1 kind: Function metadata: name: sink spec: version: "v1.0.0" image: "openfunction/sink-sample:latest" port: 8080 serving: annotations: dapr.io/inject-mode: "function" runtime: "knative" template: containers: - name: function imagePullPolicy: Always ``` ### Functions Framework Adjustments that need to be made: 1. To support one-sidecar-per-function mode, functions-framework need to get daprHost from env vars, init daprClient based on daprHost and daprHTTPPort/daprGRPCPort. 2. Do not generate/init daprClient when the sync function uses the OpenFunction signature but does not define inputs and outputs. ### Function Agent - The [blockUntilAppIsReady](https://github.com/dapr/dapr/blob/f5a5acc406302f0d5122ae30d18f9baba6dba8d3/pkg/runtime/runtime.go#L507) method is called when the dapr runtime starts, so we need a agent to listen on app-port. - The agent is also responsible for forwarding subsequent events to the function's service(only for async funtions). - The agent will support reconnection after disconnection. - The agent will handle `APP_API_TOKEN` in requests. ![](https://i.imgur.com/4r6jm8x.png)