 Make us go live. Katie, did you make us go live already? Wow, it says we're live. I guess I'll just roll with it. Katie, feel free to slack me if I am wrong or need to stop. That said, hello everybody. Welcome to the inaugural episode of Chatloop Backoff. It is February 8th, 2024, and unfortunately it is dreary and raining outside, but inside I think we will have a much better time. This program will deep dive into the realms of the cloud-native landscape. I am your host, Jeffrey Seca, but many of you know me already as GV. I am thrilled to have you join us for today's episode and we're gonna be focused on Kubernetes Gateway API. This live stream is kind of a sibling to a similarly named thing that we do at Kube.com, it's called Clashloop Backoff. I'm very, very creative in my naming scheme. In the KubeCon version, we put two community members against each other to accomplish a technical challenge of my choosing. It's meant to be laid back, at least for the audience, but generally fun. This stream is more of a self-induced version of Clashloop Backoff. I have not done any in-depth research onto this topic. Instead, I want to just dive into the topic with fresh eyes and I want to learn as I normally would off-stream, like you are going to see me kind of blunder through this. But in doing that, hopefully we can kind of walk away with having learned something together. A few housekeeping items before we get started. During the live stream, feel free to drop your questions in chat. Once I'm done reading the normal thing that I have to read, I'll be able to see everyone's messages. We're here to learn together, so if you know the answer to something or I'm stuck and you have an idea for me to follow, please speak up. Comments are welcome. That said, this is an official live stream of the CNCF and it is subject to the CNCF Code of Conduct. Please do not do anything or add anything to chat or ask questions that would violate that Code of Conduct. Basically, please respect all of your fellow participants and presenters. This video will be put on our YouTube channel afterwards, so folks that couldn't make the live stream can still learn along with us just asynchronously. With all of that said, there was some news that I wanted to talk about before we kind of get into Kubernetes Gateway API. First off, and this is hot off the presses today, a CNCF project known as Strimsy has just moved up to the incubator level of CNCF projects. So it joined in Sandbox a few years ago and I'm surprised it took this long to make incubating. Strimsy is a project in the CNCF to help manage Kafka instances in Kubernetes. Again, stateful things in Kubernetes usually need a little bit of massaging and handholding and Strimsy was a way to handle Kafka. I know a lot of places that are running Strimsy, so it's very happy to see this move on. Next up, just making folks aware of this, but if you were attending KubeCon EU, Paris, and you don't have travel plans yet, there is actually a third party group getting together and doing sort of a group train ride from different locations within the EU. It is aptly named Kube Train and it sounds like a really fun time. I will make sure to provide a link for anyone and everyone so they have more information. And the last bit of news, this is gonna sound crazy, but it actually looks like KubeCon CloudNativeCon EU 2024, Paris, that's a mouthful, might get waitlisted soon. So if you were debating on registering, I know that the early bird pricing just finished, you should register sooner rather than later or you might not make it in. Again, there's still time, but it doesn't look like there's much time and it's gonna sneak up on us pretty fast. So all of that said, let's talk about Kubernetes Ingress and specifically the Gateway API, but they are kind of intrinsically linked. Let me switch views, yay, okay. Thank you, Katie. So let's talk about Ingress in general. Kubernetes has this concept of Ingress, like Kubernetes cluster has, I guess I will show off my sweet drawing skills. You have a control plane node and then let's say you have three worker nodes. So, okay, wow, KCP, and then we'll just say worker. Worker, I might have to buy myself a little drawing kit, but you are outside of the Kubernetes cluster and you want to get access to a workload in there. How do you do that? Well, there's different ways that you can, I am not proud of this drawing. There are different ways that you can get access to a service running on here. Let's just say this is a web, I'm gonna have to draw really carefully web. There's different ways you can do that. Within Kubernetes, there are three technically for, but three main services. There's a cluster IP, which is meant to handle internal traffic within Kubernetes. Then there is a node port service and that exposes a port on every single node here. Same port, but it will route into this web service. So even if you hit like, let's say this IP is one, this IP is two, yes, I know those aren't valid IPs and this IP is three. If you hit, let's say port one, one, two, three, five on web server or Kubernetes worker node number three, it would actually route all the way to this service running on node one, node one IP one. That's not very helpful and that's not really how folks think about, routing and getting traffic from outside your cluster into the cluster. So there is a third type of service called a load balancer service. And that load balancer service expects usually that there is a entity outside of the Kubernetes cluster, not always, but bear with me, that it can direct and say, hey, we are going to have our own IP address and this will be, we'll say IP address of four. And if it gets any sort of traffic to IP address of four, this thing could have, you know, five and six. But if we get anything of IP address four, we are going to route it inside and Kubernetes itself will point to the web service, the web pod. That's still not ingress though. All that's really doing is focusing on routing traffic from point A to point B into a specific pod or workload. Ingress is a little bit more nuanced. Ingress for Kubernetes was specifically HTTP traffic and HTTPS, but really it would have HTTPS on the outside of the cluster. Once it got inside the cluster, it would terminate and then all the traffic within the cluster would just be HTTP and generally, you know, not encrypted. So then the question is, we're a big old eraser. So then the question becomes, how can we do any sort of logic around routing when, and I happen to have had conversations of folks, when Ingress was first introduced, it was meant to be a stop gap because it was only handling a small subset of traffic that Kubernetes could host, HTTP. Now, certainly, certainly a lot of workloads that are hosted on Kubernetes happen to be HTTP and, you know, web style workloads, but kind of an unintended throwback to the news, Strimsy, Strimsy is not an HTTP workload. It's very much just TCP. And when you have workloads like that, you can't really use Ingress. You have to use like a load balancer or you have to do node port and kind of handle things on the outside of the cluster. So Gateway API is meant to tackle what the basic Ingress class couldn't. And actually let's pop open to the actual Gateway API docs because I did read one thing that I think everyone should understand. And that's this right here. Because what I said can be kind of confusing. I recognize that. This is a nuanced topic and this puts it very clearly. So all Ingress really does is focus on exposing HTTP applications in a basic manner, just basic, there is no logic. You can do routing based on the URI to a specific service, but otherwise it is very simple, very easy. And in fact, Kubernetes, Ingress, this is like the most basic Ingress example. So assume that you have a service named test and that service is exposing port 80, route any traffic to the Ingress controller to this path. So if you hit that path, it goes to this service and presumably something running in a Kubernetes cluster. It does not do anything outside of that and it is not meant to. But in the real world, there's quite a bit more that we'll need if we wanna have production level, I guess controls around Ingress into a cluster. And again, what this doesn't do is it doesn't do HTTPS. Ingress can do HTTPS from the cluster outside, but once inside the cluster, there is no encryption usually. You have to have like a service mesh setup to handle that separately. Sorry, my little Doge has decided to start barking and she needs to be quiet. Yes. All right, so that kinda covers in a nutshell how I am distinguishing Gateway API from basic Kubernetes Ingress. What does Kubernetes Gateway API actually look like compared to this Ingress resource? I am glad you asked. Hey, Nuna, don't make me kick you out. So this is the simplest Gateway. If you hop into the Gateway API docs, click Guides and go to Simple Gateway. It is the simplest possible deployment. And what this is doing is defining a listener, saying all namespaces from there are allowed in and it's assuming a Gateway class that is just kind of fake. And then we specify routes. So when we specify a route, we're saying, hey, given these rules, you know, there's a backend reference of foo service and we're having this port, route to prod web, which is defined up here. It seems a little redundant, which it kind of is, but it also means that we can have multiple different rules in defined for the same service that we might be targeting. So one thing that I was interested in was like being able to split traffic, essentially creating weights, almost like with like HA proxy and other types of load balancers, you can say, you know, shard off 10% of traffic to this test instance or, you know, kind of this new version, but 90% of our traffic is still going to sit on this stable version until we know that all, thank you, Bob, I just saw your message, till we know that all traffic in the test instance is stable and isn't producing any errors. And then you can actually gradually start sharding things off. So it goes from, you know, a 9010 split to a 7030 split to a 5050 split and then probably, you know, boom. So that's one thing that you can do in Gateway API that you can't do with basic Kubernetes ingress. That's pretty nice. The other thing that's nice, and though this is experimental, this is, you know, being worked on actively is being able to route TCP traffic. Like I said before, if you needed to do any sort of TCP traffic routing, you had to assume or we had to have the Kubernetes cluster set up with some sort of load balancer and you were going to absolutely dedicate usually like an IP and a port to that TCP traffic. Now we can actually do a bit more using the same declarative way that we would define our HTTP traffic and routes, but with TCP and with GRPC as well. So it's nice to see this extensible way for us to define all of our traffic from, you know, external to the cluster going into the cluster. Before you kind of had to pick your poison, you had to decide again, I'm going to set up a load balancer and then I'm going to run my own ingress instance or I'm going to be running multiple ingress instances. I've had to do that. And then any sort of like TCP traffic that you're trying to host within there, you might need a completely separate IP address dedicated for that, using a completely different way to define traffic getting into your cluster. This is kind of unifying things and also honestly creating a much more organized way to do so. So where to begin? It accomplishes this apparently through these different primary things. TLS route and HTTP route are handled generally the same. One just defines an SSL cert and the other one doesn't. But gateway class, there we go, is the way that you define the gateway, essentially the ingress into your cluster. I realized the terminology is redundant. I apologize. The gateway itself describes how traffic winds up routing into services. And then you can define individual routes depending on the type of traffic, whether it's HTTP, HTTPS or TCP. This here is not how I normally learn, but we're going to get to how I normally learn. How I normally learn is in an editor and a terminal. For those playing at home, I am using, essentially my setup is I use a variant of Fedora called Bluefin. It's actually a variant of a universal blue. I blame George for any issues that I run into on my machine. I highly suggest you all do the same. So there you go. As with everything, we need to start off with the Kubernetes cluster. I happen to be using kind. Kind is what I use all the time. I'm most familiar with it, but this should also work with, you know, mini cube or K3S. I will also happily blame George for anything as well. Thank you, Bob. All right, we now have a kind cluster. I have a Kube CTX and KNS installed. I will make sure that I should actually pause. After this, when we post everything to YouTube, we will also have essentially a retro with all of the links, mentions, and even tools that I'm using. So everyone can kind of follow along at home and we all have the same resources. That said, I have a tool called Kube CTX and it also comes with kind of a different tool called Kube NS. It's just shortcuts to list and switch between different contexts in Kube Cuddle and different namespaces. So we see that I am, you know, in kind, kind context, I'm in the default namespace. Like I said, I did very minimal prep, but I do need to be able to speak a little bit about it just to make sure, A, I can do a demo and B, you know, I actually make this meaningful for everyone. In this case, the demo that I am going to use was set up by AWS, actually. AWS has a 2048 version of the game that you can install and then it sets up the service and everything. So let's get that going. All right, so it created its own namespace because it happens to be, you know, well, well done and nice. It created a deployment. I don't know how many replicas are in there. We'll find out in a second. And then it created a service that is likely going to point to that deployment. Oh, created a namespace. Wow, so it set up five instances of the 2048 game and it set up a node port service that is exposing 30116. And now you're gonna see how awful I actually work since kind is just running in Docker. Kubernetes and Docker. That's the IP address of the machine. Well, of the cluster, 30116. This concludes the demo, just kidding. But we do have 2048 running in our browser. So clearly it's doing something, right? But if you remember up here, all I'm doing is going to a specific node. In this case, you know, it's, our setup really only has one node. Or is the eraser? So we only really have the Kubernetes control plane and we as users are simply hitting that node on one, whatever the port was, right? And it's routing traffic directly to the pod. There is no ingress whatsoever. That's not what we want. What we wanna do is set up the gateway API. So how do we actually set up the gateway API? Let's find this out. Guides, getting started. So we need to install a gateway controller or install the gateway API CRDs manually. I think we will want to install a gateway controller. I think most people are going to be installing a gateway controller or using some sort of third party that's integrated with it. Multiple projects support the gateway API. Well, that's good. Okay. So there are different way or different projects that already support it, Cilium, Contour. A lot of folks that were using Kubernetes ingress were using Nginx ingress as kind of their main endpoint. And Nginx does have that as well. So I'm probably gonna go with Nginx also because it's GA. But there are other GA ones like Easegrass, GKE, Kong. All right. So let's take a look at Nginx gateway fabric. Let's get this rolling. Oh, quick start on a kind cluster. That was not planned. So we have a kind cluster. We can either install with Helm or we can install with Kubernetes manifests. Let's go with Helm. Let's use multiple projects. I love how Luna is still doing very tiny woops like I can't hear her. Okay, no, I'm not gonna do that. That's gonna take a while. Okay, so what I just ran into is a fun bug that I fixed on my laptop with. It's not a bug. If you are using Helm and you were using GHCR because, sorry, I should back up. If you were trying to install a Helm chart and that Helm chart is being referenced as an OCI artifact, you need to authenticate against the registry. I'm not gonna bother with that. In this case, we will just do apply the manifests normally. I'm not gonna make us waste time there. So install gateway API resources. Actually, I should go back, install with manifests. Cool. So now we will install API resources. We are on one, two, nine, I believe. So we don't, that doesn't apply to us. Wow. Yeah, one, two, nine, one. Excellent. And then here we go. Just deploy the stable release. Oh, this is their CRDs. So the Nginx specific CRDs. And then let's just go stable. So it created Nginx Gateway namespace, service account, cluster roles, deployment. And then those are the new CRDs that we installed as well. So let's verify the deployment and make sure that we get what we expect. Yay. Cool, cool. Don't think we need to upgrade. Let's see what else their kind demo had. Okay, so they do port forwarding so you can just do that locally. But I don't think we need to do that. Next, let's try and figure out how to get an, or a gateway API like route to our 2048 game. So if we do guides, getting started, simple gateway, let's start out with that one. Let's just get these all in a single folder, or file, and let's call them 2048. And then we want to route to that backend. So service 2048. So this should create a gateway, gateway class name. Actually, do we need to look up the gateway class name? Yes, we do. Double check in for any questions. No, okay. So we are setting, we are saying use the nginx gateway class that we set up. We are creating a listener on port 80, calling that prod 2048 gateway. And then we're saying allowed namespaces from, what do we have to specify for that? Cross namespace routing. Okay, so we would normally create this in the namespace of the game, which is just called game 2048. And then we route to service 2048 port 80. So we don't do 8080, we want port 80. My keyboard just died. This might make it interesting. So anyone listening? Is it my computer or is it my keyboard? I will wait for, there we go. Okay, yay keyboard. Oh, no, was it? I think it might actually be VS code that died. Remember how we said blame George for everything? I am very close to blaming George for everything. Yeah, I think VS code just crashed. VS code has resurrected, yes. Cool, cool. Okay, so we're gonna name this 2048 route. We're gonna put this in the same namespace as the game that we've set up. This is the gateway. We're calling this gateway prod 2048. We were telling it to listen on port 80 and we are saying only allow routes from the same namespace. They'll be in the same namespace, which will be the same as the service. Think we good? Let's just see what happens. Sweet. Now a real question is how do we test getting traffic in? Presumably finish handling. Okay, so it just looked like it applied what it needed to apply in 2048. Let's go back in here. There was just that. Like I said, we're learning live. I have no idea sometimes what I'm doing. I would have assumed, rather I did assume that it would create a node port or load balancer depending on the config service for all of the gateway API and then route traffic through that. And then the config of that, which would have been the nginx fabric, would be dictated by the CRDs in gateway API. So let's see what the differences are between Ingress and gateway API really quick. Limited features. I guess the other thing I could do is double check. Actually, I should do that first. Let's double check what. Okay, let's do that instead. KNS, KNS, nginx gateway. It pays to read. Okay, so we are now just routing traffic directly to the nginx gateway pod, which means theoretically, 80. Oh, was it 8080? It was 8080. Bad gateway. So now let's look at what we defined in here to see if we are missing anything. So we want listeners on port 80, which is correct. And then the port forwarding we did, did 80 to 8080, which is why we're even getting nginx 502 bad gateway. Parent rafts, prod 2048, 2048, that matches. We're saying backend reference is service 2048. You think, oh, hi, Marco. You think the game is on 80 and not 8080? I don't know what you're talking about. Okay, Marco, I think you're right. So let's, let's reapply that should, oh, I'm sorry, we need to reapply the gateway stuff. So the route is reconfigured. Let's forward the traffic again to that pod. Did I totally miss it? Yeah, I did. There we go. Marco is a genius and everyone should applaud him. Also, he pays more attention to me. Boom. So we now have a working, you know, nginx ingrat, wow, nginx fabric gateway API setup in kind. The most basic of them, but still from here, we can actually start messing around with different things. So let's go ahead and look at, that's Kubernetes ingrat, that's gateway API. Okay, let's look at some of the GA features, all right? And when you think about it, these are kind of basic features we've all probably had to deal with when we're messing with load balancers and whatnot. So being able to do redirects based on hostname, that's useful. The example I was talking about earlier about actually being able to shard traffic, essentially weight traffic and have certain traffic go to one instance of your service and certain traffic go to the other instance of the service, how can we actually do that? Let's set that up right now. So I do it right, spec rules, backend roughs. When there goes Luna again, she's so needy. Oh, that's actually cool. That's super easy. I don't have to really do that much. So we can just assign a weight here to be 100 and then we can blah. Port 80, weight zero. So now let's actually create something new. Hello world pod. That's what we're doing now. That's our life. We're just gonna try and find a thing, boom. Yep, okay, we're gonna do it. So we're gonna create a deployment called hello node. We're gonna use one of our test images and we're gonna say, hey, expose this to port 8080. So now we have two different deployments, the hello node and then the nginx gateway. This one should, yep, it's up now. And now we want to create a service or we're not gonna do, let's do this over here quick. We're not gonna do service type load balancer, we're gonna say service type node port. Seems reasonable. So now if we come back here, now that was called hello node and this one was exposed on port 8080. Theoretically, nothing should have changed. We're just kind of doing a baseline here. Yep, all right. But now let's do the inverse. We should see the hello world thing, right? Well, at least something changed. That might not work because HTPRO is in a different namespace, not a gateway API expert. Did I put them in the, Marco, thank you. I need to like find a way to have the chat up in a place that I can actually see because I have to blow up my screen so much. Marco, you are absolutely correct. But you know what we can do? What we can do is explore something else. Cross namespace routing. Let's see if we can fix this without completely blowing this up. Okay, so we would have to in the definition for the gateway, let me pull this one up quick. So in the definition of the gateway, allowed routes, namespaces from same. So that means it has to be the same namespace. In this case, we could say allowed routes namespace from selector and then kind of make it all work, right? This might be fun. And then we need to change labels on those two namespaces. Maybe this will work. Also, just so you're aware, Kristoff, I don't appreciate DMs asking me to show my keyboard failing. Okay, so theoretically, theoretically, we are allowing routes from different. Oh, let me think about this actually. Okay, so we're saying routes from different namespaces. Does that mean backend references? I don't think it does. Oh, so I don't think there's a way to, well, I don't wanna say that. Let's actually read for a second. All right, so shared gateway access true, shared gateway access true, route attachment. That's in the store namespace. Then there's a route in the site namespace. Okay, so based on what I'm seeing, and you can correct me if I'm wrong, please correct me if I'm wrong. If we want to provide weight, if we want to weight backends essentially shard between different services, those services need to be in the same namespace. We can create different routes in different namespaces that the gateway can still reference, but we can't actually split traffic between them. That might not be true, but that's kind of what I'm seeing based on these examples. I mean, Marco, your disclaimer, this is the first time I've seen gateway API. Me too, dude. This is how we learn. We just mess around and we find out and we make mistakes. I love it. Okay, so I'm gonna backpedal. I'm going to clean up the resources in nginx gateway and then I'm gonna recreate them in game 2048. So hand wavy, hold on one second. Get deployments, deployment, hello node, service hello node, that should be it. Now let's pop over there. I am lame. We are going to create a deployment and we are going to expose that. Okay, where were we? Hello node is now running in the same namespace as game 2048. It should not be true since Istio can do that. Do you know if Istio can do that with gateway API? Because we're specifically talking about how gateway API is set up. I am certainly sure that Istio can do that to the nth degree. Now I kind of want to reread this. I'm gonna stop before we dive into that unintentional segue. Services are created, deployments created. And if we pop over here, well now I want to do this again really quick. Oh, did, sorry, one second. There we go. Those were, we left those two in there because we were in the old namespace. So now theoretically, well that's fine. Never seen that before. Support 8080, is it gonna fail again? It is, is it gonna fail for the same lost connection to the pod? Error finding service for gateway, service gateway, internet's gateway not found. Are those? Oh, okay. I'm kind of dumb. I'm actually really dumb. So I went into, because we created a bunch of stuff in the wrong namespace, I went in and assumed that we didn't have the namespace specified for these resources. So when I deleted them, even though I was in the namespace I thought I mistakenly created the resources in, we actually deleted these rules out of the game 2048 namespace thus causing that error. But we are now good. We have 2048 running here. Need to stop. So let's switch the wait to see it go all to hello node. So we actually, what I'll do is create a new one. Let's reapply gateway.yaml. It has reconfigured the route. So theoretically I forced refresh and we have our new service. And then because this is kind of like a fidget spinner in my mind, we can swap back. And then if we set it to 5050, theoretically I mash control shift R and then it'll just bounce between the two, right? Yay. All right. So I think that is like the barest bones demo of some of the things that gateway API can do. But yeah, it looks like there's, I might actually suggest or rather change the upcoming schedule for Chatloop back off as Katie's listening and cringing. I can just see it. But I think it might make sense to in a few weeks go over some, like, I don't know, not, we'll not call it advanced uses, but pick up where we left off here. Because what we've done so far has really gotten to parody with just ingress and shown a little bit more on how we can start doing weighting with routing, setting weights for routes. But I kind of wanna expand more into like TCP routing and actually look into, is it possible to have different services and different namespaces and change the weights there? Cause one thing, like I'm just kind of talking off the top of my head here. One thing that I could see use case wise is if you were deploying, you know, version one of your app and then you have version two, I would do that in a completely separate namespace. I would not do that in the same namespace because there may be different dependencies that are also being paired with it. There might also be different versions of CRDs that are dependent on that application. So I have to assume there's a way to do cross namespace routing and also cross namespace weighting. I might be wrong, but we'll find out. We do try to keep this kind of, you know, an hour long thing. So I wanna kind of wind down. Is there any questions, any thoughts, any opinions so far? I do believe that it's round Robin. So like I'm mashing control R, it's 2048. I'm mashing control R, now it's doing that. I think I was just doing it so fast that it was, I don't know, freaking out, not loading things correctly. So any thoughts, questions, et cetera? Also, how do people think this format of blindly going into things and just hoping that we can sort it out together is? Trust me, I am welcome and open to any and all feedback. Also, let's, KNS, CTX, what else? What else did I do? We showed the 2048, oh, this was the second one that we did, the Hello Mini Cube. Oh, that's just the service. EngineX Fabric thing, Marco, are you, oh, EngineX Fabric, thank you. Yep, yep, yep, now I get what you mean. Running on kind. All right, I think that that might be it for today. Please leave feedback. I am at GFE on Twitter and pretty much all over the place in Slack, Kubernetes and CNCF. If you have questions, feel free to reach out. If you have ideas for topics, I do know next week we were going to ride that AI hype train, sorry, but Kate's GPT, I have not touched it. I have heard lots of things about it. I have, the only thing I'm going to look up ahead of time is if there are any dependencies I need to spin up before doing it, but next week we're going to mess around with Kate's GPT and see what we can do. If it needs a cluster that actually has like real workloads that are broken and we need to mess around, I might do this on my home lab, but otherwise we'll try and do it in kind so it's a demo that people can mess around with on their own. Otherwise, thank you, thank you for being kind, thank you for being curious. This was a lot of fun. And honestly, this is a very clear insight into how I learn. I would be doing almost the exact same thing just without a camera and a light and a microphone and I would have music on and it would be loud. That's it. Feedback is welcome. I don't know, Katie, how do we do this outro? I guess I'll just stop sharing my screen and then we'll kind of go from there. Yay, all right. Stop, stop screen sharing.