|
| 1 | +# OCI Functions Operator |
| 2 | + |
| 3 | +Kubernetes-native APIs for managing and invoking OCI Functions from OKE. |
| 4 | + |
| 5 | +Current controller image: |
| 6 | + |
| 7 | +```text |
| 8 | +ghcr.io/ronsevetoci/oci-functions-operator/controller:v0.1.7 |
| 9 | +``` |
| 10 | + |
| 11 | +## What This Operator Provides |
| 12 | + |
| 13 | +The operator exposes five namespaced CRDs in `functions.oci.oracle.com/v1alpha1`: |
| 14 | + |
| 15 | +- `FunctionApplication`: maps to an OCI Functions Application. It owns app-level settings such as compartment, region, subnets, NSGs, application config, and invocation log settings. |
| 16 | +- `Function`: maps to an OCI Function. It can reference an existing OCI Function or manage one inside a `FunctionApplication`. |
| 17 | +- `FunctionJob`: invokes a referenced `Function` with one or more inline JSON payloads, parallelism, retry limits, and per-payload status. |
| 18 | +- `FunctionEventTrigger`: routes an OCI Events rule or a Kubernetes-native `functionevent.*` event type to a `Function`. |
| 19 | +- `FunctionEvent`: an in-cluster event envelope that the operator matches against `FunctionEventTrigger` resources. |
| 20 | + |
| 21 | +`FunctionJob` and `FunctionEvent` both end in a Function invocation, but they are not the same resource. Use `FunctionJob` when a user or system wants to submit explicit invocation work and track that work as a job. Use `FunctionEvent` when an application emits an event and wants the operator to route it through matching triggers. |
| 22 | + |
| 23 | +## Resource Flow |
| 24 | + |
| 25 | +```mermaid |
| 26 | +flowchart TB |
| 27 | + APPCR[FunctionApplication CR] |
| 28 | + APP[OCI Functions Application] |
| 29 | + FNCR[Function CR] |
| 30 | + FN[OCI Function] |
| 31 | + INVOKE[Function Invocation] |
| 32 | +
|
| 33 | + APPCR --> APP |
| 34 | + APP --> FNCR |
| 35 | + FNCR --> FN |
| 36 | + FN --> INVOKE |
| 37 | +
|
| 38 | + JOB[FunctionJob CR] |
| 39 | + TRIGGER[FunctionEventTrigger CR] |
| 40 | + EVENT[FunctionEvent CR] |
| 41 | + OCIEVENT[OCI service event] |
| 42 | + RULE[OCI Events Rule] |
| 43 | +
|
| 44 | + JOB --> INVOKE |
| 45 | + EVENT --> TRIGGER |
| 46 | + OCIEVENT --> RULE |
| 47 | + RULE --> TRIGGER |
| 48 | + TRIGGER --> INVOKE |
| 49 | +``` |
| 50 | + |
| 51 | +Read it top to bottom: a `FunctionApplication` is the application wrapper, a `Function` lives inside it, and every invocation path eventually invokes that function. `FunctionJob` is direct work submission. `FunctionEventTrigger` routes either OCI service events through an OCI Events Rule or in-cluster `FunctionEvent` objects. |
| 52 | + |
| 53 | +The important boundary is that the operator does not turn OCI Functions into Pods. It keeps OCI Functions as OCI resources and gives Kubernetes users a clear control plane for application setup, function setup, invocation, event routing, status, and events. |
| 54 | + |
| 55 | +## Two Images |
| 56 | + |
| 57 | +The operator image and function runtime image are separate artifacts: |
| 58 | + |
| 59 | +- Operator/controller image: runs as a Kubernetes Deployment in OKE. It can be in GHCR, OCIR, or any registry OKE can pull from. |
| 60 | +- Function runtime image: runs in OCI Functions. It must be an OCI Functions-compatible Fn image in same-region OCIR, for example `jed.ocir.io/<TENANCY_NAMESPACE>/hello-function:fn-v1` for Jeddah. |
| 61 | + |
| 62 | +Do not use GHCR for the OCI Functions runtime image. OCI Functions pulls the runtime image from the Functions application network during invocation, so the application subnet and any attached NSGs must allow egress to Oracle Services Network/OCIR even when the OCIR repository is public. |
| 63 | + |
| 64 | +## Start Here |
| 65 | + |
| 66 | +- [Helm install](docs/helm-install.md): supported OKE installation and upgrade path. |
| 67 | +- [OKE deployment](docs/oke-deployment.md): Workload Identity, IAM, networking, and the core resource sequence. |
| 68 | +- [Function event triggers](docs/event-triggers.md): OCI Events and `functionevent.*` routing. |
| 69 | +- [Function events](docs/function-events.md): Kubernetes-native event emission. |
| 70 | +- [Debugging Functions](docs/debugging-functions.md): image, CRD, Workload Identity, NSG, and invocation failure checks. |
| 71 | +- [Design overview](docs/design.md): controller architecture, resource behavior, and current limitations. |
| 72 | +- [Sample function image](examples/hello-function/README.md): Fn-compatible Python function runtime image. |
| 73 | + |
| 74 | +Tracked files under `config/samples/` are generic examples with placeholders. Live walkthrough manifests with OCIDs, tenancy namespaces, bucket names, or temporary cleanup settings should live in the ignored `local/` directory, not in the repository history. |
| 75 | + |
| 76 | +## Helm CRDs |
| 77 | + |
| 78 | +The Helm chart includes CRDs for `FunctionApplication`, `Function`, `FunctionJob`, `FunctionEventTrigger`, and `FunctionEvent`. |
| 79 | + |
| 80 | +Fresh Helm installs install CRDs from `charts/oci-functions-operator/crds/`, but existing Helm upgrades do not add or update CRDs from that directory. Before installing or upgrading after API changes, apply the chart CRDs first: |
| 81 | + |
| 82 | +```sh |
| 83 | +kubectl apply -f charts/oci-functions-operator/crds/ |
| 84 | +``` |
| 85 | + |
| 86 | +Then run `helm upgrade --install`. |
| 87 | + |
| 88 | +## Modes |
| 89 | + |
| 90 | +`INVOKER_MODE=fake` is the default for local controller development and tests. It requires no OCI auth and creates no OCI resources. |
| 91 | + |
| 92 | +`INVOKER_MODE=oci` uses the OCI Go SDK: |
| 93 | + |
| 94 | +- On OKE, the Helm chart configures Workload Identity with `oci.authMode=workload`. |
| 95 | +- For local development only, use `OCI_AUTH_MODE=config` with `OCI_CONFIG_FILE` and `OCI_CONFIG_PROFILE`. |
| 96 | + |
| 97 | +The Helm chart is the supported way to deploy the operator on OKE. Kustomize under `config/` is kept for Kubebuilder-generated manifests and local development only. Do not mix Helm and Kustomize for the same cluster install. |
| 98 | + |
| 99 | +## Resource Model |
| 100 | + |
| 101 | +Preferred managed mode is explicit: |
| 102 | + |
| 103 | +1. Create a `FunctionApplication` for the shared OCI Functions Application. |
| 104 | +2. Create one or more managed `Function` resources with `spec.applicationRef.name`. |
| 105 | +3. Wait for `Function.status.functionId` and `Function.status.invokeEndpoint`. |
| 106 | +4. Invoke through `FunctionJob`, OCI Events-backed `FunctionEventTrigger`, or Kubernetes-native `FunctionEvent`. |
| 107 | + |
| 108 | +Legacy managed `Function` manifests that put app-level settings under `spec.config` still work for compatibility, but new manifests should use `FunctionApplication`. |
| 109 | + |
| 110 | +`Function.spec.deletionPolicy` defaults to `Retain`. Deleting a managed `Function` with `Retain` leaves OCI resources untouched. Set `deletionPolicy: Delete` only when Kubernetes deletion should also delete the managed OCI Function. `FunctionApplication.spec.deletionPolicy` controls OCI Application cleanup separately; `Delete` is honored only for managed applications and only when no functions remain. Existing-mode resources never delete OCI resources. |
| 111 | + |
| 112 | +## Local Development |
| 113 | + |
| 114 | +Install or refresh generated CRDs: |
| 115 | + |
| 116 | +```sh |
| 117 | +make generate |
| 118 | +make manifests |
| 119 | +kubectl apply -k config/crd |
| 120 | +``` |
| 121 | + |
| 122 | +Run the manager in fake mode: |
| 123 | + |
| 124 | +```sh |
| 125 | +INVOKER_MODE=fake go run ./cmd |
| 126 | +``` |
| 127 | + |
| 128 | +Apply the safe sample resources: |
| 129 | + |
| 130 | +```sh |
| 131 | +kubectl apply -k config/samples |
| 132 | +kubectl get functions,functionjobs |
| 133 | +kubectl describe functionjob hello-job |
| 134 | +``` |
| 135 | + |
| 136 | +Fake mode proves only Kubernetes reconciliation and status behavior. It does not prove OCI auth, OCI Functions network egress, OCIR image access, or function image compatibility. |
0 commit comments