 All right, we'll give everybody about 60 seconds to join. Welcome back. Hope everyone is enjoying the session so far. Just give it another 30 seconds to make sure everyone is joined. We're gonna go ahead and get started. Thank you so much for joining us. We've got a great presentation coming up here. Steve and John are both gonna present on unleashing the power of serverless computing. I'm gonna turn it over to you guys. Welcome and thank you all for joining our session. This is a great topic to talk about today because while serverless computing is not a brand new technology, there's still a lot of customers who are still evaluating and terminating when and how to get started with this. So our presentation's not about trying to convince everyone that they need to move all their workloads over to serverless technologies, but really it's just to give or empower developers and architects with the background they need so they can keep serverless computing as another tool in their toolbox because at the end of the day, it's all about using the right tool for the job. So we've got some slides. We'll go over the pros and cons, share lessons learned from the field, and then at the end of the second half, we'll have a demo to see it all in action. So who are we? So my name is Steve Tran and I'm a principal consultant. I've been at Red Hat for almost 11 years now. And like most people here, I'm a developer. I love writing code. I love finding ways to improve my own developer joy every day. And one of my principles is keeping things simple and writing clean code. Love it, ditto, I'm just kidding. My name's John Keem, I'm a solutions architect, which really is about taking our mapping business problems and problems organizations have with hopefully open source technology, that intersection between that problem domain and technology is so fascinating. And like Steve, I've been coding for many, many years and I love it. So we're gonna talk about serverless and why we love it today. Yes, so John, let's put it in context for viewers. What does serverless mean? What do we mean by that? Yes, I like that. We'll find the terms. What is serverless? So let's start with what it's not. Not a system with no servers, right? There are servers somewhere. I like to use the wireless analogy, wireless internet. So while it's wireless for you, the end user connecting and using the internet, there are wires somewhere in the system. It's just me as the end user, don't have to worry about it. So same thing with serverless. You as the end user, you as the developer don't need to worry about the server. Next, thinking that it's the best architecture for all future apps. That's not true at all. There's a perfect use case for it and there's also use case where you wouldn't wanna use it. And the same idea going back and rewriting all of your old apps. No, they're still providing value and there's a certain class of applications where serverless makes a lot of sense and there's another type where it doesn't. We're gonna go through that today. But what is it? So it is a system where the server concerns are moved to the infrastructure, aka away from the developer. And like I said, so this couple of times you can underlying theme throughout the talk for certain use cases, it works really well. Next slide. Oh, we got a bit of a lag here. There we go, all right, cool. The internet was thinking. All right, so if we take a step back, we can see how we arrived at the concept of serverless. All right, we have monoliths that we eventually broke up into loosely couple services and those services then continue to be broken up and then even defined to encapsulate or encompass a singular business domain. And then we looked even further to break those up into maybe even individual functions that we can then deploy. So we take a step back, we can see a pattern emerging. Each architectural decision came with its own set of pros and cons, and see if you can spot the trend here. We're aiming to deliver faster results by reducing code complexity and by breaking up our delivery units into smaller, more scalable units that are easier to fix, easier to build and easier to scale. Serverless is still evolving. Let's take a step back again and look at the history, the context of all of this. So breaking up into three kind of distinct milestones. The first version 1.0, starting with back in the day, AWS Lambda's, the big behemoth on the stage, released in 2014. Now, they weren't the first version of Serverless, but they were definitely one of the most popular. They offered the ability to just ship code and they would automatically scale for you. Very, very compelling for developers. Despite its many limitations, like execution time caps, tight coupling with AWS infrastructure, and a poor local development experience. Despite all that, people still came and drove and still embraced and used it. Then moving forward, things got a lot better. Version 1.5, AWS Lambda's weren't the only functions as a service in town, but a lot of other providers and vendors were building on top of Kubernetes. So they were thinking about how to offer this capability and Google saw the similarities and said, how do we actually bring all this together so we can have a common, cohesive set of ways and approaches that we can think about Serverless on Kubernetes? So Google started this by creating these common set of components and objects to do this, thus releasing the Knative project. So realizing this opportunity, Red Hat would join Knative as a founding member, but what was really amazing is the community that grew up around it, because Knative was much more than just the implementation of Serverless on Kubernetes, it really was an open standard. And this standard breaks away from the vendor locking, like vendor specific or the cloud specific implementation of it, which is really what makes Knative really compelling. And it works by essentially spinning up new containers on demand. So because of this, this not only enables functions, but also enables microservices and basically anything that can be containerized and spun up quickly. Now this brings us to the last section here. Knative came out in 2018 and we're still continuing to push the boundaries of Knatives and Serverless. With customers and with people that are using it, we're seeing really sophisticated enterprise architectures that are truly resilient and elastic on demand. In the 2.0 phase, Serverless essentially becomes another feature, another way of deploying developing applications. Since in practice, most enterprises will be running a combination of Serverless and non-Serverless workloads. So you see in microservices, monoliths, functions, all running as containers and some not, all giving organizations the ability to solve their business problems, to essentially choose the right tool for the job. Okay, so history lesson over. Now that we've gone over Serverless and that history, Steve, what are the benefits? Yeah, so I just want to highlight a couple of the key benefits and it's going to change depending on what persona you are. So for developers, it's about faster time to market and how you may ask. Serverless gives the developers the flexibility and agility to use the best tool for the job, just really focusing on writing core business code to develop those new features and fix those bugs. For the operational teams, it's about operational efficiency. They can offload a lot of the concerns to the platform itself, such as scaling, fault tolerance, capacity management, security patching and more. These infrastructure teams are freed up from sort of this unnecessary overhead so they can focus on high priority initiatives. And then finally for the business, it's all about cost savings, about saving money. We can lower the cost because it's a pay for what you use model. There's no need to pay for servers to be sitting idle. We can really maximize our resources by minimizing our compute waste. So you can get a lot more compute done with a lot less resources. There are some drawbacks to it though. It is a little bit harder to replicate the entire serverless stack or machinery locally for local testing. Yes, you can mock and stub out third party dependencies like databases or event streams or other types of systems, but it's not easy to simulate the same sort of triggers that kick off your serverless functions as your production environment. There are also operational complexities that you have to think about as well. Somebody is gonna have to set up the Knet of components, monitor their usage and troubleshoot things when things eventually go wrong. Although it's easy to install serverless on OpenShift or Kubernetes with operators, you'll need somebody who understands good DevOps practices to be able to maintain troubleshoot. And then lastly, not every application is even suitable to be run as serverless functions. There's a term called cold star latency. Whenever the application starts up for the very first time and keep in mind that these are sort of on demand, so there's nothing there right now, but when you get that first request, your container needs to spin up from nothing and that cold boot before when you're writing Spring Boot types of apps, five to 10 seconds used to be fine, but now it's not fast enough. The very first invocation that you hit or that you fire off, that very first user is gonna suffer through a little bit of that lag. So John, with that said, can you tell us what are some good serverless candidates? Yes, let's take a look at some of the few characteristics that all good serverless applications have. So the first, starting with the upper left there, stateless, independently and easily scale up and down, which is much more easily done if you don't have to maintain state. Next, specific. Single purpose, loosely coupled, meaning we can independently scale specific functionality as required by that dynamic and real time requirements of the system. Next, short and sweet. Simple, in terms of complexity, both in the code complexity and by the complexity of the idea for the developer and the way that they express and the way that they can understand the constructs and the abstractions that are being used in the code base. Next, execution limits. Closely related to short and sweet, the application should ideally run briefly and then go away, freeing up those resources for other purposes. So Steve, in your experience, what have you seen out in the wild? Yes, so I recently helped architect the system at an airline where they do sort of special processing for people called unaccompanied minors, which essentially our kids, they're traveling alone without their parents. They're given special wristbands and every time they move from say one area to another or exchange custody from a gate agent to a flight attendant and so on, their wristbands get scanned so that their locations can be tracked in real time by their parents or the guardians. This is a really good candidate for the reasons you mentioned above on this slide. And above all, it's a bursty sort of traffic pattern. This is not something that happens regularly. Maybe during the holidays, when there's more travel, this is when you would have more unaccompanied minors. So in a traditional non-serviless model, if you build out these systems, the processes, they would sit idle for maybe most of the year, but because we designed this with serviless in mind, it saved them a lot of resources because like you mentioned, we auto expand up and down whenever there's spikes and it's really about cost savings. Awesome. So conversely, let's see what characteristics where a serviless approach would not be ideal. So you're gonna see a lot of opposites here. You talked about stateless, well now, stateful. If you're having something like a server side session where you must maintain server side, then you're probably gonna have to use things like sticky sessions, which again then becomes counter to the serviless approach of applications quickly coming and going. The next class is the orchestrator where an application is maybe tightly coupled to many other services. Either they call this serviless application or your serviless application calls other services. So this nature of this tight coupling means that these components of the system end up needing to be scaled together and then this becomes counter to the serviless paradigm. Now the other two I'm gonna take together, the long running and constant invocation. So long running applications or applications that are invoked often would not be able to fully take advantage of that serviless nature of rapidly scaling up and down. Because these types of applications actually start to look like non-serviless applications, which might actually be a better approach for them. So this really underscores the point that the serviless architecture isn't for every type of application. It's simply another tool in the toolbox. Some use cases it fits really well and for the use cases like shown above, they do not. So Steve I asked you before about real world. Again, give me some real world examples of some bad serviless candidates. Yeah, the big serviless story this year was actually from Amazon Prime Video. They published some articles talking about how they were actually going back to monoliths over serviless because they got better performance. In one of the interviews, they said that it wasn't actually serviless that was the issue. It's because they were relying heavily on these things called step functions, which is an Amazon technology that lets you orchestrate multiple serviless functions together in a chain. This is a problem because each of these video functions was essentially sharing state by reading and writing to S3 buckets. It was doing a lot of network IO, serializing, deserializing data and so on. It was just very highly inefficient. Processing videos is also long running and constantly being invoked. So this was just not the right profile of an application to be serviless. So we wanna share some lessons learned from actually implementing this with customers and at a high level, these are the most common issues in each of these squares here. It could be its own 30 minute talk, but we'll just highlight a couple of the big ones for now. I would say the biggest lesson learned that everyone should take away here today is we need to handle errors properly. Our first thought might be to approach it the same way as you would with non-serviless functions, but you have to be a little bit more cautious. Yes, you do wanna build your serviless apps to be defensive and fault tolerant to nature, but you need to also consider the trade-offs of latency. If you add techniques like circuit breakers and retries and timeouts, these are all great tools for building resilient services, but you could potentially be adding additional latency or waiting for things to time out and so on. Serviless functions should be fast and should return right away. So it may not be a good idea to add all those things in. The other big block here is structured logging is key and it's critical because these serviless functions are not long live. They spin up really quickly, they should spin up really quickly and they live for a few minutes, but after they sit idle for too long, they spin down. So using structured logging, using an aggregator, a log aggregator, just so that you can collect that historical information so that you can troubleshoot and debug because you may not have access to those containers once an error happens. You also want to make sure that you're logging enough information so that you can troubleshoot after the fact, but you also don't wanna log too much because too much logging can also slow down your serviless function. Testing, like we said before, replicating the serviless infrastructure or machinery locally isn't the easiest to do. And yes, you can walk and stub out certain pieces, but a lot of the issues that I actually see is what the configurations of serviless instead of the application. So when you're writing tests or writing your code actually, make sure you're writing it in a testful manner. You can still use unit tests. You can still use it to check your programming logic and that will help pinpoint the root causes and it'll also help eliminate the code being the culprit of the issues. And then the last point, the k-native configurations. You have to understand how the defaults work and for the majority, they're generic enough to be able to support lots of different serviless functions and capabilities. But they can be tuned to be application specific too. You can change things like how long a serviless function will wait for it times out, how quickly or rapidly they scale up and down, the maximum number of replicas to scale to in the minimums and so on. We highly recommend that you have solid benchmarks of your apps before you start changing the default values. Because the further away you deviate from the defaults, the harder it is gonna be to understand why your application is behaving a certain way. Yeah, and we also wanted to add in this diagram here, the dark red pieces mean they tend to be the more troublesome pieces. So focus on them, shift left on them, do them first because the payoffs are gonna be huge. You're gonna save yourself a lot of headache and time later. Okay, now the time for the demo. Steve, what do you have for us today? All right, so I'm gonna shift my screen share real quick. And what we're gonna do is we're gonna build a serverless app sort of from scratch here. And the very first thing that we're gonna do or I'm gonna show you guys is how to get started. We're gonna take code from, we're gonna scaffold our code out from corpus.io. You can go up here to the start coding button. And for those who are spring boot developers and I've seen the spring initializer, this is sort of the same idea. This is where you'd set your coordinates for your Maven application, your job application. So I could call this dev nation. We're gonna build a simple rest service. So I can select rest easy as my rest implementation. And because we're gonna deploy to OpenShift, there's a really good plugin called the OpenShift plugin. Selecting that, it will give us the ability to eliminate some of the manual commands of like setting up your deployment configs, deploying it to the cluster and so on. So you would just generate this application, you would get a zip file, you would unzip this file and get started. I've already downloaded it. So I've got it opened up in my VS code, which I'll bring up here. And when you unzip this file, you'll have some starter methods here. You get presented with a greeter resources, which is like your very first endpoint. You get an empty or you get a properties file where you can configure stuff here. And then it comes to a simple test as well. Before we get started with the code, there's another caveat that we need to address. We need to have a cluster before we get started. So like I mentioned, I'm going to deploy this to OpenShift. So I've got an OpenShift cluster here. This is a 4.14 cluster, which is like the latest minor version. And the second caveat is we need to have the serverless component already installed, which I did using the operator, which I installed through the operator hub. So if I look for serverless, you'll see that OpenShift serverless is here. It's already installed, I installed this earlier. So we'll create a project, we'll call this DevNation. And then I'm going to jump back to the code now. So I could write the code from scratch, but the demo goblins would probably get me. So what I'm going to do is just copy and paste the code snippet that I prepared. I'll get into the details of what's going on. And the second, I just want to get the build kicked off as soon as possible, import my packages here. That's all good. And then the second piece, I mentioned that I'm using the OpenShift plugin. These are the values that I'll need for deploying to OpenShift. It's already in here. I already set it to DevNation, which is my namespace. And before I dig in, I want to kick this off. I'll kick off a build. And I'm using Maven. So I would just do Maven package. I want to specify that I'm using a different profile. I'm going to use the native profile. And then just for the sake of the demo, I'm going to skip my tests. All right. So while this is building in the background, I'll just minimize it. Let's look at the code. This is just a very simple rest service. There is nothing here that is particularly serverless or corkis in general. Like everything that we've imported is coming from the Java slash Jakarta packages. So these are just core APIs that we're calling. And then I just created two endpoints. This is what I call variable sleep, which is just to introduce artificial delay. And then another thing, just to print out headers, which is just for testing. The other thing is the applications.properties. So I had already configured this to deploy to a particular namespace, which is what we just created, the definition namespace. I changed the type from, I believe the default was deployment. I changed it to Knative because I'm deploying a Knative component. And then I set the plot to true because once I'm done building, I want to deploy automatically. And the point here is you don't need to memorize this. This is all documented and I'll just bring up the docs real quick while we're waiting for the build. This is the OpenShift plugin. If you have any questions about what parameters to set, these are all the different values or the parameters and what values you can set for them. All right, so let's go and check on our build. Still building. So I had specified that I wanted to build natively. And what that means is it's building a executable binary using corkis, ahead of time, compilation, which is actually scanning through my code base. It's looking for dead branches. It's looking for unused code. It's looking for things that doesn't need to run. And the reason why building natively takes so long and why it's so fast at runtime is because it's getting rid of all the stuff it doesn't need. It's gonna build the slimmest possible executable so that you can boot up really quickly. And it's gonna be very lightweight because it's only including the bare minimum it needs to do, whatever work it needs to do. Yeah, it's worth mentioning that corkis can run in two modes. So you would typically think about this for production type deployment settings or maybe tests or something like that where you would spend the time to build this faster, slimmer executable. But when you're developing yourself on your laptop, you probably don't wanna wait for this. So you would probably run in the other mode that actually has in dev mode live reload. So when you change the Java code, boom, you can see the changes almost instantaneously in the browser, which is really nice in terms of developer productivity. But you can also run it if you wanted to, not only in the executable, the binary that's produced here in native mode, but also with the JDK, the JVM running underneath as well in open JDK mode, which is very likened to your traditional way of running Java. So it's worth mentioning that you could do either option. All right, so it took three minutes, 45 seconds to build. You know, like John said, it's a little slow, but you probably wouldn't do this every single time if you're actively developing. You know, you probably only do this when you're ready to push a release. So what happened? You know, I built my image, I'm sorry, I built my native executable, an image got created. So let's go and look at it. Let's go to my dev nation namespace. Let's go check out the images. You know, here's my build that just kicked off a minute ago, or three minutes ago actually, it created an image stream for me. If I go to my serverless tab right here, because I set to automatically deploy, it created a serverless route for me here. And if I were to click on this, you see how it kind of hung for a little bit. If I were to look at the logs, or if I look at the pods, this application started in 0, or 0.016 seconds, but it took a little bit of time to spin up this piece of it as well. If I were to hit it again, it came back pretty much instantly. And if I do the hello endpoint, you know, we've got that. If I do hello headers, here's my debugging endpoint that I added in. So I also have a test script that I wanna show you guys. This is just creating a little bit of a load just for testing. And what it's gonna do is hit my endpoint. It's gonna call it about 500 times, and it's gonna keep it open for about 30 seconds. So what I need to do is grab the endpoint, which is just here, let's copy that, update my endpoint here. And then if I run this, it's calling my endpoint that has the variable sleep command. And what that does, it's gonna sleep for a minimum of 1,000 milliseconds and a maximum of 2,000. It's random, it takes random numbers there. If I go back and look at my pods, and check out the logs, here's a log message being printed out. It's sleeping for this many random milliseconds. Looks like it's finished. So if I go back here, it fired off 380 requests in 30 seconds. So that's not bad. And that's just one serverless function here. What I wanna show you guys next is the automatic scaling. So if I had a bigger system, I could send like 3,000 requests or 30,000 requests, but I don't like, so what I'll do is I'll artificially delay my application so that it tricks the K-native mechanism to scale out. And to do that, I will just edit the configs, I'll open this up, open up the YAML here. And what I wanna do is, I'm gonna set the concurrency of the hard limit concurrency so that each serverless function can only handle one or two requests at a time. Actually, I'll set the two. I'm gonna hit save. So now if I run the same test before, so I'll just hit this load test again. It's gonna run for 30 seconds again, but now if I go and look at my pods, you'll see a whole bunch of new containers being created. And it looks like it's about like 18 or maybe two dozen containers here. They're all running, if we look at the logs, we're getting the same sort of messages, but no, the load is being distributed across the different containers. And we'll just wait for that to finish, but this automatically, well, this sort of simulates like what would happen if you're out on like a Black Friday event where you just have a burst of traffic coming in, you wanna automatically scale up and handle whatever traffic, this finished. And then the next thing that we'll show you, if we just wait long enough, I think it's about a minute, maybe it'll give or take a couple of seconds here, these containers are sitting idle, they will start terminating. They're starting to terminate now. So while we're waiting for these to terminate, let me show you another thing. When I modified my configurations and I added that artificial concurrency limit, it created another revision of my serverless config. If I go to the revisions, I'll see two configs right here. I've got the original, which is 0001 and then my 0002. If I wanted to do something like a blue, green or canary deployment, I say I wanted to test what a new serverless function would be or how a new service function would behave, I could split traffic and send it to 50% of this one or 50% of that one. I can show you that here too. If I go here, oops, I add the service. Oh wait, where was that? There we go, set traffic distribution. You know, right now 100% of the traffic is going to my new version, but I could do something like 75% of that goes to the new one, 25% of that goes to the original or maybe vice versa, so that you wanna slowly roll out a new change. All right, so now if I go back and look at my pods, I think they should all be spun down now, right? We sort of waited a minute, now we've got nothing here. So now, that was just a demonstration of how easily it was to scale up and scale back down. One last thing is there are a lot of different configurations that we can set. The documentation's out here. You know, I configured the concurrency. I set the hard limit for how many can be concurrent, but there are many, many different configurations here. If we want it to scale to zero, which is by default it does, but maybe you don't wanna scale to zero. Maybe you wanna scale to one, so you always have one container ready to serve traffic and that will sort of help eliminate some of that cold start-ish, the cold start problem because you already have an application that's ready to go. All right, so that's all I had for the demo. John, do you have anything else to add? No, I think that was awesome. If you go back to the slide deck, we have the GitHub URL there. If you wanna play along at home, definitely check out github.com slash sqtran, that's deep, slash hello dash quarkis. And then you can pull down the code and do everything you saw here. You're gonna see in that repo, it's gonna have a little bit more code than what we just showed. We slimmed away and pulled away a lot of stuff just to make it clear and not overwhelm, but there's a lot of cool stuff that that repo actually does. Now here are all the links getting started to, and I'm gonna drop this in chat as well. Basically a lot of getting started places where there's courses and training and books and just places where we saw where we can just download and start running code. One of the main things that hopefully you take away from this is that this is not a scary thing. It's easy to get started with and hopefully you can see how to do it because Steve kinda walked through it. So feel free to pause and replay this, but pull it down and run it on your laptop and see how it feels. See if you like it. And if it does, start thinking about where you could use it, where you work today. Maybe there's a thing that this is perfect for where you have a short-lived job that you can try this out. Maybe it's a single function. Just to prove it out to say, hey, does this work? Does it work well? How does it work? Just to get your head around it. But that's the one recommendation to summarize all this is to really just play around with it. Yeah, so if we have time, I think we do have time, but if we've got any questions, feel free to drop it into the chat or you can ask out here. But yeah, do we have anything? It's okay. If not, we were perfectly answered everything that anyone ever thought about service. Yeah, we've got everything covered, so no questions. A great presentation, you guys. I'll also add that the recordings for this should be made available in the coming week, so keep an eye out. You might get an email. If not, they'll definitely be posted to the developer's YouTube channel here soon. So with that, we will sign off. Thank you, everyone. Yeah, thanks, everyone.