Add documentation for FunctionConfig CRD and reconciler (v2) - #1162
Add documentation for FunctionConfig CRD and reconciler (v2)#1162mozesl-nokia wants to merge 3 commits into
Conversation
Assisted-by: Cursor:claude-sonnet-5 Assisted-by: Cursor:grok-4.6 Signed-off-by: Mózes László Máté <laszlo.mozes@nokia.com>
✅ Deploy Preview for kpt-porch ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
There was a problem hiding this comment.
Pull request overview
Adds missing documentation for the FunctionConfig CRD and how Porch components (porch-server, function-runner, porch-controllers) reconcile and use it, updating existing docs to reflect the current “FunctionConfig + base PodTemplate/ServiceTemplate” model instead of legacy ConfigMap templating.
Changes:
- Introduces a new “Function Configuration” doc explaining FunctionConfig matching, executors, reconciler behavior, and status fields.
- Updates Function Runner architecture/design/configuration docs to reference FunctionConfig-driven executor selection and base PodTemplate/ServiceTemplate usage.
- Enhances install/deployment verification & troubleshooting docs with FunctionConfig checks and status interpretation.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| docs/content/en/docs/6_configuration_and_deployments/deployments/catalog-deployment.md | Adds verification/troubleshooting steps for FunctionConfig + base templates after catalog deployment. |
| docs/content/en/docs/6_configuration_and_deployments/configurations/opentelemetry.md | Updates OpenTelemetry guidance to use base-pod-template rather than ConfigMap templating. |
| docs/content/en/docs/6_configuration_and_deployments/configurations/components/function-runner-config/pod-templates.md | Rewrites pod templating docs to describe base PodTemplate/ServiceTemplate + FunctionConfig overrides. |
| docs/content/en/docs/6_configuration_and_deployments/configurations/components/function-runner-config/function-configuration.md | New page documenting the FunctionConfig CRD, reconciler roles, executors, and examples. |
| docs/content/en/docs/6_configuration_and_deployments/configurations/components/function-runner-config/_index.md | Updates Function Runner config overview to emphasize FunctionConfig as the primary per-function configuration source. |
| docs/content/en/docs/6_configuration_and_deployments/configurations/components/_index.md | Adds navigation links for the new Function Configuration and updated Pod Templates docs. |
| docs/content/en/docs/5_architecture_and_components/function-runner/interactions.md | Documents FunctionConfig reconciler/store and updates diagrams/flows to remove ConfigMap templating. |
| docs/content/en/docs/5_architecture_and_components/function-runner/functionality/pod-lifecycle-management.md | Updates pod lifecycle description to base PodTemplate/ServiceTemplate + FunctionConfig overrides. |
| docs/content/en/docs/5_architecture_and_components/function-runner/functionality/function-evaluation.md | Updates evaluator docs to reflect FunctionConfig-backed binary cache and pod settings. |
| docs/content/en/docs/5_architecture_and_components/function-runner/functionality/_index.md | Updates function-runner functionality index to reflect FunctionConfig-driven behavior. |
| docs/content/en/docs/5_architecture_and_components/function-runner/design.md | Updates design rationale to prefer FunctionConfig CRs over a static config file for executable evaluator mapping. |
| docs/content/en/docs/5_architecture_and_components/engine/interactions.md | Updates engine runtime selection description to be FunctionConfig-driven. |
| docs/content/en/docs/3_getting_started/installing-porch.md | Adds FunctionConfig CRD/resource verification steps to installation docs. |
| docs/content/en/docs/2_concepts/functions.md | Adds FunctionConfig-based execution model explanation to the core “Functions” concept doc. |
Suppressed comments (1)
docs/content/en/docs/6_configuration_and_deployments/configurations/components/function-runner-config/pod-templates.md:23
- In the creation flow, the base templates are read from the function-pod namespace configured by
--pod-namespace(not alwaysporch-fn-system). Also, the code only patchesfn.kpt.dev/template-versionandfn.kpt.dev/image; there is nofn.kpt.dev/reclaim-afterannotation being set, so mentioning it here is misleading.
1. Gets `base-pod-template` (`corev1.PodTemplate`) and `base-service-template` (`config.porch.kpt.dev/v1alpha1` ServiceTemplate) from `porch-fn-system`. If either is missing, it creates it from the inline default shipped in the binary.
2. Patches the function container with the requested image, the wrapper-server command, the original image entrypoint as arguments, and any image-pull secret required for private registries.
3. Patches pod metadata: `fn.kpt.dev/image` label, `fn.kpt.dev/reclaim-after` TTL annotation, and `fn.kpt.dev/template-version` set to the PodTemplate `resourceVersion`.
4. Merges `spec.podExecutor.templateOverrides` from the FunctionConfig for that image, if any.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Assisted-by: Cursor:grok-4.6 Signed-off-by: Mózes László Máté <laszlo.mozes@nokia.com>
Assisted-by: Cursor:grok-4.6 Signed-off-by: Mózes László Máté <laszlo.mozes@nokia.com>
|
| The **pod executor** is the default path for arbitrary function images: the function-runner creates (or reuses) a pod, injects a wrapper gRPC server, and runs the function image in isolation. | ||
| TTL, parallelism, and pod-spec overrides come from the matching FunctionConfig. | ||
| The **binary executor** runs a pre-built binary inside the function-runner process, which avoids pod startup cost. | ||
| The **Go executor** calls a compiled-in `ResourceListProcessor` (today: apply-replacements, set-namespace, and starlark) with no extra process at all. |
| ``` | ||
|
|
||
| A healthy install shows one FunctionConfig per bundled catalog function (apply-replacements, set-namespace, starlark, kubeconform, and others). | ||
| The `Server Applied`, `FnRunner Applied`, and `Controller Applied` columns are the generations each component has loaded; they should match the resource generation when the spec is in sync. |
There was a problem hiding this comment.
| The `Server Applied`, `FnRunner Applied`, and `Controller Applied` columns are the generations each component has loaded; they should match the resource generation when the spec is in sync. | |
| The `Server Applied`, `FnRunner Applied`, and `Controller Applied` columns are the generations each component has loaded. They should match the resource generation when the spec is in sync. |
|
|
||
| The task handler uses function runtimes configured in the engine: | ||
| The task handler uses function runtimes configured in the engine. | ||
| Which runtime handles a given image is driven by FunctionConfig (see [Function Configuration]({{% relref "/docs/6_configuration_and_deployments/configurations/components/function-runner-config/function-configuration.md" %}})): |
There was a problem hiding this comment.
FunctionConfig decides which runtimes handles a given image (?)
|
|
||
| **Request structure:** | ||
| - **Image**: Function container image identifier | ||
| - **Tag**: Optional version constraint; when set, evaluators resolve it against cached tags |
There was a problem hiding this comment.
| - **Tag**: Optional version constraint; when set, evaluators resolve it against cached tags | |
| - **Tag**: Optional version constraint. When set, evaluators resolve it against cached tags. |
| Everything else is sent over gRPC to the **function-runner**, which tries a local binary from `binaryExecutor` first and falls back to a Kubernetes pod from `podExecutor`. | ||
|
|
||
| The **pod executor** is the default path for arbitrary function images: the function-runner creates (or reuses) a pod, injects a wrapper gRPC server, and runs the function image in isolation. | ||
| TTL, parallelism, and pod-spec overrides come from the matching FunctionConfig. |
There was a problem hiding this comment.
| TTL, parallelism, and pod-spec overrides come from the matching FunctionConfig. | |
| Time to Live (TTL), parallelism, and pod-spec overrides come from the matching FunctionConfig. |
| ``` | ||
|
|
||
| `apiServerObservedGeneration`, `functionRunnerObservedGeneration`, and `controllerObservedGeneration` are the `.metadata.generation` each component last applied. | ||
| `error` is set when that component failed to apply the spec; it is cleared on the next successful reconcile. |
There was a problem hiding this comment.
| `error` is set when that component failed to apply the spec; it is cleared on the next successful reconcile. | |
| `error` is set when that component failed to apply the spec. It is cleared on the next successful reconcile. |
|
|
||
| The Function Runner automatically patches the template with function-specific configuration before creating pods. | ||
| Any custom `base-pod-template` must keep a container named `function`. | ||
| That container's command must start the wrapper gRPC server; the function-runner replaces the image and appends the original function entrypoint to `args`. |
There was a problem hiding this comment.
| That container's command must start the wrapper gRPC server; the function-runner replaces the image and appends the original function entrypoint to `args`. | |
| That container's command must start the wrapper gRPC server. The function-runner replaces the image and appends the original function entrypoint to `args`. |
| An init container named `copy-wrapper-server` is expected as the first init container when `templateOverrides.initContainer` is used, because overrides are merged by index. | ||
|
|
||
| ## Enabling Pod Templates | ||
| The Function Runner patches the template before creating pods. Leave the function image as a placeholder; it is always replaced. |
There was a problem hiding this comment.
| The Function Runner patches the template before creating pods. Leave the function image as a placeholder; it is always replaced. | |
| The Function Runner patches the template before creating pods. Leave the function image as a placeholder. It is always replaced. |
| The wrapper-server component can be configured with OpenTelemetry settings through the pod templating mechanism used by the function runner. This is done by creating a ConfigMap with a pod template that includes the necessary environment variables. | ||
| The wrapper-server can pick up OpenTelemetry settings from the function-runner's base **PodTemplate**. | ||
| Edit `base-pod-template` in `porch-fn-system` (see [Pod Templates]({{% relref "/docs/6_configuration_and_deployments/configurations/components/function-runner-config/pod-templates.md" %}})) so the `function` container env includes the exporters you want. | ||
| New function pods pick up the change on the next create or template-version replacement; existing pods are not rewritten in place. |
There was a problem hiding this comment.
| New function pods pick up the change on the next create or template-version replacement; existing pods are not rewritten in place. | |
| New function pods pick up the change on the next create or template-version replacement. Existing pods are not rewritten in place. |
| - --pod-namespace=porch-fn-system | ||
| - --function-pod-template=kpt-function-eval-pod-template | ||
| ``` | ||
| No extra function-runner flag is required; the runner always reads `base-pod-template` from `--pod-namespace`. |
There was a problem hiding this comment.
| No extra function-runner flag is required; the runner always reads `base-pod-template` from `--pod-namespace`. | |
| No extra function-runner flag is required. The runner always reads `base-pod-template` from `--pod-namespace`. |
Catalin-Stratulat-Ericsson
left a comment
There was a problem hiding this comment.
looks great. thanks so much @mozesl-nokia for adding this in. approving with comments as i dont want to block this getting merged in over minor comments. Great Work
There was a problem hiding this comment.
does this file need to exist? i understand the deployment.yaml example in the same dir but this is mainly just a readme of how the feature works + pointing to the docs anyway. cant this just be in the docs alone?
| Porch executes functions through the Engine's function runtime. | ||
| The builtin runtime (in porch-server and porch-controllers) handles images listed on a FunctionConfig `goExecutor`. | ||
| Everything else is sent over gRPC to the **function-runner**, which tries a local binary from `binaryExecutor` first and falls back to a Kubernetes pod from `podExecutor`. | ||
|
|
||
| The **pod executor** is the default path for arbitrary function images: the function-runner creates (or reuses) a pod, injects a wrapper gRPC server, and runs the function image in isolation. | ||
| TTL, parallelism, and pod-spec overrides come from the matching FunctionConfig. | ||
| The **binary executor** runs a pre-built binary inside the function-runner process, which avoids pod startup cost. | ||
| The **Go executor** calls a compiled-in `ResourceListProcessor` (today: apply-replacements, set-namespace, and starlark) with no extra process at all. | ||
|
|
||
| Regardless of executor, Porch passes the package's resources to [kpt](https://kpt.dev), which passes them on as a [ResourceList](https://github.com/kubernetes-sigs/kustomize/blob/master/cmd/config/docs/api-conventions/functions-spec.md#resourcelist) to each function in the pipeline in order. | ||
| kpt runs the functions sequentially and returns the results to Porch, which stores them in the PackageRevisionResources `status.renderStatus` field. | ||
| Rendering is triggered automatically after creating or cloning a package revision, after updating a package revision, and when a package revision is proposed. |
There was a problem hiding this comment.
in my opinion this is a bit too brutal level of complexity for the concepts sections. this is meant to be for high level detail. its great detail mind you but id recommend a bit higher level here and bring this detail into the later sections of the docs.
| The **builtin runtime** runs compiled-in Go processors (`apply-replacements`, `set-namespace`, `starlark`) for tags listed on `goExecutor`. | ||
|
|
||
| The **gRPC runtime** calls the function-runner for everything else (binary fast path, then pod). | ||
|
|
||
| The **multi-runtime** tries builtin first and falls back to gRPC. |
There was a problem hiding this comment.
i think these were fine as bullet points but its fine either way really
There was a problem hiding this comment.
this is great content but this section is meant to be for configuration of his feature not to explain what and how it functions and interacts. i think the content is great but should move into architecture and components in the relevant area and only configuration info should remain here with minimal information to support said configuration.
There was a problem hiding this comment.
not im only referring to the first 2-3 paragraphs in this file the rest is perfect as is
There was a problem hiding this comment.
same as my previous comment. just first 2 paragraphs. rest is perfect as is
| A healthy install shows one FunctionConfig per bundled catalog function (apply-replacements, set-namespace, starlark, kubeconform, and others). | ||
| The `Server Applied`, `FnRunner Applied`, and `Controller Applied` columns are the generations each component has loaded; they should match the resource generation when the spec is in sync. | ||
|
|
||
| These FunctionConfig objects replace the older static config-file / ConfigMap approach. |
There was a problem hiding this comment.
would a reader here know what the old approach was? i think this might just confuse people about what the old approach even is. i think we have versioned docs now so if someone wanted to see what the older approach was they can just go back.



Add documentation for FunctionConfig CRD and reconciler
Description
Related Issue(s)
Type of Change
Checklist
Tests added/updatedAll tests and gating checks passAdditional Notes (Optional)
AI Disclosure
If so, please describe how: