Chapter 4. Configuring OpenShift Serverless applications
4.1. Multi-container support for Serving
You can deploy a multi-container pod by using a single Knative service. This method is useful for separating application responsibilities into smaller, specialized parts.
4.1.1. Configuring a multi-container service
Multi-container support is enabled by default. You can create a multi-container pod by specifiying multiple containers in the service.
Procedure
Modify your service to include additional containers. Only one container can handle requests, so specify
ports
for exactly one container. Here is an example configuration with two containers:Multiple containers configuration
apiVersion: serving.knative.dev/v1 kind: Service ... spec: template: spec: containers: - name: first-container 1 image: gcr.io/knative-samples/helloworld-go ports: - containerPort: 8080 2 - name: second-container 3 image: gcr.io/knative-samples/helloworld-java
4.1.2. Probing a multi-container service
You can specify readiness and liveness probes for multiple containers. This feature is not enabled by default and you must configure it using the KnativeServing
custom resource (CR).
Procedure
Configure multi-container probing for your service by enabling the
multi-container-probing
feature in theKnativeServing
CR.Multi-container probing configuration
... spec: config: features: "multi-container-probing": enabled 1 ...
- 1
- Enabled multi-container-probing feature
Apply the updated
KnativeServing
CR.$ oc apply -f <filename>
Modify your multi-container service to include the specified probes.
Multi-container probing
apiVersion: serving.knative.dev/v1 kind: Service ... spec: template: spec: containers: - name: first-container image: ghcr.io/knative/helloworld-go:latest ports: - containerPort: 8080 readinessProbe: 1 httpGet: port: 8080 - name: second-container image: gcr.io/knative-samples/helloworld-java readinessProbe: 2 httpGet: port: 8090
4.1.2.1. Additional resources
4.2. EmptyDir volumes
emptyDir
volumes are empty volumes that are created when a pod is created, and are used to provide temporary working disk space. emptyDir
volumes are deleted when the pod they were created for is deleted.
4.2.1. Configuring the EmptyDir extension
The kubernetes.podspec-volumes-emptydir
extension controls whether emptyDir
volumes can be used with Knative Serving. To enable using emptyDir
volumes, you must modify the KnativeServing
custom resource (CR) to include the following YAML:
Example KnativeServing CR
apiVersion: operator.knative.dev/v1beta1 kind: KnativeServing metadata: name: knative-serving spec: config: features: kubernetes.podspec-volumes-emptydir: enabled ...
4.3. Persistent Volume Claims for Serving
Some serverless applications require permanent data storage. By configuring different volume types, you can provide data storage for Knative services. Serving supports mounting of the volume types such as secret
, configMap
, projected
, and emptyDir
.
You can configure persistent volume claims (PVCs) for your Knative services. The Persistent volume types are implemented as plugins. To determine if there are any persistent volume types available, you can check the available or installed storage classes in your cluster. Persistent volumes are supported, but require a feature flag to be enabled.
The mounting of large volumes can lead to a considerable delay in the start time of the application.
4.3.1. Enabling PVC support
Procedure
To enable Knative Serving to use PVCs and write to them, modify the
KnativeServing
custom resource (CR) to include the following YAML:Enabling PVCs with write access
... spec: config: features: "kubernetes.podspec-persistent-volume-claim": enabled "kubernetes.podspec-persistent-volume-write": enabled ...
-
The
kubernetes.podspec-persistent-volume-claim
extension controls whether persistent volumes (PVs) can be used with Knative Serving. -
The
kubernetes.podspec-persistent-volume-write
extension controls whether PVs are available to Knative Serving with the write access.
-
The
To claim a PV, modify your service to include the PV configuration. For example, you might have a persistent volume claim with the following configuration:
NoteUse the storage class that supports the access mode you are requesting. For example, you can use the
ocs-storagecluster-cephfs
storage class for theReadWriteMany
access mode.The
ocs-storagecluster-cephfs
storage class is supported and comes from Red Hat OpenShift Data Foundation.PersistentVolumeClaim configuration
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: example-pv-claim namespace: my-ns spec: accessModes: - ReadWriteMany storageClassName: ocs-storagecluster-cephfs resources: requests: storage: 1Gi
In this case, to claim a PV with write access, modify your service as follows:
Knative service PVC configuration
apiVersion: serving.knative.dev/v1 kind: Service metadata: namespace: my-ns ... spec: template: spec: containers: ... volumeMounts: 1 - mountPath: /data name: mydata readOnly: false volumes: - name: mydata persistentVolumeClaim: 2 claimName: example-pv-claim readOnly: false 3
NoteTo successfully use persistent storage in Knative services, you need additional configuration, such as the user permissions for the Knative container user.
4.3.2. Additional resources for OpenShift Container Platform
4.4. Init containers
Init containers are specialized containers that are run before application containers in a pod. They are generally used to implement initialization logic for an application, which may include running setup scripts or downloading required configurations. You can enable the use of init containers for Knative services by modifying the KnativeServing
custom resource (CR).
Init containers may cause longer application start-up times and should be used with caution for serverless applications, which are expected to scale up and down frequently.
4.4.1. Enabling init containers
Prerequisites
- You have installed OpenShift Serverless Operator and Knative Serving on your cluster.
- You have cluster administrator permissions on OpenShift Container Platform, or you have cluster or dedicated administrator permissions on Red Hat OpenShift Service on AWS or OpenShift Dedicated.
Procedure
Enable the use of init containers by adding the
kubernetes.podspec-init-containers
flag to theKnativeServing
CR:Example KnativeServing CR
apiVersion: operator.knative.dev/v1beta1 kind: KnativeServing metadata: name: knative-serving spec: config: features: kubernetes.podspec-init-containers: enabled ...
4.5. Resolving image tags to digests
If the Knative Serving controller has access to the container registry, Knative Serving resolves image tags to a digest when you create a revision of a service. This is known as tag-to-digest resolution, and helps to provide consistency for deployments.
4.5.1. Tag-to-digest resolution
To give the controller access to the container registry on OpenShift Container Platform, you must create a secret and then configure controller custom certificates. You can configure controller custom certificates by modifying the controller-custom-certs
spec in the KnativeServing
custom resource (CR). The secret must reside in the same namespace as the KnativeServing
CR.
If a secret is not included in the KnativeServing
CR, this setting defaults to using public key infrastructure (PKI). When using PKI, the cluster-wide certificates are automatically injected into the Knative Serving controller by using the config-service-sa
config map. The OpenShift Serverless Operator populates the config-service-sa
config map with cluster-wide certificates and mounts the config map as a volume to the controller.
4.5.1.1. Configuring tag-to-digest resolution by using a secret
If the controller-custom-certs
spec uses the Secret
type, the secret is mounted as a secret volume. Knative components consume the secret directly, assuming that the secret has the required certificates.
Prerequisites
- You have cluster administrator permissions on OpenShift Container Platform, or you have cluster or dedicated administrator permissions on Red Hat OpenShift Service on AWS or OpenShift Dedicated.
- You have installed the OpenShift Serverless Operator and Knative Serving on your cluster.
Procedure
Create a secret:
Example command
$ oc -n knative-serving create secret generic custom-secret --from-file=<secret_name>.crt=<path_to_certificate>
Configure the
controller-custom-certs
spec in theKnativeServing
custom resource (CR) to use theSecret
type:Example KnativeServing CR
apiVersion: operator.knative.dev/v1beta1 kind: KnativeServing metadata: name: knative-serving namespace: knative-serving spec: controller-custom-certs: name: custom-secret type: Secret
4.6. Configuring Kourier
Kourier is a lightweight Kubernetes-native Ingress for Knative Serving. Kourier acts as a gateway for Knative, routing HTTP traffic to Knative services.
4.6.1. Customizing kourier-bootstrap for Kourier getaways
The Envoy proxy component in Kourier handles inbound and outbound HTTP traffic for the Knative services. By default, Kourier contains an Envoy bootstrap configuration in the kourier-bootstrap
configuration map in the knative-serving-ingress
namespace. You can change this configuration.
Prerequisites
- You have installed the OpenShift Serverless Operator and Knative Serving.
- You have cluster administrator permissions on OpenShift Container Platform, or you have cluster or dedicated administrator permissions on Red Hat OpenShift Service on AWS or OpenShift Dedicated.
Procedure
Specify a custom bootstrapping configuration map by changing the
spec.ingress.kourier.bootstrap-configmap
field in theKnativeServing
custom resource (CR):Example KnativeServing CR
apiVersion: operator.knative.dev/v1beta1 kind: KnativeServing metadata: name: knative-serving namespace: knative-serving spec: config: network: ingress-class: kourier.ingress.networking.knative.dev ingress: kourier: bootstrap-configmap: my-configmap enabled: true # ...
4.7. Restrictive network policies
4.7.1. Clusters with restrictive network policies
If you are using a cluster that multiple users have access to, your cluster might use network policies to control which pods, services, and namespaces can communicate with each other over the network. If your cluster uses restrictive network policies, it is possible that Knative system pods are not able to access your Knative application. For example, if your namespace has the following network policy, which denies all requests, Knative system pods cannot access your Knative application:
Example NetworkPolicy object that denies all requests to the namespace
kind: NetworkPolicy apiVersion: networking.k8s.io/v1 metadata: name: deny-by-default namespace: example-namespace spec: podSelector: ingress: []
4.7.2. Enabling communication with Knative applications on a cluster with restrictive network policies
To allow access to your applications from Knative system pods, you must add a label to each of the Knative system namespaces, and then create a NetworkPolicy
object in your application namespace that allows access to the namespace for other namespaces that have this label.
A network policy that denies requests to non-Knative services on your cluster still prevents access to these services. However, by allowing access from Knative system namespaces to your Knative application, you are allowing access to your Knative application from all namespaces in the cluster.
If you do not want to allow access to your Knative application from all namespaces on the cluster, you might want to use JSON Web Token authentication for Knative services instead. JSON Web Token authentication for Knative services requires Service Mesh.
Prerequisites
-
Install the OpenShift CLI (
oc
). - OpenShift Serverless Operator and Knative Serving are installed on your cluster.
Procedure
Add the
knative.openshift.io/system-namespace=true
label to each Knative system namespace that requires access to your application:Label the
knative-serving
namespace:$ oc label namespace knative-serving knative.openshift.io/system-namespace=true
Label the
knative-serving-ingress
namespace:$ oc label namespace knative-serving-ingress knative.openshift.io/system-namespace=true
Label the
knative-eventing
namespace:$ oc label namespace knative-eventing knative.openshift.io/system-namespace=true
Label the
knative-kafka
namespace:$ oc label namespace knative-kafka knative.openshift.io/system-namespace=true
Create a
NetworkPolicy
object in your application namespace to allow access from namespaces with theknative.openshift.io/system-namespace
label:Example
NetworkPolicy
objectapiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: <network_policy_name> 1 namespace: <namespace> 2 spec: ingress: - from: - namespaceSelector: matchLabels: knative.openshift.io/system-namespace: "true" podSelector: {} policyTypes: - Ingress
4.8. Configuring revision timeouts
You can configure timeout durations for revisions globally or individually to control the time spent on requests.
4.8.1. Configuring revision timeout
You can configure the default number of seconds for the revision timeout based on the request.
Prerequisites
- You have installed the OpenShift Serverless Operator and Knative Serving.
- You have cluster administrator permissions on OpenShift Container Platform, or cluster or dedicated administrator permissions on Red Hat OpenShift Service on AWS or OpenShift Dedicated.
Procedure
Choose the appropriate method to configure the revision timeout:
To configure the revision timeout globally, set the
revision-timeout-seconds
field in theKnativeServing
custom resource (CR):apiVersion: operator.knative.dev/v1beta1 kind: KnativeServing metadata: name: knative-serving namespace: knative-serving spec: config: defaults: revision-timeout-seconds: "300"
To configure the timeout per revision by setting the
timeoutSeconds
field in your service definition:apiVersion: serving.knative.dev/v1 kind: Service metadata: namespace: my-ns spec: template: spec: timeoutSeconds: 300 containers: - image: ghcr.io/knative/helloworld-go:latest
4.8.2. Configuring maximum revision timeout
By seting the maximum revision timeout, you can ensure that no revision can exceed a specific limit.
Prerequisites
- You have installed the OpenShift Serverless Operator and Knative Serving.
- You have cluster administrator permissions on OpenShift Container Platform, or cluster or dedicated administrator permissions on Red Hat OpenShift Service on AWS or OpenShift Dedicated.
Procedure
To configure the maximum revision timeout, set the
max-revision-timeout-seconds
field in theKnativeServing
custom resource (CR):If this value is increased, the activator `terminationGracePeriodSeconds` should also be increased to prevent in-flight requests being disrupted.
apiVersion: operator.knative.dev/v1beta1 kind: KnativeServing metadata: name: knative-serving namespace: knative-serving spec: config: defaults: max-revision-timeout-seconds: "600"