copyright | lastupdated | keywords | subcollection | ||
---|---|---|---|---|---|
|
2019-09-17 |
kubernetes, iks, knative |
containers |
{:new_window: target="_blank"} {:shortdesc: .shortdesc} {:screen: .screen} {:pre: .pre} {:table: .aria-labeledby="caption"} {:codeblock: .codeblock} {:tip: .tip} {:note: .note} {:important: .important} {:deprecated: .deprecated} {:download: .download} {:preview: .preview}
{: #serverless-apps-knative}
Learn how to install and use Knative in a Kubernetes cluster in {{site.data.keyword.containerlong_notm}}. {: shortdesc}
What is Knative and why I want use it?
Knative is an open source platform that was developed by IBM, Google, Pivotal, Red Hat, Cisco, and others. The goal is to extend the capabilities of Kubernetes to help you create modern, source-centric containerized, and serverless apps on top of your Kubernetes cluster. The platform is designed to address the needs of developers who today must decide what type of app they want to run in the cloud: 12-factor apps, containers, or functions. Each type of app requires an open source or proprietary solution that is tailored to these apps: Cloud Foundry for 12-factor apps, Kubernetes for containers, and OpenWhisk and others for functions. In the past, developers had to decide what approach they wanted to follow, which led to inflexibility and complexity when different types of apps had to be combined.
Knative uses a consistent approach across programming languages and frameworks to abstract the operational burden of building, deploying, and managing workloads in Kubernetes so that developers can focus on what matters most to them: the source code. You can use proven build processes that you are already familiar with, such as Kaniko, Dockerfile, Bazel, and others. By integrating with Istio, Knative ensures that your serverless and containerized workloads can be easily exposed on the internet, monitored, and controlled, and that your data is encrypted during transit.
How does Knative work?
Knative comes with two key components, or primitives, that help you to deploy and manage your serverless apps in your Kubernetes cluster:
- Serving: The
Serving
primitive helps to deploy serverless apps as Knative services and to automatically scale them, even down to zero instances. To expose your serverless and containerized workloads, Knative uses Istio. When you install the managed Knative add-on, the managed Istio add-on is automatically installed as well. By using the traffic management and intelligent routing capabilities of Istio, you can control what traffic is routed to a specific version of your service, which makes it easy for a developer to test and roll out a new app version or do A-B testing. - Eventing: With the
Eventing
primitive, you can create triggers or event streams that other services can subscribe to. For example, you might want to kick off a new build of your app every time code is pushed to your GitHub master repo. Or you want to run a serverless app only if the temperature drops below freezing point. For example, theEventing
primitive can be integrated into your CI/CD pipeline to automate the build and deployment of apps in case a specific event occurs.
The Knative open-source project deprecated the Build primitive in favor of the Tekton open-source project. The Build primitive provided you with tools to automate the build process for your app from source code to a container image. The Tekton project originated from the Knative project and provides advanced CI/CD features on top of the deprecated Knative Build primitive. For more information, see the Tekton open-source project . {: note}
What is the Managed Knative on {{site.data.keyword.containerlong_notm}} (experimental) add-on?
Managed Knative on {{site.data.keyword.containerlong_notm}} is a managed add-on that integrates Knative and Istio directly with your Kubernetes cluster. The Knative and Istio versions in the add-on are tested by IBM and supported for the use in {{site.data.keyword.containerlong_notm}}. For more information about managed add-ons, see Adding services by using managed add-ons.
Are there any limitations?
If you installed the container image security enforcer admission controller in your cluster, you cannot enable the managed Knative add-on in your cluster.
{: #knative-setup}
Knative builds on top of Istio to ensure that your serverless and containerized workloads can be exposed within the cluster and on the internet. With Istio, you can also monitor and control network traffic between your services and ensure that your data is encrypted during transit. When you install the managed Knative add-on, the managed Istio add-on is automatically installed as well. However, as a developer you don't need to know Ingress specifics because you use Knative features only to work with your serverless app. {: shortdesc}
Before you begin:
- Install the IBM Cloud CLI, the {{site.data.keyword.containerlong_notm}} plug-in, and the Kubernetes CLI. Make sure to install the
kubectl
CLI version that matches the Kubernetes version of your cluster. - Create a standard cluster with at least 3 worker nodes that each have 4 cores and 16 GB memory (
b3c.4x16
) or more. Additionally, the cluster and worker nodes must run at least the minimum supported version of Kubernetes, which you can review by runningibmcloud ks addon-versions --addon knative
. - Ensure that you have the Writer or Manager {{site.data.keyword.cloud_notm}} IAM service role for {{site.data.keyword.containerlong_notm}}.
- Target the CLI to your cluster.
To install Knative in your cluster:
-
Enable the managed Knative add-on in your cluster. When you enable Knative in your cluster, Istio and all Knative components are installed in your cluster.
ibmcloud ks cluster addon enable knative --cluster <cluster_name_or_ID> -y
{: pre}
Example output:
Enabling add-on knative for cluster knative... OK
{: screen}
The installation of all Knative components might take a few minutes to complete.
-
Verify that Istio is successfully installed. All pods for the nine Istio services and the pod for Prometheus must be in a
Running
status.kubectl get pods --namespace istio-system
{: pre}
Example output:
NAME READY STATUS RESTARTS AGE istio-citadel-748d656b-pj9bw 1/1 Running 0 2m istio-egressgateway-6c65d7c98d-l54kg 1/1 Running 0 2m istio-galley-65cfbc6fd7-bpnqx 1/1 Running 0 2m istio-ingressgateway-f8dd85989-6w6nj 1/1 Running 0 2m istio-pilot-5fd885964b-l4df6 2/2 Running 0 2m istio-policy-56f4f4cbbd-2z2bk 2/2 Running 0 2m istio-sidecar-injector-646655c8cd-rwvsx 1/1 Running 0 2m istio-statsd-prom-bridge-7fdbbf769-8k42l 1/1 Running 0 2m istio-telemetry-8687d9d745-mwjbf 2/2 Running 0 2m prometheus-55c7c698d6-f4drj 1/1 Running 0 2m
{: screen}
-
Optional: If you want to use Istio for all other apps in the
default
namespace, add theistio-injection=enabled
label to the namespace. Each serverless app pod that you create with Knative automatically runs an Envoy proxy sidecar so that the app can be included in the Istio service mesh. However, other apps in your namespaces are not included in the Istio service mesh by default. To include these apps, you must apply the label.kubectl label namespace default istio-injection=enabled
{: pre}
-
Verify that all pods of the Knative
Serving
component are in aRunning
state.kubectl get pods --namespace knative-serving
{: pre}
Example output:
NAME READY STATUS RESTARTS AGE activator-598b4b7787-ps7mj 2/2 Running 0 21m autoscaler-5cf5cfb4dc-mcc2l 2/2 Running 0 21m controller-7fc84c6584-qlzk2 1/1 Running 0 21m webhook-7797ffb6bf-wg46v 1/1 Running 0 21m
{: screen}
{: #update-knative-addon}
Update your Knative add-on to the latest versions. {: shortdesc}
-
Check whether your add-on is at the latest version. If your add-on is denoted with
* (<version> latest)
, you can update the add-on.ibmcloud ks cluster addons --cluster <mycluster> | grep knative
{: pre}
Example output:
OK Name Version knative 0.7.1* (<version> latest)
{: screen}
-
Save any resources, such as configuration files for any services or apps, that you created or modified in the
knative-serving
,knative-monitoring
, andknative-eventing
namespaces. Example command:kubectl get pod <pod_name> -o yaml -n knative-serving > knative-serving-pods.yaml kubectl get pod <pod_name> -o yaml -n knative-monitoring > knative-monitoring-pods.yaml kubectl get pod <pod_name> -o yaml -n knative-eventing > knative-eventing-pods.yaml
{: pre}
-
Save the Kubernetes resources that were automatically generated in the Knative namespaces to a YAML file on your local machine. These resources are generated by using custom resource definitions (CRDs).
-
Get the CRDs for the
knative-serving
,knative-monitoring
, andknative-eventing
namespaces.kubectl get crd -n knative-serving kubectl get crd -n knative-monitoring kubectl get crd -n knative-eventing
{: pre}
-
Save any resources created from these CRDs.
-
-
If you modified any of the following Knative resources, get the YAML file and save them to your local machine. If you modified any of these resources, but you want to use the installed default instead, you can delete the resource. After a few minutes, the resource is re-created with the installed default values.
Resource name | Resource type | Namespace |
---|---|---|
config-autoscaler | ConfigMap | knative-serving |
config-controller | ConfigMap | knative-serving |
config-domain | ConfigMap | knative-serving |
config-gc | ConfigMap | knative-serving |
config-istio | ConfigMap | knative-serving |
config-logging | ConfigMap | knative-serving |
config-network | ConfigMap | knative-serving |
config-observability | ConfigMap | knative-serving |
kaniko | BuildTemplate | default |
iks-knative-ingress | Ingress | istio-system |
Example command:
kubectl get cm config-autoscaler -n knative-serving -o yaml > config-autoscaler.yaml
{: pre}
-
Disable the add-on in your cluster.
ibmcloud ks cluster addon disable knative --cluster <cluster_name_or_ID> -f
{: pre}
-
Verify that the
knative-serving
,knative-monitoring
,knative-eventing
, andistio-system
namespaces are deleted. The namespaces might have a STATUS ofTerminating
for a few minutes before they are deleted.kubectl get namespaces -w
{: pre}
-
Re-enable the add-on.
ibmcloud ks cluster addon enable knative --cluster <cluster_name_or_ID> --version <version>
{: pre}
-
Apply the CRD resources that you saved in step 3.
kubectl apply -f crd.yaml -n knative-serving kubectl apply -f crd.yaml -n knative-monitoring kubectl apply -f crd.yaml -n knative-eventing
{: pre}
-
If you saved any of the resources in step 4, reapply them.
Example command:
kubectl apply -f config-autoscaler.yaml -n knative-serving
{: pre}
-
If you saved any pod configuration files in step 2, reapply them.
kubectl apply -f knative-serving-pods.yaml kubectl apply -f knative-monitoring-pods.yaml kubectl apply -f knative-eventing-pods.yaml
{: pre}
-
Verify that your cluster uses the latest version of the Knative managed add-on.
ibmcloud ks cluster addons --cluster <mycluster> | grep knative
{: pre}
Example output:
OK Name Version knative 0.7.1
{: screen}
{: #knative-deploy-app}
After you set up Knative in your cluster, you can deploy your serverless app as a Knative service. {: shortdesc}
What is a Knative service?
To deploy an app with Knative, you must specify a Knative Service
resource. A Knative service is managed by the Knative Serving
primitive and is responsible to manage the entire lifecycle of the workload. When you create the service, the Knative Serving
primitive automatically creates a version for your serverless app and adds this version to the revision history of the service. Your serverless app is assigned a public URL from your Ingress subdomain in the format <knative_service_name>-<namespace>.<ingress_subdomain>
that you can use to access the app from the internet. In addition, a private hostname is assigned to your app in the format <knative_service_name>-<namespace>.cluster.local
that you can use to access your app from within the cluster.
What happens behind the scenes when I create the Knative service?
When you create a Knative service, your app is automatically deployed as a Kubernetes pod in your cluster and exposed by using a Kubernetes service. To assign the public hostname, Knative uses the IBM-provided Ingress subdomain and TLS certificate. Incoming network traffic is routed based on the default IBM-provided Ingress routing rules.
How can I roll out a new version of my app?
When you update your Knative service, a new version of your serverless app is created. This version is assigned the same public and private hostnames as your previous version. By default, all incoming network traffic is routed to the latest version of your app. However, you can also specify the percentage of incoming network traffic that you want to route to a specific app version so that you can do A-B testing. You can split incoming network traffic between two app versions at a time, the current version of your app and the new version that you want to roll over to.
Can I bring my own custom domain and TLS certificate?
You can change the configmap of your Istio Ingress gateway and the Ingress routing rules to use your custom domain name and TLS certificate when you assign a hostname to your serverless app. For more information, see Setting up custom domain names and certificates.
To deploy your serverless app as a Knative service:
-
Create a YAML file for your first serverless
Hello World
app in Go with Knative. When you send a request to your sample app, the app reads the environment variableTARGET
and prints"Hello ${TARGET}!"
. If this environment variable is empty,"Hello World!"
is returned.apiVersion: serving.knative.dev/v1alpha1 kind: Service metadata: name: kn-helloworld namespace: default spec: template: spec: containers: - image: docker.io/ibmcom/kn-helloworld env: - name: TARGET value: "Go Sample v1"
{: codeblock}
Understanding the YAML file components -
Create the Knative service in your cluster.
kubectl apply -f service.yaml
{: pre}
Example output:
service.serving.knative.dev "kn-helloworld" created
{: screen}
-
Verify that your Knative service is created. In your CLI output, you can view the public DOMAIN that is assigned to your serverless app. The LATESTCREATED and LATESTREADY columns show the version of your app that was last created and that is currently deployed in the format
<knative_service_name>-<version>
. The version that is assigned to your app is a random string value. In this example, the version of your serverless app isrjmwt
. When you update the service, a new version of your app is created and assigned a new random string for the version.kubectl get ksvc/kn-helloworld
{: pre}
Example output:
NAME DOMAIN LATESTCREATED LATESTREADY READY REASON kn-helloworld kn-helloworld-default.mycluster.us-south.containers.appdomain.cloud kn-helloworld-rjmwt kn-helloworld-rjmwt True
{: screen}
-
Try out your
Hello World
app by sending a request to the public URL that is assigned to your app.curl -v <public_app_url>
{: pre}
Example output:
* Rebuilt URL to: kn-helloworld-default.mycluster.us-south.containers.appdomain.cloud/ * Trying 169.46.XX.XX... * TCP_NODELAY set * Connected to kn-helloworld-default.mycluster.us-south.containers.appdomain.cloud (169.46.XX.XX) port 80 (#0) > GET / HTTP/1.1 > Host: kn-helloworld-default.mycluster.us-south.containers.appdomain.cloud > User-Agent: curl/7.54.0 > Accept: */* > < HTTP/1.1 200 OK < Date: Thu, 21 Mar 2019 01:12:48 GMT < Content-Type: text/plain; charset=utf-8 < Content-Length: 20 < Connection: keep-alive < x-envoy-upstream-service-time: 17 < Hello Go Sample v1! * Connection #0 to host kn-helloworld-default.mycluster.us-south.containers.appdomain.cloud left intact
{: screen}
-
List the number of pods that were created for your Knative service. In the example in this topic, one pod is deployed that consists of two containers. One container runs your
Hello World
app and the other container is a side car that runs Istio and Knative monitoring and logging tools.kubectl get pods
{: pre}
Example output:
NAME READY STATUS RESTARTS AGE kn-helloworld-rjmwt-deployment-55db6bf4c5-2vftm 2/2 Running 0 16s
{: screen}
-
Wait a few minutes to let Knative scale down your pod. Knative evaluates the number of pods that must be up at a time to process incoming workload. If no network traffic is received, Knative automatically scales down your pods, even to zero pods as shown in this example.
Want to see how Knative scales up your pods? Try to increase workload for your app, for example by using tools like the Simple cloud-based load tester. {: tip}
kubectl get pods
{: pre}
If you do not see any
kn-helloworld
pods, Knative scaled down your app to zero pods. -
Update your Knative service sample and enter a different value for the
TARGET
environment variable.Example service YAML:
apiVersion: serving.knative.dev/v1alpha1 kind: Service metadata: name: kn-helloworld namespace: default spec: template: spec: containers: - image: docker.io/ibmcom/kn-helloworld env: - name: TARGET value: "Mr. Smith"
{: codeblock}
-
Apply the change to your service. When you change the configuration, Knative automatically creates a new version for your app.
kubectl apply -f service.yaml
{: pre}
-
Verify that a new version of your app is deployed. In your CLI output, you can see the new version of your app in the LATESTCREATED column. When you see the same app version in the LATESTREADY column, your app is all set up and ready to receive incoming network traffic on the assigned public URL.
kubectl get ksvc/kn-helloworld
{: pre}
Example output:
NAME DOMAIN LATESTCREATED LATESTREADY READY REASON kn-helloworld kn-helloworld-default.mycluster.us-south.containers.appdomain.cloud kn-helloworld-ghyei kn-helloworld-ghyei True
{: screen}
-
Make a new request to your app to verify that your change was applied.
curl -v <service_domain>
Example output:
... Hello Mr. Smith!
{: screen}
-
Verify that Knative scaled up your pod again to account for the increased network traffic.
kubectl get pods
Example output:
NAME READY STATUS RESTARTS AGE kn-helloworld-ghyei-deployment-55db6bf4c5-2vftm 2/2 Running 0 16s
{: screen}
-
Optional: Clean up your Knative service.
kubectl delete -f service.yaml
{: pre}
{: #knative-custom-domain-tls}
You can configure Knative to assign hostnames from your own custom domain that you configured with TLS. {: shortdesc}
By default, every app is assigned a public subdomain from your Ingress subdomain in the format <knative_service_name>-<namespace>.<ingress_subdomain>
that you can use to access the app from the Internet. In addition, a private hostname is assigned to your app in the format <knative_service_name>-<namespace>.cluster.local
that you can use to access your app from within the cluster. If you want to assign hostnames from a custom domain that you own, you can change the Knative configmap to use the custom domain instead.
-
Create a custom domain. To register your custom domain, work with your Domain Name Service (DNS) provider or IBM Cloud DNS.
-
Configure your domain to route incoming network traffic to the IBM-provided Ingress gateway. Choose between these options:
- Define an alias for your custom domain by specifying the IBM-provided domain as a Canonical Name record (CNAME). To find the IBM-provided Ingress domain, run
ibmcloud ks cluster get --cluster <cluster_name>
and look for the Ingress subdomain field. Using a CNAME is preferred because IBM provides automatic health checks on the IBM subdomain and removes any failing IPs from the DNS response. - Map your custom domain to the portable public IP address of the Ingress gateway by adding the IP address as an A record. To find the public IP address of the Ingress gateway, run
nslookup <ingress_subdomain>
.
- Define an alias for your custom domain by specifying the IBM-provided domain as a Canonical Name record (CNAME). To find the IBM-provided Ingress domain, run
-
Purchase an official wildcard TLS certificate for your custom domain. If you want to purchase multiple TLS certificates, make sure the CN is different for each certificate.
-
Create a Kubernetes secret for your cert and key.
-
Encode the cert and key into base-64 and save the base-64 encoded value in a new file.
openssl base64 -in tls.key -out tls.key.base64
{: pre}
-
View the base-64 encoded value for your cert and key.
cat tls.key.base64
{: pre}
-
Create a secret YAML file by using the cert and key.
apiVersion: v1 kind: Secret metadata: name: mydomain-ssl type: Opaque data: tls.crt: <client_certificate> tls.key: <client_key>
{: codeblock}
-
Create the certificate in your cluster.
kubectl apply -f secret.yaml
{: pre}
-
-
Open the
iks-knative-ingress
Ingress resource in theistio-system
namespace of your cluster to start editing it.kubectl edit ingress iks-knative-ingress -n istio-system
{: pre}
-
Change the default routing rules for your Ingress.
- Add your custom wildcard domain to the
spec.rules.host
section so that all incoming network traffic from your custom domain and any subdomain is routed to theistio-ingressgateway
. - Configure all hosts of your custom wildcard domain to use the TLS secret that you created earlier in the
spec.tls.hosts
section.
Example Ingress:
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: iks-knative-ingress namespace: istio-system spec: rules: - host: '*.mydomain' http: paths: - backend: serviceName: istio-ingressgateway servicePort: 80 path: / tls: - hosts: - '*.mydomain' secretName: mydomain-ssl
{: codeblock}
The
spec.rules.host
andspec.tls.hosts
sections are lists and can include multiple custom domains and TLS certificates. {: tip} - Add your custom wildcard domain to the
-
Modify the Knative
config-domain
configmap to use your custom domain to assign hostnames to new Knative services.-
Open the
config-domain
configmap to start editing it.kubectl edit configmap config-domain -n knative-serving
{: pre}
-
Specify your custom domain in the
data
section of your configmap and remove the default domain that is set for your cluster.-
Example to assign a hostname from your custom domain for all Knative services:
apiVersion: v1 kind: ConfigMap data: <custom_domain>: "" metadata: name: config-domain namespace: knative-serving
{: codeblock}
By adding
""
to your custom domain, all Knative services that you create are assigned a hostname from your custom domain. -
Example to assign a hostname from your custom domain for select Knative services:
apiVersion: v1 kind: ConfigMap data: <custom_domain>: | selector: app: sample mycluster.us-south.containers.appdomain.cloud: "" metadata: name: config-domain namespace: knative-serving
{: codeblock}
To assign a hostname from your custom domain for select Knative services only, add a
data.selector
label key and value to your configmap. In this example, all services with the labelapp: sample
are assigned a hostname from your custom domain. Make sure to also have a domain name that you want to assign to all other apps that do not have theapp: sample
label. In this example, the default IBM-provided domainmycluster.us-south.containers.appdomain.cloud
is used.
-
-
Save your changes.
-
With your Ingress routing rules and Knative configmaps all set up, you can create Knative services with your custom domain and TLS certificate.
{: #knative-access-volume}
Access Kubernetes secrets and config maps from your Knative service by mounting the secret or config map as a volume to your Knative service.
{: shortdesc}
Knative services support the Kubernetes volume
specification to mount an existing Kubernetes secret or configmap to your app. Although the volume
specification is supported, not all of the related features are supported in Knative. As of today, you can mount volumes that point to Kubernetes secrets or config maps only. To access other types of volumes, such as persistent volume claims (PVCs), you must use Kubernetes directly.
{: note}
-
Retrieve existing Kubernetes secrets or config maps in your cluster and note the name of the secret or config map that you want to mount.
Example command for secrets:
kubectl get secrets
{: pre}
Example command for config maps:
kubectl get configmaps
{: pre}
-
Reference your secret or config map as a Kubernetes volume in your Knative service. To share secrets and config maps across Knative services, mount the volume to every Knative service that must access the data.
Example YAML file for mounting a secret:
apiVersion: serving.knative.dev/v1alpha1 kind: Service metadata: name: kn-helloworld namespace: default spec: template: spec: containers: - image: docker.io/ibmcom/kn-helloworld volumeMounts: - name: <volume_name> mountPath: /<file_path> volumes: - name: <volume_name> secret: secretName: <secret_name>
{: codeblock}
Example YAML file for mounting a config map:
apiVersion: serving.knative.dev/v1alpha1 kind: Service metadata: name: kn-helloworld namespace: default spec: template: spec: containers: - image: docker.io/ibmcom/kn-helloworld volumeMounts: - name: <volume_name> mountPath: /<file_path> volumes: - name: <volume_name> configMap: name: <configmap_name>
{: codeblock}
Understanding the YAML file components -
Create the Knative service in your cluster.
kubectl apply -f service.yaml
{: pre}
Example output:
service.serving.knative.dev "kn-helloworld" created
{: screen}
{: #knative-private-registry}
To access a container registry, your cluster must bet set up with the appropriate image pull secrets that include the credentials to authenticate with your registry. By default, Knative services can access images that are stored in {{site.data.keyword.registryshort_notm}}. To access other private registries, you must store the credentials in a Kubernetes image pull secret in your cluster. {: shortdesc}
-
Follow the instructions to create an image pull secret that includes the credentials to access your private container registry.
-
Create a Knative service that uses the image pull secret. You can choose if you want to reference the image pull secret in your Knative service directly as shown in the following example, or to add the image pull secret to the Kubernetes service account of the namespace where you want to deploy your Knative service.
Example to reference the image pull secret in your Knative service:
apiVersion: serving.knative.dev/v1alpha1 kind: Service metadata: name: kn-helloworld namespace: default spec: template: spec: containers: - image: docker.io/ibmcom/kn-helloworld imagePullSecrets: - name: <secret_name>
{: codeblock}
-
Create the Knative service in your cluster.
kubectl apply -f service.yaml
{: pre}
Example output:
service.serving.knative.dev "kn-helloworld" created
{: screen}
{: #knative-access-service}
You can access your Knative service from another Knative service by using a REST API call to the URL that is assigned to your Knative service. {: shortdesc}
-
List all Knative services in your cluster.
kubectl get ksvc --all-namespaces
{: pre}
-
Retrieve the DOMAIN that is assigned to your Knative service.
kubect get ksvc/<knative_service_name>
{: pre}
Example output:
NAME DOMAIN LATESTCREATED LATESTREADY READY REASON myservice myservice-default.mycluster.us-south.containers.appdomain.cloud myservice-rjmwt myservice-rjmwt True
{: screen}
-
Use the domain name to implement a REST API call to access your Knative service. This REST API call must be part of the app for which you create a Knative service. If the Knative service that you want to access is assigned a local URL in the format
<service_name>-<namespace>.svc.cluster.local
, Knative keeps the REST API request within the cluster-internal network.Example code snippet in Go:
resp, err := http.Get("<knative_service_domain_name>") if err != nil { fmt.Fprintf(os.Stderr, "Error: %s\n", err) } else if resp.Body != nil { body, _ := ioutil.ReadAll(resp.Body) fmt.Printf("Response: %s\n", string(body)) }
{: codeblock}
{: #knative-service-settings}
Review common Knative service settings that you might find useful as you develop your serverless app. {: shortdesc}
- Setting the minimum and maximum number of pods
- Scaling your app based on CPU usage or number of requests
- Specifying the maximum number of requests per pod
- Changing the default container port
- Changing the
scale-to-zero-grace-period
- Creating private-only serverless apps
- Forcing the Knative service to repull a container image
{: #knative-min-max-pods}
You can specify the minimum and maximum number of pods that you want to run for your apps by using an annotation. For example, if you don't want Knative to scale down your app to zero instances, set the minimum number of pods to 1. {: shortdesc}
apiVersion: serving.knative.dev/v1alpha1
kind: Service
metadata:
name: ...
spec:
template:
metadata:
annotations:
autoscaling.knative.dev/minScale: "1"
autoscaling.knative.dev/maxScale: "100"
spec:
containers:
- image: <image_name>
...
{: codeblock}
{: #scale-cpu-vs-number-requests}
By default, Knative scales your app based on the average number of incoming requests per pod. If the number of concurrent requests exceeds the default setting of 100 requests per pod, Knative automatically creates another instance of your pod and starts load balancing incoming requests between your instances. This behavior is also referred to as concurrency or concurrent auto-scaling. You can change the default number of requests by specifying the number of requests per pod. To instruct Knative to scale your app based on CPU usage instead, use the autoscaling.knative.dev/metric
annotation.
{: shortdesc}
apiVersion: serving.knative.dev/v1alpha1
kind: Service
metadata:
name: myservice
spec:
template:
metadata:
annotations:
autoscaling.knative.dev/metric: cpu
autoscaling.knative.dev/target: 80
spec:
containers:
- image: <image_name>
....
{: codeblock}
{: #max-request-per-pod}
You can specify the maximum number of requests that an app instance can receive and process before Knative considers to scale up your app instances. For example, if you set the maximum number of requests to 1, then your app instance can receive one request at a time. If a second request arrives before the first one is fully processed, Knative scales up another instance. By default, Knative sets the maximum number of requests for a pod to 100.
apiVersion: serving.knative.dev/v1alpha1
kind: Service
metadata:
name: myservice
spec:
template:
spec:
containers:
- image: <image_name>
containerConcurrency: 1
....
{: codeblock}
Understanding the YAML file components | |
---|---|
containerConcurrency |
Enter the maximum number of requests an app instance can receive at a time before Knative considers to scale up your app instances. |
{: #knative-container-port}
By default, all incoming requests to your Knative service are sent to port 8080. You can change this setting by using the containerPort
specification.
{: shortdesc}
apiVersion: serving.knative.dev/v1alpha1
kind: Service
metadata:
name: ...
spec:
template:
spec:
containers:
- image: <image_name>
ports:
- containerPort: <container_port>
{: codeblock}
{: #knative-idle-time}
Change the default time that your Knative service instance does not receive any requests before Knative scales down your service to zero instances. {: shortdesc}
Knative uses the config-autoscaler
config map in the knative-serving
namespace to determine the amount of time to wait before a stable Knative service is considered idle
and can be scaled down to zero instances. This time is also referred to as the scale-to-zero-grace-period
. By default, the grace period is set to 30 seconds. However, before Knative starts counting down the seconds, the service must be considered stable for 60 seconds (stable-window
). For example, if requests are stopped to your app, your Knative service instance is still up for the next 90 seconds (60s stable window
+ 30s scale-to-zero-grace-period
) before Knative scales down your service to zero instances.
If you do not want Knative to scale down your service to zero instances, set the minimum number of pods to 1. {: tip}
-
Open the
config-autoscaler
config map in theknative-serving
namespace of your cluster. The config map opens in thevi
editor.kubectl edit configmap config-autoscaler -n knative-serving
{: pre}
-
Change the default value for the
scale-to-zero-grace-period
. The new value must be configured in seconds (s
).scale-to-zero-grace-period: "60s"
{: codeblock}
-
Optional. To also change the time that your service must be considered stable, update the
stable-window
property. The new value must be configured in seconds (s
).stable-window: "90s"
{: codeblock}
-
Save your changes to the config map and close the
vi
editor. Your changes are automatically applied to existing and new Knative services.
{: #knative-private-only}
By default, every Knative service is assigned a public route from your Istio Ingress subdomain and a private route in the format <service_name>.<namespace>.cluster.local
. You can use the public route to access your app from the public network. If you want to keep your service private, you can add the serving.knative.dev/visibility
label to your Knative service. This label instructs Knative to assign a private hostname to your service only.
{: shortdesc}
apiVersion: serving.knative.dev/v1alpha1
kind: Service
metadata:
name: myservice
labels:
serving.knative.dev/visibility: cluster-local
spec:
template:
spec:
containers:
- image: <image_name>
...
{: codeblock}
{: #knative-repull-image}
The current implementation of Knative does not provide a standard way to force your Knative Serving
component to repull a container image. To repull an image from your registry, choose between the following options:
-
Modify the Knative service
template
: Thetemplate
of a Knative service is used to create a revision of your Knative service. If you modify this template and for example, add therepullFlag
annotation, Knative must create a new revision for your app. As part of creating the revision, Knative must check for container image updates. When you setimagePullPolicy: Always
, Knative cannot use the image cache in the cluster, but instead must pull the image from your container registry.apiVersion: serving.knative.dev/v1alpha1 kind: Service metadata: name: <service_name> spec: template: metadata: annotations: repullFlag: 123 spec: containers: - image: <image_name> imagePullPolicy: Always
{: codeblock}
You must change the
repullFlag
value every time that you want to create a new revision of your service that pulls the latest image version from your container registry. Make sure that you use a unique value for each revision to avoid that Knative uses an old image version because of two identical Knative service configurations.
{: note} -
Use tags to create unique container images: You can use unique tags for every container image that you create and reference this image in your Knative service
container.image
configuration. In the following example,v1
is used as the image tag. To force Knative to pull a new image from your container registry, you must change the image tag. For example, usev2
as your new image tag.apiVersion: serving.knative.dev/v1alpha1 kind: Service metadata: name: <service_name> spec: template: spec: containers: - image: myapp:v1 imagePullPolicy: Always
{: codeblock}
{: #knative-related-links}
- Try out this Knative workshop to deploy your first
Node.js
fibonacci app to your cluster.- Explore how to use the Knative
Build
primitive to build an image from a Dockerfile in GitHub and automatically push the image to your namespace in {{site.data.keyword.registrylong_notm}}. - Learn how you can set up routing for network traffic from the IBM-provided Ingress subdomain to the Istio Ingress gateway that is provided by Knative.
- Roll out a new version of your app and use Istio to control the amount of traffic that is routed to each app version.
- Explore how to use the Knative
- Explore Knative
Eventing
samples. - Learn more about Knative with the Knative documentation .