 Well, hello and welcome to another Dev Nation Live. I'm coming to you live from Amsterdam. Hopefully my internet connection will stand up enough to get through this session today because we have a very cool topic to talk about. We're gonna show you serverless on Kubernetes, specifically this open source project called Knative and we have one of our resident experts here from Red Hat. He actually goes by William Marquito as his nickname. So just some insider knowledge, he actually knows something about Brazil. So that's where that middle name comes from. Maybe he'll tell you more about it when he gets on the scene here. But at this point, I'd like to turn it over to him. He's got a lot of great content to focus on and I'm sure you're gonna enjoy what you see with this trigger technology. So William, it's up to you now. All right, thank you, Per. Yes, happy to talk about Knative and a little bit about our serverless plans in Red Hat. Yeah, as the presentation already on, can I start already? Let me share my screen here real quick. There you go. Put that full screen mode. Alrighty, so let's cover a little bit about the basics on Knative and I also have prepared a demo. Let's see if we can get it running on my machine. I mean, it's a lot of moving parts installed on Minishift on my laptop. If that doesn't work well, we have a recorded session as well as a backup, but let's see. So to start, I'd like to ask a question. So can you actually implement the serverless way without functions, right? And that might be a weird way to start up talk about serverless, but in fact, we are used to have that question, I would say, and back on the SOA days, we have the same question about service buzz and people would say, can you actually implement service-oriented architecture without service buzz? If you're doing IT, I'd say around 2004, 2009, you would have the same kind of similar question. And I'd say that even today, that still hasn't been completely solved because if you actually search service-oriented architecture on Google, you get the definition that it's actually an internet protocol, which is quite weird if you ask me, right? But going back to the actual topic here, which is serverless, right? The actual definition from CNCF, which I think is a very good one, covers some of the main topics here, right? I would say about serverless. So the idea of building and running applications that of course do not require server management that are executed and scaled and built, ideally on demand, right? That's the whole point. And there is something in the middle there where you see the bundled as one or more functions, right? But if we actually remove the bundled as one or more functions from the picture, does that change the concept of what serverless is? Like I really don't think so, right? Then let's dive more into that. If you actually look at the high-level traits, I would say for serverless, right? Again, beyond just talking about functions, right? You get those same traits regardless if it's a function or microservice or an application or any containerized application. So the idea of leveraging no server, no management of servers, implicitly high availability and consumption-based pricing, auto-scale, auto-provisionment, if you can leverage all that in any class of application, right? So why limit that to only functions, right? And that's exactly where I would say Knative comes and help and provide a lot of that infrastructure. So what exactly is Knative? So you can think about Knative as a set of extensions to Kubernetes and those extensions, they provide building blocks to build a serverless platform, but again, not specifically tied to functions or not. Again, any container-based application can be used here. The three extensions, the three modules that are part of Knative are build, serving, and eventing where build is more about the actual building your source code into an artifact. That could be a jar, that could be a zip file or a container, of course, that to run in Kubernetes, we're talking about containers here, but that's the idea of like coming from source and going to something that is executable, right? And then you have serving. So now that I have that container, that application build, I gotta serve that application some way, right? And serving takes care of that, but not only that, it also offers a way to serve that application reacting to events, right? And it also offers the capability of scaling according to the number of events it received and also scaling down to zero, right? Which then saves some resources when that application is not being executed. Last but not least, we have eventing, which is that the third module here, the third component I'd say from Knative that offers infrastructure for eventing. So that's how you define event sources, channels, and how those events are actually going to trigger your application in serving. And I'll dive a little bit more into that in the next slide. So diving a little bit into build. So the idea of build is then to provide a step, so a list of containers that are run in a certain order and those steps become your build steps. Just this week, this component is being out, I mean, I'd say redesigned or discussed to be called pipelines or build pipelines because in the end of the day, all those steps of build, they kind of create a pipeline itself, right? There is this idea of a build template as well. You can use, you can install different build templates on the platform and by using those build templates, you have then effectively a reusable template to build an application. So if that's a Java application, you wanna build using build. Or if that it's maybe a build pack, you can think, you can install those different templates. And on the right side here, you have an example of that CRD of that YAML file that describes the build, right? But if you're already an OpenShift user, I mean, this idea is probably not new to you. You already had OpenShift build and source to image, but this is now applying or reusing some of those concepts to, I'd say, any Kubernetes installation. Serving is then about serving that container that you just built. So you have the idea of a service that it actually includes routes, configuration and revisions. The configurations are then it's a pointer to the head of the latest revision of that application. A revision is then a snapshot, a pointing time of that particular application of that code, if you may. And then you have routes, which is then how traffic is going to be sent to that revision, right? That said, you might notice some similarity here to what you probably have seen already in some issue talks because behind the scenes, Knetive serving is today leveraging issue to do traffic split and to deal with all the different revisions and route the percentage of the traffic to those revisions as well. Last but not least, we have eventing. Eventing is, as I said, again, this idea to provide a generic eventing framework. It's already using Cloud Events, the CNC app spec, as far as the format for the events or the messages. And a bunch of the people actually doing Cloud Events is also participating on the eventing work. The API at a high level, I can define some of this construct. So the idea for receive adapter, channel subscription and those I would say are the three big ones. Receive adapter, you can think of it as a way for your event source to map that particular event to something that is going to be then sent to Knetive channel. And then you have the channel itself, which is a named endpoint and all these concepts, all these APIs, I would say they are high level constructs. The implementation behind the scenes, for example, for a channel, it could be provided by Kafka or an AMQP server or what have you, right? And then you have the subscription, of course, which then registers to a channel to receive those events. If we look at the eventing model in this diagram that's coming from the Knetive docs, you get a better sense for the whole workflow, right? For example, for a GitHub event, you implement a receive adapter that runs on a single pod, that receive adapter then sends to a channel, that channel is backed by a Kafka topic. That Kafka topic then has a couple of subscribers, in this case, two subscribers. And then from there, you actually deliver that event to your service, which is effective within your application, right? That's a high level, I'd say, description of the whole workflow of eventing. But so when we look at the Knetive constructs and the high level, I'd say the traits you see here, so configuration, revision, route, service, build, all of those you can map to, I'd say, one factor, right, from the 12-factor app. So those, I would say, are common traits for most modern cloud-native applications today. So the idea to keep code and configuration separate, the idea to trigger a new revision for every single change you make in your source code, how you're going to handle concurrency, disposability, again, that's something that is, I'd say, natural for a serverless platform. And then the idea of separating the build steps from the running steps, from releasing, all of that, I would say, you already get out of the box from this high level constructs in Knetive. And looking a little bit now into what Knetive and Red Hat is, I'd say, I mean, what Red Hat has been doing with Knetive, overall, I'd say that would be the architecture we see. I mean, of course, you have RHEL, you have Kubernetes, and you have OpenShift, but then you have Knetive there providing this infrastructure for events and build and serving applications, right, where you'd have this thin layer called function as a service on top of it, if you want to build a fast. And effectively, what comes, what goes into that function as a service layer is just the invoker, the runtime, and maybe a CLI, but you already get that out of OpenShift with OC or ODO, OpenShift do, right? And then you have the API also. So this is, I would say, how we are working with Knetive to enable some of that in OpenShift, but we also, I would say, envision a future where different cloud providers that want to support their function engine on top of Kubernetes, that they could also embrace Knetive or make it Knetive compliant, if you may, or whatever that means. But if you get to that stage, I would say, then you effectively have a way to implement function as a service that is interoperable, right? Because given the nature of Kubernetes and OpenShift, you can run that on-premise or on any cloud. We are also working on our own fast, which is OpenShift Cloud Functions, but you can see how that becomes then a more easy way to avoid, I'd say, locking, right? So you are not, if you're using, if you like the Azure Functions model, let's say, or the IBM Cloud Functions model, you can still do that on-prem or even on a different cloud provider if you want to. So looking at the whole workflow here, and soon enough, I'll get to the demo, you can see here that, I mean, it all starts with the functions or an application. So someone builds an application, for example, and send that to KnativeBuild. That is going to then provision or send that container to serving. And then going with the workflow, let's say application A here, send a new event, a new entry or upload a new file to a service. And I'm just using some Red Hat products here, but again, you can think of that or any other event source, any ISV event source, what have you, right? Those services, those event sources then, receive that event, send that to a receive adapter, and then you have in Knative events, the channel that is going to receive that, send to the function or to the application as a cloud event, and then you have Knative and events handling, Knative serving and Knative events handling those moving parts, I'd say behind the scenes, right? So for you developer, again, you were concerned, just I would say with the yellow parts, everything else become part of the infrastructure. So let's dive into the demo, which hopefully makes things a little bit more concrete. Let me move away from the full screen. Let's make sure things are up and running here, up and shift console. So I'm running everything locally, right, on my machine. And as I said, because I'm sharing my screen here, and I do have a lot of things deployed on my mini shift cluster, my CPU, as you can see, it's a bit overwhelmed, but this is a mini shift environment with Istio, Knative build, Knative eventing and Knative serving already installed. And I'm going to now execute some commands, to demonstrate how to create a service. Effectively, I'm going to show you how to create a blue-green deployment using Knative, right? I have a set of instructions here. Those will be available on a GitHub repo as well, but just to get started, right? I mean, I'm skipping the installation steps, and I can cover that later if we have time. But at this point, we have, this is the definition of a service in Knative. So you have the definition here of what the service looks like. I'm asking Knative to run the latest configuration for that service. You have the definition of the revision, and I can't double click here. Let's go back. There you go. You have the definition of the revision template and the actual spec for that container to run. So this would be a straightforward configuration for a revision and a route as part of a service in Knative. But I think it would be more interesting to actually show that into separate steps. So let's start with creating just the configuration, right? So at this point, I have the configuration for that same container, and I'm specifying here the container concurrency as well. So how many instances of that container I want to run? So let's add into this real quick. I'm in the wrong directory. There's this terminal here. It's already in the right place. Okay, so here I have... Oh, I just learned about that, which is much better. So this is the revision as I showed you before. I'll leave it there so you can digest a little bit of the content. There you go. Now I'm going to apply that revision to the cluster. And here I have, not again, I just lost my watch. So let me watch, there you go. All namespaces, watch, now there you go. So it looks like my mini-shift is not behaving properly. Bummer. So okay, let me transition to the video then, which it's exactly the same steps I'll be doing here, increase the video. Apologize for that, probably need a bigger box. I recorded this last night, thinking about concern about this exact same problem. Hope the phone size is good. So same deal here, I'm just playing the video. So showing that Istio is installed, Knitiv is installed, Knit build, serving and eventing. Increase a little bit the speed and I'll pause if needed. So here I'm showing that in my namespace, I don't have any application being created at this point other than the templates and the infrastructure from Knitiv itself. And on that side now, I'm going to show the YAML. I just described the configuration for the first revision. Great, at this time now I'm going to apply that configuration here on the top, you should see the container being initialized and this is a very interesting thing. You can see that there are like the three slash three there showing that in a single pod I actually have three containers being created. When I switch back to the presentation, I'm going to specifically cover what those containers are. And here I have also executed a current command to call that service, but you see that it failed, right? Because I have just created the configuration but I'm still missing the route. So if we look at the OpenShift console, you can see the deployment going on for that container, for that application. And as part of that, you see the user container and the QO proxy that got created. And the third container was still being established with this, which is the Istio, right? So again, curve is not working, great. Let's create the route. The route here, again, using the same principles from Istio, you get the percentage there. So 100% of the traffic is going to that revision. Let's see, apply. Now the route is created, great. The current command worked. But guess what? I had a problem in my application, right? So it would still be not exactly running the revision, the version I was expecting, right? You see here the three containers that are part of the service being created, the Istio proxy and the Q proxy. There you go. So now I need to fix my application because it was missing one of the parameters, right? To make it run successfully and print hello world in a message. So I'm adding that here to another revision of that same app. I'm gonna create the second revision. And you can see that it's going to trigger here the 002 and you see the pod be initialized and all that. But by the same token, right, I have not yet defined the route that point to the revision number two. So now I have to update the route or create another route to the revision number two as well. And then in this case here, I'm just sending, I'm sending 100% of the traffic to that new revision. So now that that got created, I can curl and voila. Now I get the sample, the result I was expecting pointing to V2. Now I have created also another route object that actually maps 50% of the traffic to each version. So again, if I was actually doing a blue green deployment here, I could say for V2, I just want let's say 10% of the traffic to go. And I don't know, do a dark deployment. I think it's also one of the patterns that could be used here to implement. In this case, just for the sake of demonstrations, I'm implementing, I'm doing 50%, right? So you can see how every call for the service actually calls a different revision, a different version of that service. Can we speed up a little bit in the interest of time? So this is another interesting part. You can see Kiali here. It's already installed in my cluster. That comes as part of the Istio operator that I installed. And you have the two revisions of the Hello World service being displayed, right? Let me just go back to my project namespace. And you have here, so this is 001 and this is 002. The unknown here, I mean, this is a work in progress as you might know, again, the Knative is really new and the integration with Kiali has been worked. But I'd like to show you here just to kind of make a point I mean about the, how this application, how this can be used combined with Istio, right? And with Kiali as a visualization to understand the traffic of that application. So now I'm going to put some load into the cluster. I'm going to fire two threads and 32 connections against the Hello World service. And if we check on Kiali, you can also see a little bit of the inbound metrics and I mean the number of connections it's being handled by a given instance, a given version of the service. You also have Yeager out of the box, I would say provided also by our Istio operator. And with that, you can also do tracing for your service. And remember that I have just created, I have just defined those resources for Knative. So the configuration and the route, I have not created anything specific for Istio or for tracing. Those are just being provided by the platform for you. So you can see how long it's taking each step of that particular service, right? I mean the whole workflow. But now I'm going to transition a little bit into the build part. So I'm going to delete all the services. I have been, have created so far and I'm going to demonstrate how one can actually create a build and build your application, let's say inside OpenShift, inside the cluster, right? Using Knative build. So I have already installed a build template. I can go back real quick here so you can see that. So this is a build.template for Java that it's already installed in the cluster. And I'm going to follow the nice tutorial that Kamash put together here. Here you have some of the steps to create that. So the first thing I'm doing here is creating a persistent volume for Maven. This is a very interesting step because it can save a lot of resources, right? The fact that we are sharing a Maven repository, I'd say a Maven location for all your dependencies in this storage that is provisioned for you inside the cluster, right? And then you have the actual installation of the template itself. But to build the application, right? You just have to run the service YAML. That's the only YAML you actually have to apply. And that's exactly what I'm going to do next here. So just going to the right folder, there you go, speed up a little bit, right? Looking at this YAML, and I can show the YAML here. It's probably interesting to dive into that a little bit. You have the definition of a service, the name of the app, the same service definition we have seen before where you have run latest, run the latest configuration. But as part of that now, I have a build template as well. So that's defining also some of the steps that are going to be executed as part of this build, right? And I'm going to trigger the build here. Okay, I'm just doing the same thing here. Ba, ba, ba. Great, apply. Nice. So now the build has been started, right? Looking at the OpenShift console, you can't actually see the pod because it's just the build still going on at this time. But if you look at monitoring, you can see that the build has been initialized and you also see the steps. So all the individual containers that were started as part of that build. So again, all the steps, so grabbing the source code from Git, performing the actual build, doing the Git push into the internal container registry inside OpenShift. All that was already defined during the build, at the build CRD, I would say at the build YAML file that I've created for my service. This is the push that is still running. It's waiting to do the actual provisioning which is the last step. Speed up a little bit here. So now that the build was completed, right? You can see that the deployment of my application already started. Again, I just did the OC apply service Java.yaml. Behind the scenes that build was triggered and the provisioning of the application was also started. Now I can call that service. And in this case here, because I deployed the service, I got the configuration and the route already created for me. I'm going to execute the call and there you go. That's the hello world build for, the build for Java, right? Now I'm going to just repeat that same step, updating the code in Java app and then perform another build. So you can see how just by detecting that change, behind the scenes you get the same experience, right? I'm updating the value for the container name to from one to two, doing the same here to point the revision to the right version of the container and I'll keep the build using the same command. So the workflow becomes, I'd say, a little bit more easy, right? Again, another build was triggered and from there another version of that greater service is going to be provisioned. And I mean, that's pretty much, I'd say the idea of the demo. So showing you how the build happening on the server is being handled by Knative builds. I'm going to go back to the slides because I know we're kind of almost on time already, but I'll have a quick recap about the demo here. So real quick, the installation itself, so we have been working to provide mini shift add-ons. So it's very easy to install on your laptop. If you want to install just build, just serving or events, I would recommend having, I would say, probably a beefy machine. I mean, 16 gigs is, I'd say, the bare minimum today. But we're also working to build Knative operators and make that installation through the UI for OKD as well. That also work, I mean, you have the documentation links here, you can follow along and see which way you prefer to install. Mini shift add-ons or operators. The demo I did for blue-green deployments, again, the step, the high-level steps, you create a revision for an application, you create a route, you test and repeat. Very, I'd say, straightforward once you get the gist of it. I know that the first time, and because I was running through the video here, maybe it was too fast. Inside the pod, you get the three containers being created. So the Istio proxy that is going to handle all the inbound, outbound traffic to your cluster. The Kio proxy, that is something that Knative adds to control concurrency and the actual user container, right? That is where your code is going to be executed. And for the build part, that's pretty much it. So you can think about a workflow here where the ops team installed those build templates. I'm using build.ah here for that and maybe create the Maven persistent volume. So that's going to be shared. A developer just writes code and the platform takes care of executing that build, caching the dependencies and then provision your app. So in conclusion, so far, I have not created a single function, right? And if you're going to ask, can you implement serverless without functions, I would say yes for sure. And you should think about how you can leverage those serverless traits in any class of applications, I would say today. Here's just a little cheat sheet. If you are starting getting started with Knative, you want to see and list some of those resources in your mini shift, in your cluster, in your Kubernetes. And I just joke about here, like if we had to see a live for this, I mean, that's something that it's, I would say, in progress and being discussed upstream as well. To learn more about that, we will be at KubeCon. And at KubeCon, we will have a demo session live on a more powerful machine in my laptop. So you can see that live as well. And on that demo, we're going to go over eventing as well. So come see us there. And to learn more as well, I have a bunch of links here from blog posts that our team already produced to our actual progress on the add-ons, on the operators, in all the Knative community as well. Thank you very much. Let's go for Q&A if we still have time. I know it went a little bit over, I guess. Right. So there are a couple of questions I just want to throw at you and see if you can have a quick answer, right? One is if I have autoscale turned off, do I need to worry about any nodes or resources, resources associated with this Knative thing? Have you guys thought about it on the team? Sorry, Bor, your audio was breaking up a little bit. I almost got the question. I got the part of the auto-scaler being disabled, but then what else? No, so Kubernetes has an autoscaler. How does this integrate with that? Oh, right. Oh, great. Yeah, that's a very common question. I mean, the idea here of the Knative scaling bit is that it's scaling based on demand, on events. The Kubernetes or auto-scaler is based on resource consumption, right? So it's going to scale down, it's going to scale using memory or CPU, but it's quite tricky to do something like, let's say, scale to zero, right? Because you can't really go to zero for CPU or memory. With Knative, the scale is based on demand. So I have a new event, I'm going to start one container. If I have 10 events, I'm going to start 10 containers. If I have zero events for a minute or for 30 seconds, I'm going to scale down to zero, right? You can't do that with the Kubernetes auto-scaler. So that's kind of how you differentiate those. Okay, no, good answer. And we have, let's just try to get one more question in. Peter asked this question really early in the session. What about RBAC, and RBAC is built into Kubernetes? And what's the relationship to operators and the CRD? Oh, that's a very good question. I mean, because we are running Knative inside Kubernetes as native resources, I mean, the RBAC story becomes, I'd say, natural, right? It's not applied today, but I mean, you can integrate because it's controlled as an object in Kubernetes, you can definitely apply, leverage the same RBAC system from Kubernetes to those objects as well. I mean, in fact, looking at that, for example, example, when I was creating the service, the configuration and the route, you can envision a model where a developer, for example, has permission to create as many configurations of that application as he wants. So as many, he's just writing code and pushing those versions to the cluster. But then another person with a different permission, with a different role can come into play and just push the route, tweaking how much load, how much traffic is going to be sent to that particular version of the code, right? So you can play with that and that's definitely something we want to explore. Okay, well, there'll be more questions. And actually, we do want to schedule a deeper dive. Well, not more questions today, but we'll do a deeper dive in the future. We're certainly out of time for today. I want to thank everyone for coming and participating in our session. Markito, awesome job, even though you had a fun video with demo kind of thing and actually people on the chat. So thank you for that. All right, but we need to get this point. No problem. Thank you all.