At Direktiv, we're big fans of Knative. It's not just for serverless – it's a fantastic deployment tool for Kubernetes too.
The project is emphasizing the serverless nature but it's just in general a great deployment tool as well. In my opinion, it simplifies that process because the deployment of e.g. a HTTP services comes down to one file which describes the whole service you want to provide to your applications or users.
I could provide a big overview of how Knative works, but in this little tutorial I want to show you the basic installation and configuration and how to deploy your first Knative service.
Knative Installation
Starting with Knative can be a bit daunting, especially when it comes to choosing the right installation method. There are two primary ways to install Knative: YAML-based installation and the Knative operator.
The YAML-based installation is straightforward, but it's somewhat limited in flexibility. If you need to modify configurations during installation, this method won't be good enough. That's where the Knative operator comes in handy. The operator not only installs the serving component but also the eventing component if required and it is offering more flexibility and customization options.
To get started with the Knative operator, you can use the following command. Do note that it can only be installed in the default
namespace:
kubectl apply -f https://github.com/knative/operator/releases/download/knative-v1.13.3/operator.yaml
Once you've executed the command to install the Knative operator, you should have the operator up and running with two pods in the default
namespace.
To verify that the operator is running, you can use the command kubectl get pods
knative-operator-6d768fb7-xnjgs
operator-webhook-7d6b54d78b-q66fh
Knative is requiring a network layer and you have three different options: Istio, Kourier, and Contour.
Istio: Istio is a powerful service mesh that provides advanced networking, security, and observability features.
Kourier: Kourier is purpose-built for Knative, providing a lightweight and efficient network layer specifically designed for serverless workloads.
Contour: Contour is a Kubernetes ingress controller that can also be used as the network layer for Knative. It provides basic routing and load balancing capabilities.
When deciding which option to choose, consider your specific environment, requirements, and preferences. At Direktiv, we typically opt for Contour due to its simplicity. However, your choice may vary depending on your use case and infrastructure setup.
In this tutorial we will use Contour as well:
kubectl apply --filename https://github.com/knative/net-contour/releases/download/knative-v1.13.0/contour.yaml
Contour installs an internal and external service in two namespaces. If external access to your Knative services isn't needed, you can optimize your setup by deleting the contour-external
namespace. This eliminates the allocation of an unnecessary external IP within the cluster. Simply run the following command:
kubectl delete ns contour-external
Knative Configuration
Installing Knative using a single YAML file with the operator is convenient, but configuring it can be challenging and I find the documentation a bit thin. Therefore I will explain it a little bit (although there is a lot more).
The basic YAML would look like the following snippet.
apiVersion: operator.knative.dev/v1beta1
kind: KnativeServing
metadata:
name: knative-serving
Usually you want to configure the network layer, features and other settings in Knative. You can modify this file to change the settings during installation.
apiVersion: operator.knative.dev/v1beta1
kind: KnativeServing
metadata:
name: direktiv-knative
spec:
ingress:
contour:
enabled: true
deployments:
- name: activator
annotations:
linkerd.io/inject: enabled
config:
features:
multi-container: "enabled"
kubernetes.podspec-volumes-emptydir: "enabled"
kubernetes.podspec-init-containers: "enabled"
autoscaler:
initial-scale: "0"
allow-zero-initial-scale: "true"
min-scale: "0"
deployment:
registries-skipping-tag-resolving: "kind.local,ko.local,dev.local,localhost:5000,localhost:31212"
network:
ingress-class: "contour.ingress.networking.knative.dev"
This YAML is a very simple installation file for Knative. Individual components can be addressed under deployments
. These components can be activator
, autoscaler
, controller
, webhook
or autoscaler-hpa
. In this YAML we are setting an annotation for the activator
pod.
Under config
is the configuration for Knative's different ConfigMaps in kubernetes.
- config-autoscaler
- config-defaults
- config-deployment
- config-domain
- config-features
- config-gc
- config-leader-election
- config-logging
- config-network
- config-observability
- config-tracing
You can lookup all the different settings in the configmaps after installation and tweak your Knative installation like modifying timeouts and maximum connections.
The most important setting in this case is ingress-class: "contour.ingress.networking.knative.dev"
under network. This has to be configured because we are using Contour as network layer in this tutorial.
We recently had one installation where a proxy server was required. Because it took me a little bit to figure out how to set environment variables for the pods I'd like to share the snippet how to do that:
...
deployments:
- name: controller
env:
- container: controllerserving-certs-ctrl-ca
envVars:
- name: HTTP_PROXY
value: "http://myproxy:3128"
- name: HTTPS_PROXY
value: "http://myproxy:3128"
- name: NO_PROXY
value: ".svc,.default,.local,.cluster.local,localhost"
...
After appying the YAML with kubectl apply -f knative.yaml
the list of pods in the default
namespace will look like this and we are ready to install the first service.
knative-operator-6d768fb7-jthff 1/1 Running
operator-webhook-7d6b54d78b-75v46 1/1 Running
autoscaler-79d9fb98c-5mtnd 1/1 Running
controller-cdf856494-lv9qk 1/1 Running
webhook-dddf6fcff-jvdjc 1/1 Running
autoscaler-hpa-7969f4f665-kdhv7 1/1 Running
activator-74cc7497c9-vqch9 1/1 Running
Creating a Service
After setting up Knative it is time to run the first service. Applying the following file will create a Knative service.
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: helloworld-go
spec:
template:
spec:
containers:
- image: direktiv/simple-hello
env:
- name: TARGET
value: "Go Sample v1"
To check if the service is up and running execute kubectl get ksvc
and the service will show up in the list of available Knative services and it's status.
NAMESPACE NAME URL LATESTCREATED LATESTREADY READY REASON
default helloworld-go http://helloworld-go.default.svc.cluster.local helloworld-go-00001 helloworld-go-00001 True
By default Knative would start a pod instance as well but because we have configured allow-zero-initial-scale
and initial-scale
the service will only be prepared for consumption and not started. A simple curl
will "activate" the pod though.
kubectl run -it --rm --restart=Never --image curlimages/curl curl-test -- curl http://helloworld-go.default
Maybe you have noticed the delay when calling the service. This happens when the service does a "cold start" with zero pods available.
At the beginning we said, Knative is a great deployment tool even without the serverless component. We can configure the service to have at least X pods available all the time to avoid those cold starts. With that approach Knative can be used as a simplified Kubernetes deployment tool.
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: helloworld-go
namespace: default
spec:
template:
metadata:
annotations:
autoscaling.knative.dev/min-scale: "1"
spec:
containers:
- image: direktiv/simple-hello
env:
- name: TARGET
value: "Go Sample v1"
The annotation autoscaling.knative.dev/min-scale
would set the minimum number of pods to 1 meaning there is always one pod running at any given time.
I'm hoping this quick introduction to Knative will help you to get started. There is so much more to explore with Knative with e.g. traffic management and versioning. But I will write about this in a different post.
If you have any questions, just leave a comment!
Top comments (0)