Elevate your Cloud-Native Journey: Knative the VMware Tanzu Way Part I - Streamlined Installation of Knative
Knative 💙
In the rapidly evolving landscape of modern software architecture, event-driven systems have emerged as a pivotal paradigm, empowering organizations to create highly responsive, scalable, and adaptable applications. Knative stands at the forefront of this revolution, offering a robust and flexible framework for building event-driven architectures (EDA) that seamlessly integrate diverse components, enhance automation, and enable real-time data processing.
I’m evangelizing and supporting the Knative project for a longer time already. I recently had the pleasure to demonstrate parts of its comprehensive feature set at the great ContainerDays event in beautiful Hamburg, Germany.
After a rough start AV wise the demo gods are with @vmw_rguske! Amazing live coding session going on at stage K4🤘 #CDS23 #kubernetes #k8s #knative pic.twitter.com/vSbzhFbVta
— David de Hoop ☁️🚀🧑💻 (@DavidShadoow) September 11, 2023
The overall positive feedback afterwards was gratifying and confirmed best that Knative is just awesome 🚀.
Like it is often with exciting technologies which captivate me, the more I get into it, the more my excitement increases. But still, it feels like I’m just scratching the surface giving the fact, that the project continues to evolve and that it admittedly also has its complexity.
In my blog post Demoing Knative Serving and Eventing using Demo-Magic-Scripts, I barely touched two of the three building blocks of Knative, which are Serving, Eventing and Functions. But the intention of the post was more to promote the demo-magic scripts I’ve created in order to “easily” demo some Serving and Eventing goodness, as well as a recording of my VMware {Code} session.
Therefore, it’s about time to start a new blog series and to share with you what I’ve touched on so far, which experiences I’ve made on my journey and most important, to provide hints, resources and tips & tricks which hopefully helps you on your journey with this thrilling project.
Naturally, such a series (IMO) has to start with guidance on how-to install Knative on an existing Kubernetes environment. Consequently, this first post will cover the installation of Knative.
The easiest way to get started is Knative Quickstart, a plugin for the Knative cli kn
. It’ll install the minimium of the Serving and Eventing components on a local KinD cluster. But keep in mind, it’s for experimentation use only. Which is fine for the start!
Giving the fact that I’m working for VMware, I’m going to describe how to install Knative the VMware Tanzu way.
VMware Tanzu Cloud Native Runtimes
Tanzu Cloud Native Runtimes, commonly known as CNR, is VMware’s supported Knative offering for Serving and Eventing. In a nutshell, it’s a packaged, simple to deploy and with some VMware goodies equipped Knative version.
Simple to deploy because Day-1 as well as Day-2 operations of each building block (Serving, Eventing) will be done using the Carvel tools suite. A comprehensive set of reliable, single-purpose tools which simplify the life-cycle of applications (Figure I).
The mentioned “goodies” are covered in one of the next posts.
In order to manage internal and external access to the services in a cluster, CNR uses Contour, an open source Kubernetes ingress controller maintained by VMware.
As of writing this series, CNR version 2.3.1 is latest
and also the version which I’m using for the sake of this post. It’s recommended to check the CNR release notes before start installing CNR (as usual). CNR version 2.3.1 includes Knative 1.10.2 and supports Kubernetes version 1.25 and higher.
Prerequisites
Here’s the thing! Cloud Native Runtimes is not a single purchasable VMware solution. It’s part of VMware’s modular application development platform solution Tanzu Application Platform (TAP). It is used as the runtime foundation for TAP and provides many of the great Knative Serving features, like:
- scale from 0 to many and back to 0 (concurrency-based scaling)
- traffic routing/splitting
- traffic encryption
Therefore, the TAP documentation is the source of truth for topics like prerequisites and installation details. Please make sure to read it carefully and to meet the documented prerequisites.
TL;DR:
- A Tanzu Network account to download Tanzu Application Platform packages
- Network access to https://registry.tanzu.vmware.com
- A container image registry, such as Harbor for application images, base images, and runtime dependencies
- with enough storage capacity
- A wildcard subdomain for applications
- An appropriate Kubernetes cluster-size - Resource requirements
- Installation of the Cluster Essentials for non-Tanzu Kubernetes clusters (TKC)
Important:
If you are planning to install CNR on a non-Tanzu Kubernetes Grid (TKG = VMware’s Kubernetes solution) cluster, please make sure to install the Cluster Essentials as documented.
:down_arrow::up_arrow: Relocation of Image-Bundles/Packages
One preperation for the actual installation requires the relocation of the necessary installation image-bundles. Relocation describes the download and upload of an image-bundle. A bundle captures your configuration files and a list of references to images on which they depend.
Basically, it’s not a “hard” requirement but it’s recommended to relocate the bundles to your own private Cloud Native Registry, like Harbor, in order to be independed from the availability of the VMware Registry.
Two bundles can be relocated.
Image Bundle(s) == Package(s)
- Packages for TKG
- Packages includes certain Kubernetes cluster extensibilities like Antrea (CNI), Contour (Ingress), Harbor (Registry), cert-manager (cert issuer) and more
- TAP specific packages
- necessary for the installation of TAP/CNR
Two options exist to achieve our goal. The first option is to download the packages as tar
ball (--to-tar
) and to ultimately upload the file.
The second option is to directly copy the packages over from one registry to another (--to-repo
).
I dedicated a separate article on Sharing Container Images using the Docker CLI or Carvel’s imgpkg. You’ll find many helpful details in this post.
Relocating Tanzu Kubernetes Grid Packages
The TKG packages can be relocated using the tanzu
cli. Make sure you have at least 10G of disk space available before initiating the download process. Here’s a working example:
Download:
Make sure you’ve created a folder beforehand, otherwise you’ll float your dir
.
|
|
Upload:
The following command will upload the downloaded image-bundles (packages) to a referenced registry repository.
|
|
I skipped the relocation of the (standard) packages for TKG and kept the pre-configured online package repository.
Relocating Tanzu Application Platform Packages - Option #1
Let’s start relocating the packages for TAP.
- Export specific metadata as variables:
|
|
- Download the TAP packages:
|
|
If everything went well, the operation will end with the result succeeded
and the tar-ball has a size of roughly 10G.
|
|
- Upload the packages to your private registry instance:
|
|
Hopefully a similar result applies to this operation as well.
|
|
Ultimately, all image bundles are showing up in our registry (Figure II).
Relocating Tanzu Application Platform Packages - Option #2
Like initially introduced, the 2nd option is to directly copy
the images over. The first option helps in case you are running an internet-restricted environment (air-gapped) and the image-bundles have to be shared via organisation comliant ways.
|
|
The result is identical to option #1. With this, three check marks can be set on the prerequisites:
- Access to Tanzu Network ✅
- Network access to VMware registry ✅
- Relocation of the Tanzu Application Packages ✅
Next - Tanzu packages installation preperations.
Preperations for Tanzu Packages Installation
As aforementioned, I’m using VMware Tanzu Kubernetes Grid to instantiate Kubernetes clusters on vSphere and I’ve also mentioned that I’m going to use the Carvel tools to install certain Kubernetes cluster extensions (Ingress, etc.). The kapp-controller is a crucial component which needs to run in your k8s cluster. It runs by default on every deployed Tanzu Kubernetes Cluster (TKC).
|
|
As listed in the prerequisites section, install the Cluster Essentials on Kubernetes clusters which aren’t TKG, to have e.g. the kapp-controller available as well.
Furthermore, in order to easily distribute secrets across namespaces, the secretgen-controller is used and also installed on TKCs by default.
|
|
Adding the TAP Package Repository
Per default, the custom resource (CR) packagerepositories.packaging.carvel.dev
named tanzu-standard
within the tkg-system
namespace is configured with the url for the Standard Packages.
|
|
By using the command tanzu package available list -n tkg-system
, the kapp-controller will retrieve all available packages from the configured url. We want to have the same for the relocated TAP packages.
We start with the creation of a new namespace for the TAP packages.
|
|
This namespace will be used to store TAP packages related resources (configmaps
, secrets
, etc.) within the namespace.
|
|
If your kapp-controller is not configured to trust your private registry, the operations will quickly end with the shown error.
I’ve covered this topic in my blog post Deploy VMware Tanzu Packages from a private Container Registry.
In order to have the kapp-controller trust my registry, I have to present the registry certificate via a secret.
|
|
|
|
Delete the kapp-controller pod to pick up the additional configuration.
|
|
Due to the failed adding of the TAP packagerepository, the CR is still in Reconcile failed
state. Let’s validate if the updated kapp-controller configuration works by using the command tanzu package repository update
.
|
|
Looks better already. Checking the ultimate state:
|
|
Perfect! Now, lets check which packages are available using tanzu package available list -n tap-packages
.
Hint: Make sure to run a decent screen resolution 😉
That’s quite A LOT of packages but keep calm, not all are necessarily needed for TAP. Positively speaking, it is good to only have one repository to maintain, one source of truth for TAP.
Furthermore, if it is TAP related, like Cloud Native Runtimes, make sure to only use packages provided by the TAP packages repository.
Example: Here’s a direct comparison of the provided cert-manager versions for the two available package repositories tanzu-standard
and tap-1.6.3
.
Tanzu Standard - Cert-Manager Version | TAP Packages - Cert-Manager Version |
---|---|
1.11.1+vmware.1-tkg.1 | 2.3.1 |
You can notice that the available versions for cert-manager differs from each other.
Preperations:
- Adding the TAP Package Repository ✅
Installation of Tanzu Packages
This section describes the actual installation of Cloud Native Runtimes with having the above mentioned prerequisites and preperations in place. Packages which I’m going to install are:
- cert-manager.tanzu.vmware.com
- contour.tanzu.vmware.com
- cloud-native-runtimes.tanzu.vmware.com
- eventing.tanzu.vmware.com
Normally, the first three listed packages are installed when following the TAP installation routine. This is not my intention and therefore I have to install the packages one by one. Also, this will affect the values.yaml
file for the CNR installation itself, since we have to specify that we are using an existing Contour installation.
Two different ways can be used to operate packages. You can either use the tanzu
cli or the kubectl
cli. For the sake of showing how this looks like, I’m going to demonstrate it for the packages cert-manager and Contour.
Installing Cert-Manager
The certificate-controller cert-manager is the first component which will be installed.
- Using the
tanzu
cli:
|
|
- Using
kubectl
:
|
|
The installation can be validated checking the packageinstall
CR.
|
|
|
|
Installing Contour
Contour will be deployed the same way like cert-manager but since Contour provides a few more configurations for the installation, a dedicated values.yaml
file will be used. I created a new file named contour-data-values.yaml
and added the following content:
|
|
By default the service type
for Envoy is NodePort
but since I’m installing Contour to a vSphere cluster that uses NSX (same applies to the NSX Advanced Load Balancer) as a load balancer service provider, I adjusted this option to use LoadBalancer
instead.
The installation will be kicked-off by executing:
|
|
- The
kubectl
way:
|
|
Validating it at the end:
|
|
DNS Wildcard Subdomain
Knative allocates a wildcard subdomain for Knative Services. What is a Knative Service? I’m planning to create a dedicated blog post on Knative Serving in which this specific resource will be part of. For now, a Knative Service describes an application like a webserver or a function for example which got deployed using Knative.
In my environment, DNS services are provided using dnsmasq. All future workloads which will run on my Knative installation will use this subdomain. Using a wildcard subdomain like e.g. jarvis.cpod-nsxv8.az-stc.cloud-garage.net
requires an IP address which can be used for proper resolution. This IP address is provided by the high-performnce, robust and flexible proxy Envoy which comes with the Contour installation.
The IP address can be obtained via:
|
|
I’m gpoing to use the given IP address to create the needed entry in my /etc/dnsmasq.conf
file:
|
|
A restart of the dnsmasq.service
is required to take effect on the made changes (systemctl restart dnsmasq.service
).
Securing Workloads in CNR
Multiple options are provided to secure http
connections to your instantiated applications. Since cert-manager is already installed to add certificates and certificate issuers as resource types to Kubernetes clusters, we can use it to obtain, renew, and use our own certificates.
I created a new shared ingress issuer as an on-platform representation of my certificate authority. Therefore, all new workloads get their ingress certificates issued by the shared ingress issuer.
The first step is to create a secret type kubernetes.io/tls
. This secret contains “myCA” tls.crt
as well as tls.key
data.
|
|
This step is followed by the creation of the ClusterIssuer
itself. I simply named it my-company
.
|
|
This issuer has the earlier created tls
certificate my-company-ca
configured.
Another way to use your own TLS Certificates
It is also possible to bypass the ClusterIssuer
and use the Contour CR TLSCertificateDelegation
instead. This flexibility makes it possible to provide custom certificates and delegate these to your targetNamespaces
.
Here’s a working example:
|
|
Source: Use your existing TLS Certificate for Cloud Native Runtimes
Use wildcard certificates with Cloud Native Runtimes
And just another option which is available to explore is to set up a custom ingress issuer that issues wildcard certificates.
Look it up on VMware Docs: Use wildcard certificates with Cloud Native Runtimes.
Installing Cloud Native Runtimes 🚀
Having everything settled and in place, I can start achieving the ultimate goal, the installation of Knative Serving via VMware’s Cloud Native Runtimes. Similar to what I used for the Contour package, I also have to provide a values.yaml
file to apply certain configurations for the installation.
My configuration includes the following:
Key | Type | Description |
---|---|---|
domain_name |
“jarvis.cpod-nsxv8.az-stc.cloud-garage.net” | Wildcard domain name for Knative Services which I configured with the assigned load balancer IP address of the Envoy proxy. |
domain_template |
“{{.Name}}.{{.Domain}}” | This option gives you the flexibility to construct the DNS name for the Knative Service. |
ingress_issuer |
“cpod-jarvis” | Using this option sets the Auto-TLS feature to true . |
ingress (internal and external) |
“tanzu-system-ingress” | Configures Contour to route ingress traffic for external and internal services. |
Create the file and add the following configurations (adjusted properly) to it.
|
|
And off we go:
|
|
Oh, oh, no deployments or pods showing up…
Pod Security Admission Controller 👊
After a long breath of waiting for pods finally showing up on my cluster, I got troubled. The (old) Pods Security Policy admission controller hitted me a couple of times already. Therefore, I checked one of the created replicaSets
within the Knative-Serving
namespace and there I found it:
|
|
Since I’m running a Kubernetes v1.26 cluster in my environment…
|
|
…the Pods Security Policy admission controller isn’t used anymore. The new Pod Security admission controller was introduced in Kubernetes v1.25 and is the “successor” of the Pods Security Policy admission controller. Consequently, I configured the pod-security with privileged
for all my namespaces:
|
|
Source: Configure Pod Security for TKR 1.25 and Later
I had to wait a moment until the reconciliation
operation kicked in again for the new installed package. You can always check the status of the packageinstalls.packaging.carvel.dev
CR, short app
.
|
|
Update Cloud Native Runtimes configuration
There are many package configuration options exposed through data values that allows you to customize your Cloud Native Runtimes installation. The available values can be obtained executing:
|
|
Also, if you want to check which values were used for the initial installation of a package, you can get it from the corresponding secret
inside the namespace which were used for the package. Obvisouly, the values aren’t available in plain text. However, you can simply decode the base64
encoded data.
Here’s an example for the CNR package.
- First: Retrieve the encoded data
|
|
- Second: Decode the data
|
|
If you want to apply any additional configurations, add the values to your values.yaml
file and reapply it using the tanzu package installed update
command:
tanzu package installed update cloud-native-runtimes -p cnr.tanzu.vmware.com -v 2.3.1 --values-file values-issuer.yaml -n tap-packages
Verify Knative Serving Functionalities
Now having Knative Serving up and running, the fun can begin 😁. I’m using a simple web-server application for my validation. I created the Knative Service imperatively: kn service create containerdays23-v1 --image registry.cloud-garage.net/rguske/webapp:v1 -n myapp --port 80
Again, I will cover Serving in detail in my next post of this series. For now, I keep it at a basic level. The Knative Service deployment can be checked using kn service list -n myapp
|
|
This wasn’t expected 🤔.
There’s a resource in Knative named certificates.networking.internal.knative.dev
. I checked the state of it in my myapp
namespace.
|
|
And the status message
surprised me very much.
|
|
The issue occurs due the fact, that I kept the default configuration for Knative Service naming which is "{{.Name}}.{{.Namespace}}.{{.Domain}}
. Therefore, the created name containerdays23-v1.myapp.jarvis.cpod-nsxv8.az-stc.cloud-garage.net
is 4 characters too long 🤦
|
|
I looked it up and found that this is a known issue: When using auto-tls, Knative Service Fails with CertificateNotReady.
The solution for me was simply to shorten the domain_template
by applying the following configuration:
Key | Type |
---|---|
domain_template |
“{{.Name}}.{{.Domain}}” |
Therefore, it is now: containerdays23-v1.jarvis.cpod-nsxv8.az-stc.cloud-garage.net
Installing Knative Eventing ⭐
Last but absolutely not least is the installation of the Knative Eventing package. Knative Eventing depends on Knative Serving. For the installation itself are no additional values necessary. Therefore, it’s just straight forward.
|
|
Unfortunately, the Pod Security Admission Controllers hits the second time.
[…]
message: ‘pods “rabbitmq-broker-webhook-7557658cf6-9qxpw” is forbidden: violates PodSecurity “restricted:latest”: unrestricted capabilities (container “rabbitmq-broker-webhook” must set securityContext.capabilities.drop=[“ALL”]), seccompProfile (pod or container “rabbitmq-broker-webhook” must set securityContext.seccompProfile.type to “RuntimeDefault” or “Localhost”)’
[…]
This is due to the PSA “default baseline” in vSphere with Tanzu (TKGS). I had to apply the PSA pod-security.kubernetes.io/enforce=privileged
, like here, to the new created namespaces for Eventing during the installation of the package as well. You have to be “quick”.
|
|
I wonder if this behaviour survives user-feedback…
However, this is treated differently in Tanzu Kubernetes Grid (M).
Conclusion
Knative provides a more approachable abstraction on top of Kubernetes. I will dive deeper into its comprehensive feature set in the next blog posts of this series. Cloud Native Runtimes (CNR) is VMware’s official Knative offering which is part of the modular application development platform Tanzu Application Platform (TAP). The streamlined installation of Knative Serving and Eventing is done using Tanzu Packages for TAP. Tanzu Packages are applications which are not only packaged but also completely life-cycled in a modern way using the VMware maintained OSS project Carvel.
The next blog post will show a lot of the great features which are provided by Knative Serving. Buckle up for some cool demos.
Resources
- Knative project
- Demoing Knative Serving and Eventing using Demo-Magic-Scripts
- Serving
- Eventing
- Functions
- Knative Quickstart
- KinD
- Tanzu Cloud Native Runtimes
- Tanzu Application Platform
- Prerequisites for installing Tanzu Application Platform
- Resource requirements
- Cluster Essentials
- Packages
- Sharing Container Images using the Docker CLI or Carvel’s imgpkg
- Deploy VMware Tanzu Packages from a private Container Registry
- secretgen-controller
- shared ingress issuer
- Configure Pod Security for TKR 1.25 and Later