Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,6 @@ spec:
- jsonPath: .status.apiServerObservedGeneration
name: Server Applied
type: integer
- jsonPath: .status.functionRunnerObservedGeneration
Comment thread
CsatariGergely marked this conversation as resolved.
name: FnRunner Applied
type: integer
- jsonPath: .status.controllerObservedGeneration
name: Controller Applied
type: integer
Expand Down Expand Up @@ -923,12 +920,6 @@ spec:
description: Contains an error message if one occurred whilst trying
to apply the FunctionConfig
type: string
functionRunnerObservedGeneration:
description: FunctionRunnerObservedGeneration indicates which generation
of the config the function-runner has applied to the executable
and pod evaluator
format: int64
type: integer
type: object
type: object
served: true
Expand Down
3 changes: 0 additions & 3 deletions api/porchconfig/v1alpha1/function_config_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import (
// +kubebuilder:subresource:status
// +kubebuilder:resource:path=functionconfigs,singular=functionconfig
// +kubebuilder:printcolumn:name="Server Applied",type=integer,JSONPath=`.status.apiServerObservedGeneration`
// +kubebuilder:printcolumn:name="FnRunner Applied",type=integer,JSONPath=`.status.functionRunnerObservedGeneration`
// +kubebuilder:printcolumn:name="Controller Applied",type=integer,JSONPath=`.status.controllerObservedGeneration`
type FunctionConfig struct {
metav1.TypeMeta `json:",inline"`
Expand Down Expand Up @@ -57,8 +56,6 @@ type FunctionConfigStatus struct {

// ApiServerObservedGeneration indicates which generation of the config the porch server has applied to the build-in runtime
ApiServerObservedGeneration int64 `json:"apiServerObservedGeneration,omitempty"`
// FunctionRunnerObservedGeneration indicates which generation of the config the function-runner has applied to the executable and pod evaluator
FunctionRunnerObservedGeneration int64 `json:"functionRunnerObservedGeneration,omitempty"`
// ControllerObservedGeneration indicates which generation of the config the porch controller has applied to its builtin runtime
ControllerObservedGeneration int64 `json:"controllerObservedGeneration,omitempty"`
// Contains an error message if one occurred whilst trying to apply the FunctionConfig
Expand Down
23 changes: 8 additions & 15 deletions controllers/functionconfigs/functionconfigreconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,29 +186,29 @@ func (s *FunctionConfigStore) GetBinaryFromCache(image string) (string, bool) {
return "", false
}

func (s *FunctionConfigStore) GetBinaryFromCacheByConstraint(image, tag string) (string, bool) {
func (s *FunctionConfigStore) GetBinaryFromCacheByConstraint(image, tag string) (string, string, bool) {
s.mu.RLock()
defer s.mu.RUnlock()

parsedImage := imageutil.Parse(image)
cacheEntry, ok := s.binaryExecutorCache[parsedImage.BaseName]
if !ok {
return "", false
return "", "", false
}

if !cacheEntry.PrefixRegex.MatchString(parsedImage.Prefix()) {
return "", false
return "", "", false
}

cacheKeys := slices.Collect(maps.Keys(cacheEntry.Tags))

selectedKey, err := imageutil.FindBestSemverMatch(tag, cacheKeys)
if err != nil {
return "", false
return "", "", false
}
selectedBinary, ok := cacheEntry.Tags[selectedKey]

return selectedBinary, ok
return selectedBinary, selectedKey, ok
}

func (s *FunctionConfigStore) GetExecCache() map[string]BuiltInCacheEntry {
Expand Down Expand Up @@ -246,9 +246,8 @@ func (s *FunctionConfigStore) List() []*configapi.FunctionConfig {
type ReconcilerFor string

const (
ReconcilerForFunctionRunner ReconcilerFor = "function-runner"
ReconcilerForServer ReconcilerFor = "server"
ReconcilerForController ReconcilerFor = "controller"
ReconcilerForServer ReconcilerFor = "server"
ReconcilerForController ReconcilerFor = "controller"
)

type Reconciler struct {
Expand Down Expand Up @@ -292,15 +291,13 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (res ctrl.
}

defer func() {
patch := client.MergeFrom(obj.DeepCopy())
patch := client.MergeFromWithOptions(obj.DeepCopy())

if finalErr != nil {
obj.Status.Error = finalErr.Error()
} else {
obj.Status.Error = ""
switch r.For {
case ReconcilerForFunctionRunner:
obj.Status.FunctionRunnerObservedGeneration = obj.Generation
case ReconcilerForServer:
obj.Status.ApiServerObservedGeneration = obj.Generation
case ReconcilerForController:
Expand Down Expand Up @@ -342,8 +339,6 @@ func (r *Reconciler) removeFinalizer(ctx context.Context, obj *configapi.Functio
patch := client.MergeFrom(obj.DeepCopy())

switch r.For {
case ReconcilerForFunctionRunner:
controllerutil.RemoveFinalizer(obj, FunctionRunnerFinalizer)
case ReconcilerForServer:
controllerutil.RemoveFinalizer(obj, ServerFinalizer)
case ReconcilerForController:
Expand All @@ -363,8 +358,6 @@ func (r *Reconciler) addFinalizer(ctx context.Context, obj *configapi.FunctionCo

updated := false
switch r.For {
case ReconcilerForFunctionRunner:
updated = controllerutil.AddFinalizer(obj, FunctionRunnerFinalizer)
case ReconcilerForServer:
updated = controllerutil.AddFinalizer(obj, ServerFinalizer)
case ReconcilerForController:
Expand Down
10 changes: 1 addition & 9 deletions controllers/functionconfigs/functionconfigreconciler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,10 +229,6 @@ func TestFinalizersAdded(t *testing.T) {
forValue ReconcilerFor
finalizer string
}{
string(ReconcilerForFunctionRunner): {
forValue: ReconcilerForFunctionRunner,
finalizer: FunctionRunnerFinalizer,
},
string(ReconcilerForServer): {
forValue: ReconcilerForServer,
finalizer: ServerFinalizer,
Expand Down Expand Up @@ -338,7 +334,7 @@ func TestGetBinaryFromCacheByConstraint(t *testing.T) {

for name, tc := range tests {
t.Run(name, func(t *testing.T) {
path, found := store.GetBinaryFromCacheByConstraint(tc.image, tc.constraint)
path, _, found := store.GetBinaryFromCacheByConstraint(tc.image, tc.constraint)
assert.Equal(t, tc.wantFound, found)
if tc.wantFound {
assert.Equal(t, tc.wantPath, path)
Expand Down Expand Up @@ -492,10 +488,6 @@ func TestFinalizersRemoved(t *testing.T) {
forValue ReconcilerFor
finalizer string
}{
string(ReconcilerForFunctionRunner): {
forValue: ReconcilerForFunctionRunner,
finalizer: FunctionRunnerFinalizer,
},
string(ReconcilerForServer): {
forValue: ReconcilerForServer,
finalizer: ServerFinalizer,
Expand Down
6 changes: 5 additions & 1 deletion controllers/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,11 @@ func setupFunctionConfigReconciler(mgr ctrl.Manager) (*functionconfigs.FunctionC
if prefix == "" {
prefix = runneroptions.GHCRImagePrefix
}
functionConfigStore := functionconfigs.NewFunctionConfigStore(prefix, "")
functionCacheDir := os.Getenv("FUNCTION_CACHE_DIR")
if functionCacheDir == "" {
functionCacheDir = "/home/nonroot/functions"
}
functionConfigStore := functionconfigs.NewFunctionConfigStore(prefix, functionCacheDir)

rec := &functionconfigs.Reconciler{
Client: mgr.GetClient(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package packagerevision

import (
"context"
"flag"
"fmt"
"os"
Expand All @@ -24,8 +25,10 @@ import (
"github.com/kptdev/porch/controllers/packagerevisions/pkg/webhooks"
"github.com/kptdev/porch/pkg/cache/contentcache"
"github.com/kptdev/porch/pkg/engine"
"github.com/kptdev/porch/pkg/engine/podevaluator"
porch "github.com/kptdev/porch/pkg/registry/porch"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
)

Expand All @@ -35,6 +38,7 @@ const (
defaultRenderRequeueDelay = 2 * time.Second
defaultRepoOperationRetryAttempts = 3
defaultMaxGRPCMessageSize = 6 * 1024 * 1024 // 6MB
defaultPodNamespace = "porch-fn-system"
)

func (r *PackageRevisionReconciler) InitDefaults() {
Expand Down Expand Up @@ -78,21 +82,60 @@ func (r *PackageRevisionReconciler) Init(mgr ctrl.Manager) error {
)

fnRunnerAddr := os.Getenv("FUNCTION_RUNNER_ADDRESS")
functionRuntime, err := engine.NewMultiFunctionRuntime(fnRunnerAddr, r.MaxGRPCMessageSize, r.FunctionConfigStore)
if err != nil {
return fmt.Errorf("failed to create function runtime: %w", err)
}
opts := runneroptions.RunnerOptions{}
wrapperServerImage := os.Getenv("WRAPPER_SERVER_IMAGE")

prefix := os.Getenv("DEFAULT_IMAGE_PREFIX")
if prefix == "" {
prefix = runneroptions.GHCRImagePrefix
}

var podOpts *podevaluator.PodEvaluatorOptions
var kubeClient client.WithWatch
if wrapperServerImage != "" {
podNamespace := os.Getenv("POD_NAMESPACE")
if podNamespace == "" {
podNamespace = defaultPodNamespace
}
var err error
kubeClient, err = client.NewWithWatch(mgr.GetConfig(), client.Options{Scheme: mgr.GetScheme()})
if err != nil {
return fmt.Errorf("failed to create kube client for pod evaluator: %w", err)
}
podOpts = &podevaluator.PodEvaluatorOptions{
PodNamespace: podNamespace,
WrapperServerImage: wrapperServerImage,
WarmUpPodCacheOnStartup: true,
MaxGrpcMessageSize: r.MaxGRPCMessageSize,
DefaultImagePrefix: prefix,
MaxWaitlistLength: 1,
MaxParallelPodsPerFunction: 2,
}
}

functionRuntime, err := engine.NewMultiFunctionRuntime(context.Background(), engine.MultiFunctionRuntimeOptions{
GRPCAddress: fnRunnerAddr,
MaxGrpcMessageSize: r.MaxGRPCMessageSize,
FunctionConfigStore: r.FunctionConfigStore,
PodEvaluator: podOpts,
KubeClient: kubeClient,
DefaultImagePrefix: prefix,
})
if err != nil {
return fmt.Errorf("failed to create function runtime: %w", err)
}
opts := runneroptions.RunnerOptions{}
opts.InitDefaults(prefix)
r.Renderer = newKptRenderer(functionRuntime, opts)
if fnRunnerAddr != "" {
ctrl.Log.WithName(r.Name()).Info("function runtime enabled (builtin + fn-runner)", "address", fnRunnerAddr)
} else {
ctrl.Log.WithName(r.Name()).Info("function runtime enabled (builtin only, FUNCTION_RUNNER_ADDRESS not set)")
switch {
case fnRunnerAddr != "" && wrapperServerImage != "":
log.Info("function runtime enabled (builtin + fn-runner + pod evaluator)",
"fnRunner", fnRunnerAddr, "podNamespace", podOpts.PodNamespace)
case fnRunnerAddr != "":
log.Info("function runtime enabled (builtin + fn-runner)", "address", fnRunnerAddr)
case wrapperServerImage != "":
log.Info("function runtime enabled (builtin + pod evaluator)", "podNamespace", podOpts.PodNamespace)
default:
log.Info("function runtime enabled (builtin only)")
}

// Register PackageRevision validating webhook.
Expand Down
34 changes: 6 additions & 28 deletions deployments/function-pods/README.md
Original file line number Diff line number Diff line change
@@ -1,35 +1,13 @@
### Function Pod Template

In order to leverage custom manifests for Pod and frontend Service of Function Pods created by Function Runner, the following additional Kubernetes Resource Manifests (KRM) need to be provisioned in the Porch environment
Function execution pods are created by the **Engine pod evaluator** (porch-server and, when enabled, porch-controllers), not Function Runner.

* A ConfigMap containing 2 data elements: a) a KRM of type Pod under the `template` key and b) a KRM of type Service under `serviceTemplate` key
* A Kubernetes Role providing read access to resource type ConfigMap in the porch-system namespace
* A Kubernetes RoleBinding, binding to the above listed Role to the ServiceAccount (porch-fn-runner) used by Function Runner Pod
Default manifests install Kubernetes `PodTemplate` `base-pod-template` and `ServiceTemplate` `base-service-template` in `porch-fn-system`. See `deployments/porch/22-function-templates.yaml` and [Pod Templates](../../docs/content/en/docs/6_configuration_and_deployments/configurations/components/porch-server-config/pod-templates.md).

All of the above KRMs are predefined in `deployment.yaml` file present in this folder.
The ConfigMap-based `--function-pod-template` flow documented previously for Function Runner is no longer used.

### How to enable Function Pod Template use by Function Runner
### How to customize

* Apply the [deployment.yaml manifest](deployment.yaml) from this directory
Edit `base-pod-template` in `porch-fn-system` (or the YAML in `deployments/porch/22-function-templates.yaml` before deploy). porch-server and porch-controllers already have RBAC via the `porch-function-executor` Role.

```
kubectl apply -f deployment.yaml
```

* Add an additional argument `--function-pod-template` in command section of function-runner deployment instructing it to use the Function Pod Template ConfigMap, as shown below

```
kubectl edit deployment -n porch-system function-runner
```

```
command:
- /server
- --config=/config.yaml
- --functions=/functions
- --pod-namespace=porch-fn-system
- --function-pod-template=kpt-function-eval-pod-template
- --max-request-body-size=6291456 # Keep this in sync with porch-server's corresponding argument
```

After the function-runner Pods restart, they will start using the Pod and Service templates from ConfigMap.
This folder's `deployment.yaml` is a historical ConfigMap example and is not wired into current porch-server.
6 changes: 0 additions & 6 deletions deployments/porch/2-function-runner.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,9 @@ spec:
runAsGroup: 10001
command:
- /home/nonroot/server
- --pod-namespace=porch-fn-system
- --max-request-body-size=6291456 # Keep this in sync with porch-server's corresponding argument
- --max-parallel-pods-per-function=2
- --max-waitlist-length=1
- --warm-up-pod-cache=true
- --functions=/home/nonroot/functions
env:
- name: WRAPPER_SERVER_IMAGE
value: ghcr.io/kptdev/porch-wrapper-server:latest
- name: OTEL_METRICS_EXPORTER
value: "prometheus"
- name: OTEL_EXPORTER_PROMETHEUS_HOST
Expand Down
8 changes: 7 additions & 1 deletion deployments/porch/3-porch-server.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ spec:
value: "9464" # Default value, showing for visibility
- name: OTEL_TRACES_EXPORTER
value: none
- name: WRAPPER_SERVER_IMAGE
value: ghcr.io/kptdev/porch-wrapper-server:latest
args:
- --function-runner=function-runner:9445
- --cache-directory=/cache
Expand All @@ -86,6 +88,10 @@ spec:
- --max-request-body-size=6291456 # Keep this in sync with function-runner's corresponding argument
- --cache-type=db
- --disable-admission-plugins=MutatingAdmissionPolicy # This can be enabled once kindest/node 1.36.1 is released
- --max-parallel-pods-per-function=2
- --max-waitlist-length=1
- --warm-up-pod-cache=true
- --functions=/home/nonroot/functions
ports:
- containerPort: 9464
name: metrics
Expand Down Expand Up @@ -119,7 +125,7 @@ spec:
periodSeconds: 10
failureThreshold: 6
successThreshold: 1
timeoutSeconds: 5
timeoutSeconds: 5
---
apiVersion: v1
kind: Service
Expand Down
6 changes: 6 additions & 0 deletions deployments/porch/6-rbac-bind.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ roleRef:
kind: Role
name: porch-function-executor
subjects:
- kind: ServiceAccount
name: porch-server
namespace: porch-system
- kind: ServiceAccount
name: porch-controllers
namespace: porch-system
- kind: ServiceAccount
name: porch-fn-runner
namespace: porch-system
6 changes: 6 additions & 0 deletions deployments/porch/9-controllers.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@ spec:
value: "true"
- name: GIT_CACHE_DIR
value: "/cache"
- name: FUNCTION_CACHE_DIR
value: "/home/nonroot/functions"
- name: POD_NAMESPACE
value: "porch-fn-system"
- name: WRAPPER_SERVER_IMAGE
value: ghcr.io/kptdev/porch-wrapper-server:latest
- name: OTEL_SERVICE_NAME
value: porch-controllers
- name: OTEL_METRICS_EXPORTER
Expand Down
2 changes: 1 addition & 1 deletion deployments/porch/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ make deployment-config
- `IMAGE_REPO`: Set image repository (default: `ghcr.io/kptdev`)
- `ENABLED_RECONCILERS`: Comma-separated list of reconcilers (default: `packagevariants,packagevariantsets,repositories`)
- `FN_RUNNER_WARM_UP_POD_CACHE`: Enable/disable pod cache warm-up (default: `true`)
- `PORCH_GHCR_PREFIX_URL`: KRM function catalog registry prefix (from `.env` or environment). Applied to porch-server (`--default-image-prefix`), function-runner (`--default-image-prefix`), and porch-controllers (`DEFAULT_IMAGE_PREFIX`) for all `make run-in-kind*` targets that use `deployment-config`.
- `PORCH_GHCR_PREFIX_URL`: KRM function catalog registry prefix (from `.env` or environment). Applied to porch-server (`--default-image-prefix`) and porch-controllers (`DEFAULT_IMAGE_PREFIX`) for all `make run-in-kind*` targets that use `deployment-config`.

Examples:

Expand Down
Loading