FAQ

This document describes FAQs when using OpenFunction.

Q: How to use private image repositories in OpenFunction?

A: OpenFunction uses Shipwright (which utilizes Tekton to integrate with Cloud Native Buildpacks) in the build phase to package the user function to the application image.

Users often choose to access a private image repository in an insecure way, which is not yet supported by the Cloud Native Buildpacks.

We offer a workaround as below to get around this limitation for now:

  1. Use IP address instead of hostname as access address for private image repository.
  2. You should skip tag-resolution when you run the Knative-runtime function.

For references:

buildpacks/lifecycle#524

buildpacks/tekton-integration#31

Q: How to access the Knative-runtime function without introducing a new ingress controller?

A: OpenFunction provides a unified entry point for function accessibility, which is based on the Ingress Nginx implementation. However, for some users, this is not necessary, and instead, introducing a new ingress controller may affect the current cluster.

In general, accessible addresses are for the sync(Knative-runtime) functions. Here are two ways to solve this problem:

  • Magic DNS

    You can follow this guide to config the DNS.

  • CoreDNS

    This is similar to using Magic DNS, with the difference that the configuration for DNS resolution is placed inside CoreDNS. Assume that the user has configured a domain named “openfunction.dev” in the ConfigMap config-domain under the knative-serving namespace (as shown below):

    1. $ kubectl -n knative-serving get cm config-domain -o yaml
    2. apiVersion: v1
    3. data:
    4. openfunction.dev: ""
    5. kind: ConfigMap
    6. metadata:
    7. annotations:
    8. knative.dev/example-checksum: 81552d0b
    9. labels:
    10. app.kubernetes.io/part-of: knative-serving
    11. app.kubernetes.io/version: 1.0.1
    12. serving.knative.dev/release: v1.0.1
    13. name: config-domain
    14. namespace: knative-serving

    Next, let’s add an A record for this domain. OpenFunction uses Kourier as the default network layer for Knative Serving, which is where the domain should flow to.

    1. $ kubectl -n kourier-system get svc
    2. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
    3. kourier LoadBalancer 10.233.7.202 <pending> 80:31655/TCP,443:30980/TCP 36m
    4. kourier-internal ClusterIP 10.233.47.71 <none> 80/TCP 36m

    Then the user only needs to configure this Wild-Card DNS resolution in CoreDNS to resolve the URL address of any Knative Service in the cluster.

    Where “10.233.47.71” is the address of the Service kourier-internal.

    1. $ kubectl -n kube-system get cm coredns -o yaml
    2. apiVersion: v1
    3. data:
    4. Corefile: |
    5. .:53 {
    6. errors
    7. health
    8. ready
    9. template IN A openfunction.dev {
    10. match .*\.openfunction\.dev
    11. answer "{{ .Name }} 60 IN A 10.233.47.71"
    12. fallthrough
    13. }
    14. kubernetes cluster.local in-addr.arpa ip6.arpa {
    15. pods insecure
    16. fallthrough in-addr.arpa ip6.arpa
    17. }
    18. hosts /etc/coredns/NodeHosts {
    19. ttl 60
    20. reload 15s
    21. fallthrough
    22. }
    23. prometheus :9153
    24. forward . /etc/resolv.conf
    25. cache 30
    26. loop
    27. reload
    28. loadbalance
    29. }
    30. ...

    If the user cannot resolve the URL address for this function outside the cluster, configure the hosts file as follows:

    Where “serving-sr5v2-ksvc-sbtgr.default.openfunction.dev” is the URL address obtained from the command “kubectl get ksvc”.

    1. 10.233.47.71 serving-sr5v2-ksvc-sbtgr.default.openfunction.dev

After the above configuration is done, you can get the URL address of the function with the following command. Then you can trigger the function via curl or your browser.

  1. $ kubectl get ksvc
  2. NAME URL
  3. serving-sr5v2-ksvc-sbtgr http://serving-sr5v2-ksvc-sbtgr.default.openfunction.dev

Q: How to enable and configure concurrency for functions?

A: OpenFunction categorizes function types into “sync runtime” and “async runtime” based on the type of request being handled. These two types of functions are driven by Knative Serving and Dapr + KEDA.

Therefore, to enable and configure the concurrency of functions, you need to refer to the specific implementation in the above components.

The following section describes how to enable and configure concurrency of functions in OpenFunction according to the “sync runtime” and “async runtime” sections.

Sync runtime

You can start by referring to this document in Knative Serving on enabling and configuring concurrency capabilities.

Knative Serving has Soft limit and Hard limit configurations for the concurrency feature.

Soft limit

You can refer to the Global(ConfigMap) and Global(Operator) sections of this document to configure global concurrency capabilities.

And for Per Revision you can configure it like this.

  1. apiVersion: core.openfunction.io/v1beta2
  2. kind: Function
  3. metadata:
  4. name: function-sample
  5. spec:
  6. serving:
  7. scaleOptions:
  8. knative:
  9. autoscaling.knative.dev/target: "200"

Hard limit

OpenFunction currently doesn’t support configuring Hard limit for Per Revision. You can refer to the Global(ConfigMap) and Global(Operator) sections of this document to configure global concurrency capabilities.

In summary

In a nutshell, you can configure Knative Serving’s Autoscaling-related configuration items for each function as follows, just as long as they can be passed in as Annotation, otherwise, you can only do global settings.

  1. # Configuration in Knative Serving
  2. apiVersion: serving.knative.dev/v1
  3. kind: Service
  4. metadata:
  5. name: helloworld-go
  6. namespace: default
  7. spec:
  8. template:
  9. metadata:
  10. annotations:
  11. autoscaling.knative.dev/<key>: "value"
  12. # Configuration in OpenFunction (recommended)
  13. apiVersion: core.openfunction.io/v1beta2
  14. kind: Function
  15. metadata:
  16. name: function-sample
  17. spec:
  18. serving:
  19. scaleOptions:
  20. knative:
  21. <key>: "value"
  22. # Alternative approach
  23. apiVersion: core.openfunction.io/v1beta2
  24. kind: Function
  25. metadata:
  26. name: function-sample
  27. spec:
  28. serving:
  29. annotations:
  30. autoscaling.knative.dev/<key>: "value"

Async runtime

You can start by referring to the document in Dapr on enabling and configuring concurrency capabilities.

Compared to the concurrency configuration of sync runtime, the concurrency configuration of async runtime is simpler.

  1. # Configuration in Dapr
  2. apiVersion: apps/v1
  3. kind: Deployment
  4. metadata:
  5. name: nodesubscriber
  6. namespace: default
  7. spec:
  8. template:
  9. metadata:
  10. annotations:
  11. dapr.io/app-max-concurrency: "value"
  12. # Configuration in OpenFunction (recommended)
  13. apiVersion: core.openfunction.io/v1beta2
  14. kind: Function
  15. metadata:
  16. name: function-sample
  17. spec:
  18. serving:
  19. annotations:
  20. dapr.io/app-max-concurrency: "value"

Q: How to create source repository credential for the function image build process?

A: You may be prompted with errors like Unsupported type of credentials provided, either SSH private key or username/password is supported (exit code 110) when using spec.build.srcRepo.credentials, which means you are using an incorrect Secret resource as source repository crendital.

OpenFunction currently implements the function image building framework based on ShipWright, so we need to refer to this document to setup the correct source repository credential.

Q: How to install OpenFunction in an offline environment?

A: You can install and use OpenFunction in an offline environment by following steps:

Pull the Helm Chart

Pull the helm chart in an environment that can access GitHub:

  1. helm repo add openfunction https://openfunction.github.io/charts/
  2. helm repo update
  3. helm pull openfunction/openfunction

Then use tools like scp to copy the helm package to your offline environment, e.g.:

  1. scp openfunction-v1.0.0-v0.5.0.tgz <username>@<your-machine-ip>:/home/<username>/

Synchronize images

You need to sync these images to your private image repository:

  1. # dapr
  2. docker.io/daprio/dashboard:0.10.0
  3. docker.io/daprio/dapr:1.8.3
  4. # keda
  5. openfunction/keda:2.8.1
  6. openfunction/keda-metrics-apiserver:2.8.1
  7. # contour
  8. docker.io/bitnami/contour:1.21.1-debian-11-r5
  9. docker.io/bitnami/envoy:1.22.2-debian-11-r6
  10. docker.io/bitnami/nginx:1.21.6-debian-11-r10
  11. # tekton-pipelines
  12. openfunction/tektoncd-pipeline-cmd-controller:v0.37.2
  13. openfunction/tektoncd-pipeline-cmd-kubeconfigwriter:v0.37.2
  14. openfunction/tektoncd-pipeline-cmd-git-init:v0.37.2
  15. openfunction/tektoncd-pipeline-cmd-entrypoint:v0.37.2
  16. openfunction/tektoncd-pipeline-cmd-nop:v0.37.2
  17. openfunction/tektoncd-pipeline-cmd-imagedigestexporter:v0.37.2
  18. openfunction/tektoncd-pipeline-cmd-pullrequest-init:v0.37.2
  19. openfunction/tektoncd-pipeline-cmd-workingdirinit:v0.37.2
  20. openfunction/cloudsdktool-cloud-sdk@sha256:27b2c22bf259d9bc1a291e99c63791ba0c27a04d2db0a43241ba0f1f20f4067f
  21. openfunction/distroless-base@sha256:b16b57be9160a122ef048333c68ba205ae4fe1a7b7cc6a5b289956292ebf45cc
  22. openfunction/tektoncd-pipeline-cmd-webhook:v0.37.2
  23. # knative-serving
  24. openfunction/knative.dev-serving-cmd-activator:v1.3.2
  25. openfunction/knative.dev-serving-cmd-autoscaler:v1.3.2
  26. openfunction/knative.dev-serving-cmd-queue:v1.3.2
  27. openfunction/knative.dev-serving-cmd-controller:v1.3.2
  28. openfunction/knative.dev-serving-cmd-domain-mapping:v1.3.2
  29. openfunction/knative.dev-serving-cmd-domain-mapping-webhook:v1.3.2
  30. openfunction/knative.dev-net-contour-cmd-controller:v1.3.0
  31. openfunction/knative.dev-serving-cmd-default-domain:v1.3.2
  32. openfunction/knative.dev-serving-cmd-webhook:v1.3.2
  33. # shipwright-build
  34. openfunction/shipwright-shipwright-build-controller:v0.10.0
  35. openfunction/shipwright-io-build-git:v0.10.0
  36. openfunction/shipwright-mutate-image:v0.10.0
  37. openfunction/shipwright-bundle:v0.10.0
  38. openfunction/shipwright-waiter:v0.10.0
  39. openfunction/buildah:v1.23.3
  40. openfunction/buildah:v1.28.0
  41. # openfunction
  42. openfunction/openfunction:v1.0.0
  43. openfunction/kube-rbac-proxy:v0.8.0
  44. openfunction/eventsource-handler:v4
  45. openfunction/trigger-handler:v4
  46. openfunction/dapr-proxy:v0.1.1
  47. openfunction/revision-controller:v1.0.0

Create custom values

Create custom-values.yaml in your offline environment:

  1. touch custom-values.yaml

Edit custom-values.yaml, add the following content:

  1. knative-serving:
  2. activator:
  3. activator:
  4. image:
  5. repository: <your-private-image-repository>/knative.dev-serving-cmd-activator
  6. autoscaler:
  7. autoscaler:
  8. image:
  9. repository: <your-private-image-repository>/knative.dev-serving-cmd-autoscaler
  10. configDeployment:
  11. queueSidecarImage:
  12. repository: <your-private-image-repository>/knative.dev-serving-cmd-queue
  13. controller:
  14. controller:
  15. image:
  16. repository: <your-private-image-repository>/knative.dev-serving-cmd-controller
  17. domainMapping:
  18. domainMapping:
  19. image:
  20. repository: <your-private-image-repository>/knative.dev-serving-cmd-domain-mapping
  21. domainmappingWebhook:
  22. domainmappingWebhook:
  23. image:
  24. repository: <your-private-image-repository>/knative.dev-serving-cmd-domain-mapping-webhook
  25. netContourController:
  26. controller:
  27. image:
  28. repository: <your-private-image-repository>/knative.dev-net-contour-cmd-controller
  29. defaultDomain:
  30. job:
  31. image:
  32. repository: <your-private-image-repository>/knative.dev-serving-cmd-default-domain
  33. webhook:
  34. webhook:
  35. image:
  36. repository: <your-private-image-repository>/knative.dev-serving-cmd-webhook
  37. shipwright-build:
  38. shipwrightBuildController:
  39. shipwrightBuild:
  40. image:
  41. repository: <your-private-image-repository>/shipwright-shipwright-build-controller
  42. GIT_CONTAINER_IMAGE:
  43. repository: <your-private-image-repository>/shipwright-io-build-git
  44. MUTATE_IMAGE_CONTAINER_IMAGE:
  45. repository: <your-private-image-repository>/shipwright-mutate-image
  46. BUNDLE_CONTAINER_IMAGE:
  47. repository: <your-private-image-repository>/shipwright-bundle
  48. WAITER_CONTAINER_IMAGE:
  49. repository: <your-private-image-repository>/shipwright-waiter
  50. tekton-pipelines:
  51. controller:
  52. tektonPipelinesController:
  53. image:
  54. repository: <your-private-image-repository>/tektoncd-pipeline-cmd-controller
  55. kubeconfigWriterImage:
  56. repository: <your-private-image-repository>/tektoncd-pipeline-cmd-kubeconfigwriter
  57. gitImage:
  58. repository: <your-private-image-repository>/tektoncd-pipeline-cmd-git-init
  59. entrypointImage:
  60. repository: <your-private-image-repository>/tektoncd-pipeline-cmd-entrypoint
  61. nopImage:
  62. repository: <your-private-image-repository>/tektoncd-pipeline-cmd-nop
  63. imagedigestExporterImage:
  64. repository: <your-private-image-repository>/tektoncd-pipeline-cmd-imagedigestexporter
  65. prImage:
  66. repository: <your-private-image-repository>/tektoncd-pipeline-cmd-pullrequest-init
  67. workingdirinitImage:
  68. repository: <your-private-image-repository>/tektoncd-pipeline-cmd-workingdirinit
  69. gsutilImage:
  70. repository: <your-private-image-repository>/cloudsdktool-cloud-sdk
  71. digest: sha256:27b2c22bf259d9bc1a291e99c63791ba0c27a04d2db0a43241ba0f1f20f4067f
  72. shellImage:
  73. repository: <your-private-image-repository>/distroless-base
  74. digest: sha256:b16b57be9160a122ef048333c68ba205ae4fe1a7b7cc6a5b289956292ebf45cc
  75. webhook:
  76. webhook:
  77. image:
  78. repository: <your-private-image-repository>/tektoncd-pipeline-cmd-webhook
  79. keda:
  80. image:
  81. keda:
  82. repository: <your-private-image-repository>/keda
  83. tag: 2.8.1
  84. metricsApiServer:
  85. repository: <your-private-image-repository>/keda-metrics-apiserver
  86. tag: 2.8.1
  87. dapr:
  88. global:
  89. registry: <your-private-image-registry>/daprio
  90. tag: '1.8.3'
  91. contour:
  92. contour:
  93. image:
  94. registry: <your-private-image-registry>
  95. repository: <your-private-image-repository>/contour
  96. tag: 1.21.1-debian-11-r5
  97. envoy:
  98. image:
  99. registry: <your-private-image-registry>
  100. repository: <your-private-image-repository>/envoy
  101. tag: 1.22.2-debian-11-r6
  102. defaultBackend:
  103. image:
  104. registry: <your-private-image-registry>
  105. repository: <your-private-image-repository>/nginx
  106. tag: 1.21.6-debian-11-r10

Install OpenFunction

Run the following command in an offline environment to try to install OpenFunction:

  1. kubectl create namespace openfunction
  2. helm install openfunction openfunction-v1.0.0-v0.5.0.tgz -n openfunction -f custom-values.yaml

Note

If the helm install command gets stuck, it may be caused by the job contour-contour-cergen.

Run the following command to confirm whether the job is executed successfully:

  1. kubectl get job contour-contour-cergen -n projectcontour

If the job exists and the job status is completed, run the following command to complete the installation:

  1. helm uninstall openfunction -n openfunction --no-hooks
  2. helm install openfunction openfunction-v1.0.0-v0.5.0.tgz -n openfunction -f custom-values.yaml --no-hooks

Patch ClusterBuildStrategy

If you want to build wasm functions or use buildah to build functions in offline environment, run the following command to patch ClusterBuildStrategy:

  1. kubectl patch clusterbuildstrategy buildah --type='json' -p='[{"op": "replace", "path": "/spec/buildSteps/0/image", "value":"openfunction/buildah:v1.28.0"}]'
  2. kubectl patch clusterbuildstrategy wasmedge --type='json' -p='[{"op": "replace", "path": "/spec/buildSteps/0/image", "value":"openfunction/buildah:v1.28.0"}]'

Q: How to build and run functions in an offline environment

A: Let’s take Java functions as an example to illustrate how to build and run functions in an offline environment:

  • Synchronize https://github.com/OpenFunction/samples.git to your private code repository

  • Follow this prerequisites doc to create push-secret and git-repo-secret

  • Change public maven repository to private maven repository:

    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <project xmlns="http://maven.apache.org/POM/4.0.0"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    5. <modelVersion>4.0.0</modelVersion>
    6. <groupId>dev.openfunction.samples</groupId>
    7. <artifactId>samples</artifactId>
    8. <version>1.0-SNAPSHOT</version>
    9. <properties>
    10. <maven.compiler.source>11</maven.compiler.source>
    11. <maven.compiler.target>11</maven.compiler.target>
    12. </properties>
    13. <repositories>
    14. <repository>
    15. <id>snapshots</id>
    16. <name>Maven snapshots</name>
    17. <!--<url>https://s01.oss.sonatype.org/content/repositories/snapshots/</url>-->
    18. <url>your private maven repository</url>
    19. <releases>
    20. <enabled>false</enabled>
    21. </releases>
    22. <snapshots>
    23. <enabled>true</enabled>
    24. </snapshots>
    25. </repository>
    26. </repositories>
    27. <dependencies>
    28. <dependency>
    29. <groupId>dev.openfunction.functions</groupId>
    30. <artifactId>functions-framework-api</artifactId>
    31. <version>1.0.0-SNAPSHOT</version>
    32. </dependency>
    33. </dependencies>
    34. </project>

    Make sure to commit the changes to the code repo.

  • Synchronize openfunction/buildpacks-java18-run:v1 to your private image repository

  • Modify functions/knative/java/hello-world/function-sample.yaml according to your environment:

    1. apiVersion: core.openfunction.io/v1beta2
    2. kind: Function
    3. metadata:
    4. name: function-http-java
    5. spec:
    6. version: "v2.0.0"
    7. image: "<your private image repository>/sample-java-func:v1"
    8. imageCredentials:
    9. name: push-secret
    10. build:
    11. builder: <your private image repository>/builder-java:v2-18
    12. params:
    13. RUN_IMAGE: "<your private image repository>/buildpacks-java18-run:v1"
    14. env:
    15. FUNC_NAME: "dev.openfunction.samples.HttpFunctionImpl"
    16. FUNC_CLEAR_SOURCE: "true"
    17. srcRepo:
    18. url: "https://<your private code repository>/OpenFunction/samples.git"
    19. sourceSubPath: "functions/knative/java"
    20. revision: "main"
    21. credentials:
    22. name: git-repo-secret
    23. serving:
    24. template:
    25. containers:
    26. - name: function # DO NOT change this
    27. imagePullPolicy: IfNotPresent
    28. triggers:
    29. http:
    30. port: 8080

    If your private mirror repository is insecure, please refer to Use private image repository in an insecure way

  • Run the following commands to build and run the function:

    1. kubectl apply -f functions/knative/java/hello-world/function-sample.yaml