 Hello everyone, welcome to this week in CloudNATV. We are diving into a code behind CloudNATV. I'm Paul Simões, I'm CNCF Ambassador, and every week we bring a new setup presented to showcase how to work with CloudNATV technologies. They will build things, they will break things, I hope so, and they will answer your questions. Join us every Wednesday at 3PM AT, and this week we are proud to have Thomas Graf from ISO Valency, CTO from ISO Valency, and he will refuse to talk about network policies. Also, join us to KubeCon CloudNATV Con Virtual Europe in May, 4th, and 7th to where the last from the CloudNATV community. Remember, this is an official live stream of the CNCF, and as is subject to the CENCF Code of Conduct, please do not add anything to the chat or questions that will be in relation of the Code of Conduct. Basically, please be respectful of all your fellows, participants, and presenters. With that, I'll hand it over to you, Thomas, to get off to this presentation. Thank you so much to join us. We are very happy to have you talk about one thing very, in my opinion, interesting, but sometimes difficult to do, and I want to learn with you. Show me the code, please, Thomas. Thanks a lot, Paolo. What a nice intro. Let's hope we can demystify a bit of the complexity around network policy today. Hello, everybody. My name is Thomas. As Paolo mentioned, I'm a CTO and co-founder of ISO Valent. I'm also one of the maintainers of the Cilium open source project, which is the context, I think, why I'm talking about network policies. Cilium is a CNI that implements network policy, which gives us or gives me kind of good insights into some of the struggles that users of Kubernetes around our policy have. For today, I have a tutorial prepared that we can go through, but as you have questions, feel free to just interrupt me right into the chat and we can take it anywhere where you want. So I'm going to start sharing my screen. If you want to follow along, you can open this repo and just clone it, Cilium slash network policy tutorial here. We will basically be going through this step-by-step. It has all of the examples, all of the yamls, all of the links, everything you need. So let's dive right in. So first of all, what will we cover today? We'll cover a bunch of fundamentals here. Minimal on Kubernetes default allow, default deny, what is this, ingress, egress, what is this? And then broadly talk about ingress and egress control, like what is allowed to go into a pod, what is allowed to flow out of a pod. That's roughly our agenda. So what do you need to kind of follow along with me? You need a Kubernetes cluster. You can use any cluster that you have available. And we're going to use Cilium. You can of course use any other CNI as well that can enforce our policies, of course. If you want to install Cilium, install the Cilium CLI here, the instructions for Darwin and Linux, then create a cluster here, for example, instructions on how to do this on GKE. You can of course also use Minicube or kind of whatever you want and then install Cilium. Basically, with these two commands, again, you don't need to use Cilium at all. Any Kubernetes cluster with capability to enforce our policy is fine. And then we're also going to use Hubble here. So let's do this. Hubble is a EBPF-based visibility layer and it will help us a bit to gain visibility into what's going on on the network policy side. So let's quickly check whether Cilium is up and Hubble is up. So we have deployed Hubble here, Cilium is up, Hubble is still coming up. Let's give it another second. Thomas, sorry. Could you increase a little bit of your screen because it's a little bit difficult to see? Oh yeah, yeah, yeah, let's figure. Yeah, yeah, yeah, yeah, yeah, yeah, yeah, yeah. How does this look? Is it better? A little bit more, please. A little bit more. Take it, no, no, no, no, thank you. Thank you very much. All right. And then we are going to observe some flows. We're gonna use Hubble for this. So for the sake of the simplicity of this tutorial, we're just gonna do a port forward here and then run Hubble observe. All right, so we've already bind, it's good. And this will be observing flow for us. We'll use that way wrong. So let's dive in. First of all, what is network policy? Why should we care? This picture kind of shows where not network policy comes in. Network policy is a Kubernetes object that defines policies in your cluster, which means you can restrict network packets that go into a pod, that go out of a pod, both for pod to pod traffic, but also for traffic that's coming from outside a cluster into the cluster or for pod traffic that is leaving the cluster as well. So this is network policy. This is where this comes in. The enforcement is done by the CNI to contain a network interface. That's the network layer of Kubernetes. The CNI layer is basically responsible for the enforcement of network policy. In terms of Kubernetes understanding, you actually don't need to have a lot of understanding. What you need to understand is the basics, like there are pods, there are services and so on. In terms of network policies, it's all about pods. As you will see in examples, we will argue about pods, we will not argue about services or deployments and so on, it's mostly about pod labels. Throughout the entire tutorial, we'll always use this single example, like front-end and back-end with the service in front. All right, first concept that you need to understand, which is very important, which is default allow and default deny. In your Kubernetes cluster, if you're not doing anything, everything is allowed. There's no restrictions, any pod can talk to any other pod, any pod can be accessed from the outside, any pod can talk to the internet. Once you start introducing our policies, you can start putting individual pods into default deny. So this is not a global toggle, you can put individual pods, namespaces into default deny and start locking things down, we'll look into this. Second, very important concept is to understand there's a difference between ingress and egress. Those are networking specific terms. Ingress is basically network packets that go into a pod and egress or network packets that are leaving a pod. Network policy difference rates between ingress and egress. So you can say, I want to do ingress default deny, so I only want to control what's going into a pod and egress shall remain at default allow or allow everything. So you have fine-grained control over tackling either both ingress or egress or only one of them. All right, enough intro, let's get hands on. So first of all, we will deploy a demo app here into our Kubernetes namespace. It's very simple, it's a front-end and the back-end. So let's do this, let's deploy this. We'll start coming up and let's validate that this is actually running. You can see we have a back-end, we have a front-end, single replica is to keep it simple. The back-end has a service defined and then we have the standard Kubernetes service. This is all in the default namespace, nothing fancy. All right, to simplify the further commands a bit, we're gonna store the pod names in variables. Let's do that. Let's quickly validate that we have the pod names. So you can see this is basically, these are just the pod names. We will be executing into these pods to generate network traffic to test things out. All right, so now let's validate that we can actually, that it's that we actually have network connectivity. So we're gonna do a kube control exec into the front-end pod and run curl to the back-end to the service here. This is a service name port 8080, and then just print the first line. We will keep on using this throughout the tutorial. You can see the back-end has responded with HTTP 200, so yes, the network connection has been successful. This was allowed to talk. All right, so let's get network policy involved. This is how a network policy looks like. This is a specific policy that puts a pod into what's called default deny for ingress. It's interesting because you don't actually see the name deny in the YAML itself except for in the name. So this is the name of the policy, but this is actually the syntax that you're using to put a pod into default deny. If you're good, you understand this YAML. I'm usually, even though I've been working with network policy for a while, I usually use a network policy editor. We can look at that. So this link will get you to the network policy editor. This will visualize what this policy does. So this is the policy that we just saw, but it's now visualized graphically. So you can see there is a policy. It selects the pod at the back end based on the pod selectors. And then you can see the left, this is the ingress. This is now red. So this is now in default deny, which means it's all locked down. And then on the right, this is the egress. And you see it's all green. This is still everything is allowed. You can see this is still the YAML. Let me close my slack so we don't see the notifications. All right, so let's create this policy. Create the policy. It's loaded. We can see that it's loaded. Yes, it's loaded. We have one policy loaded back end ingress deny. And let's make sure that we are now in default deny. So let's see if the front end can still talk to the back end. And this should be timing out. And it will time out. See, it timed out after five seconds because we said like connect time out five here. So we don't have to wait forever. So we successfully put the back end part into default deny at ingress. All right, so because we only put the ingress into default deny, the back end should still be able to reach out of the cluster. So let's test if we can still reach kubernetes.io, the website. Let's do this. So we do an exec, curl, kubernetes.io, and yes. So like this return HTTP 301, so this was successful. This was kubernetes.io returning 301. So back end ingress is denied. Egress is still allowed. All right, let's look a bit into what these policies like, how this policy is constructed. We have the very common header at the top like every other or any other Kubernetes object that has a kind, the kind is not our policy as an API version, metadata, so just name and namespace, so it has a name. And then there's a spec. And the spec, the most important part here is the pod selector. The pod selector defines what pods does this policy apply to. Network policy is a namespaced object, so it means the pod selector will only apply to the pods in the namespace of which the policy is loaded into. There is also global network policies from several CNI providers, and there is upstream discussion around having a global network policy as well, but right now the standard network policy object or resource is namespaced. So this spec says this policy applies to all pods in the namespace that have the label app equals backend. And then the final part is spec policy types ingress. This means this policy applies to ingress. And then, okay, the question comes up, why is this now a default deny? This is a bit of a hidden specification, I would say. There is a rule which says that a pod is in default allow until a policy selects it. So unless you have a policy which selects it by the pod selector, and that policy defines that traffic direction, in this case ingress. So as soon as you have a policy selecting that pod, and as soon as that policy defines anything around ingress, those pods will go into default deny at ingress. This is how Kubernetes network policy works. This is why this policy up here is a default deny, because of this reason. All right. If we put ingress into default deny, how come we were able to reach out to Kubernetes IO? Kubernetes IO is responding package, right? And it's sending a reply, and that reply is coming back into our pod. Why was our pod, so why was this command successful? If I run this again, why was this command successful? Because of stateful policy enforcement. So what is stateful policy enforcement? Stateful policy enforcement means that reply traffic is treated specifically. This means if you have an ingress deny, let's say that the cross here defines the ingress deny, then new requests coming in, new connections will get blocked. If egress is still allowed, then reply traffic for those egress initiated connections that reply traffic will be allowed automatically. So this means you can have a policy that says ingress default deny, I want to block any new incoming connection, but I still want to allow my pod to reach out and receive the reply traffic. Then if the CNI offers stateful enforcement, then this is possible. All the popular CNIs offer stateful policy enforcement. So you don't have to allow the reply traffic specifically. You only have to allow the direction which initiates the connection. The very important. All right, so we have default deny. Cool, like now my front end cannot talk my back end. Very obvious next step is let's allow front end to talk to the back end, very obvious. And maybe you have seen a policy like this before. This is how the policy looks like. But let's look at it in the editor again. I think that's a nice visual, how that looks like. So very simple, very similar to as before. We see like a lot of red, almost everything is still blocked. But now we have one green line here, which is saying in the same namespace, the app equals front end pods can now talk to my back end. And we can actually think we can mouse over. Yes, and if we can mouse over and in the YAML below, you can see of the green shadow, you can see the element in the YAML in the policy that defines this part. So it's this part here that defines that pod selector match labels app back end ingress and then allow from the pod selector with app front end. So allow the front end to talk to the back end, not really rocket science, pretty clear. But even the editor I think makes it even easier to understand this. All right, so let's go back, let's load this policy. So this is the policy, we're gonna load it. So let's see that it was loaded correctly. But now we have two, we have a deny policy and we have an allow policy. And yes, that's valid, you have multiple policies, all the policies are additive. So this policy will put the back end into default deny and this policy will then allow from the front end. So let's make sure that this is actually working. We can see that the front end can now talk to the back end again and it's returning HTTP 200. All right, cool. So we have done pod to pod. It's probably not what you will do to get started though. A lot of you will probably use namespaces as natural boundaries of some sort. So a good starting point for many of you is actually to allow everything inside of a namespace. That's something that gives you quite a bit of segmentation and security, but doesn't require you to allow every single pod connection. So let's look at how that can actually work. Again, this is the policy here and we'll look at it in the editor easier. You can see now the green arrow is now the entire namespace. So any pod in the namespace can now talk to this. And you can also see an empty pod selector here. What this means is that it matches all the pods. So what this policy does, you can also, there's no longer an app equals back end here. This policy matches all the pods in the namespace and it also allows from all the pods in the namespace. So this policy, what this policy does is allow everything inside of that namespace for ingress. So any pod in that namespace can receive a packet from any other pod in that same namespace. Let's load this in. So we'll load it in and let's test it. And I mean, many of you will say, why are you doing this? You have already allowed front end to back end. So yes, of course it works. It has worked before, right? We now have three policies loaded, right? But you see that this is now a pod selector none. So it selects all of the pods in this namespace. We can now actually delete the specific policy. So we're gonna delete the policy back at ingress allow front end. So we're gonna delete this policy. That was the wrong copy paste. That's now deleted. Let's double check, but it's deleted. Yeah, now we have two left. So we have the ingress deny, the default deny and then allow everything in the namespace. And I'll test again. I need you to still work. Cool. Well, this is allow everything inside the namespace inside of for ingress call. So far we have been operating within the boundaries of one namespace. What if you need traffic across namespaces? Very typical example, Prometheus is running there and scraping metrics from all the pods. So think of the monitoring namespace here as something that requires access to all of your pods across different namespaces. How do we do this? This is the YAML and we'll look at it in the editor so we can see how that looks like. So this policy has now in the cluster section. So it's no longer in the same namespace. It's now in the cluster section. It has now a filter or a rule that says if the namespace label is type equals monitoring then allow it. So this policy will, it's the highlighted part. This policy says that any pod in any namespace with the label type equals monitoring is allowed to talk to the backend. So again, you see we have a pod selector match labels app backend. So let's actually load that in. And for this we don't have the monitoring namespace yet. So we're gonna create the namespace monitoring. We're gonna label that namespace with the label type equals monitoring here. And we're gonna deploy a sample application in here just so we can do something. Cool, we have that created that will get deployed. And we will also extract the pod name of the monitoring pod. Check if that worked. Yes, so this is our monitoring pod. So you have monitoring pod, you have a monitoring pod running. This is like, think of this as your Prometheus here running. All right, so backend is in default in i. So let's look at our policy that we have loaded. Backend is in default in i and we allow within the namespace. So the monitoring pod should not be able to talk to the backend. So let's see here. So kubectl exec, we're running curl and we are talking to backend default like to the service name of the backend pod here. And yes, this is timing out. So it's not allowed. Let's define a policy to allow this like the one that we looked at. So this policy, this policy, we're gonna load this policy. All right, and then test it again. I'm just testing and running it without the timeout basically. And that should now work. Yes, HTTP 200, so it's working again. So we have now enabled an entire or a set of namespaces to talk to our backend. Cool, probably not like in all the versions of Kubernetes that's the only granularity that you have in more reason and more reason being actually like couple of releases. It's not like the latest and greatest. You can combine the pod selector and the namespace selector. So we can actually do something allow from a namespace with the label type monitoring from a pod with the label app monitoring. So we can combine the two. And I'm not gonna load the editor. I think it's pretty obvious. From from, you can see there is now a namespace selector. So this is the namespace selector and there's a pod selector. And they are, they're ended together. So only both of those matches, they, the policy will actually allow this. So let's load this and also delete the old one. Like the namespace scoped one. So let's create the new one and delete the old one. So like we will remove the wider policy and install a more fine-grained policy. Yeah, so we now have ingress from monitoring app and let's test it. That should still work. Cool. So we've done a couple of things here already. Like we have shown how to lock down ingress. We've shown how to allow policies between particular parts in the same namespace. We have looked at how to allow everything in the same namespace. And we have also looked at how to allow from other namespaces to a particular part. What about egress? So egress is the traffic direction for things that are leaving the pod. Obviously putting a pod into default deny egress is exactly the same as for ingress but you basically write ingress here, egress here. So if you load this, it looks exactly the same as before but it should be red on the other side. Yeah, so it's now red on the right side and it's blocking egress and it's actually not affecting ingress so it's all green, right? So very consistent, what you would expect. Let's load this. Let's load this policy. So this will put the front end. So we're no longer doing the front and we're no longer doing the back end. We're now putting the front end into default deny. And let's test that the front end can now longer talk to the back end so that this no longer works. Let's see, because the back end still allows it, right? So if we look at our policy before we run this, there is still a backend ingress allow and there is still a bank, all pods allow ingress, but the egress portion of the front end is still now be blocking this. So if you have both egress and ingress policies then both policies need to allow it. But let's copy the wrong line. It should time out, both have to allow this. Cool, what about time out? All right, so far so good. Allowing pod to pod connectivity kind of it's getting more of the same, right? This looks exactly the same as before, but for egress. I'm not gonna show everything. Let's just load it in, all right? I'm gonna load it in. Let's look at a policy again, right? So egress to pod selector backend so front end can talk to backend. Okay, load it in, let's try it out. Why is this not working? Does anybody have an idea why this is not working? Right in the chat now, why is this not working? Didn't we look at the policy? Didn't we just allow it? With the pod selector, front end, policy type egress allow to backend. Is the policy loaded? Yes, front end egress deny and then front end egress allow to backend. Why the heck is this not working? Actually, let's look at, let's look here. This is actually, this is a perfect example why the editor is so useful. Let's see, let's say, let's try. Yeah, let's look at the editor. Let's see what the editor says here. So the editor is saying I have. I love this editor. Please, if you are presenting, talk more about that. Absolutely. So yeah, let's highlight like a, I think the editor being awesome here. So policy app equals front end and yes, there is a green arrow app equals backend. Cool, that this is this to highlight a part. Let's crawl down a little bit. What is this? DNS, has anybody ever heard of DNS? Like what does DNS do? Why is that arrow red? Ah, okay, could this be a sign? It's always DNS, isn't it? It's always DNS. So the reason why this is not working and if you watch very closely to the error message here, so to this one, look at the error message like very, very, very closely. Resolving timed out. So it was the DNS resolution that was not working. Why is this? Let's look at how DNS works for Kubernetes. So we have our front end pods and we have our backend pods and we have established this connection from a policy perspective. And then there is something called core DNS or cube DNS, which is running in the cube system namespace. And this is doing a DNS resolution. We did not allow this. Before we started locking down egress, front end was not restricted. So we could freely talk to core DNS. But now we put egress into default deny and all of a sudden, front end was no longer allowed to talk to core DNS. So if we do the connect here and we're talking to the service name, the service name, this needs to be resolved by DNS. That's why it's not working. We can validate this theory, right? So here's a bit of JSON query magic to extract the pod IP of the backend. Let's do that. So I can show you that this is just the IP. So this is just the IP of the backend pod. And if we now do the curl again, well, directly to the backend IP, it should work again, right? Because we actually allowed this. There you go, 200. So we've proven that it is DNS. It's always DNS, isn't it? So how do I enable DNS? So first of all, you could, and we're actually gonna do that as well. I can go in here, look, load our policy. And I can actually just say, like, allow DNS. And this will add a rule down here. Where is it here? We'll add this rule in here. Two namespace selector, pod selector, Kate's app, Qtns, port 53 protocol UDP, which is the DNS part. So you can write this YAML yourself, or you can use something like this editor to generate the YAML for you if you are lazy like me. You can then download it here to download the YAML and so on. You could share it in a get up gist and so on. So let's load this policy. It's basically, where am I? I'm above. Let's load this policy. What this policy does here, is the same or almost the same policy. This is a bit more restrictive than the one we just saw before. It has two elements. It has a namespace selector contains code DNS. So the namespace has to have the label type or contains equals code DNS. And the pod selector, Kate's app Qtns. How do concurrent policy apply if policies are additive? Great question. Let's answer that question before we continue. So all of the policies, you can load concurrently at the same time. And Kubernetes will then distribute them to all of the Kubernetes worker nodes by what the CNI is basically watching on the network policy resource. So all of the Kubernetes nodes will be watching for changes to the network policy resource. Very exactly the same way as, for example, Qproxy is watching for service and endpoint updates to the load balancing. So all of these nodes will be receiving the network policy updates at a slightly different time. Eventually, it's eventually consistent. And as they receive the updates, they will start enforcing those rules. So if you load three different policies exactly the same time, they might actually end up in a slightly different order at different nodes. Or like the CNI might process them in different orders and so on. There's very little guarantee given on when exactly a network policy is being enforced. Some of the more advanced CNIs, for example, Syllium can give you visibility into when all of the nodes are enforcing a policy, for example, but that's not something that standard Kubernetes network policy currently does. I hope that answered the question. Or maybe like, there's also another point here. If they're additive, this means by design, if the policies are additive and by selecting a pod, you put it into default deny. And then any number of policies that you load, they're all additive. So it actually doesn't matter whether when you remove it again, like what is allowed is always the sum of all policies. That's why you're not strictly dependent on one particular order. All right, so let's load this policy. And in order for this policy to function, we actually need to label our cube system namespace to add this contains code in S label for a second. So let's do that. Let's label it. Okay, that's already done. So it's already has this label. I have apparently run this demo before. And let's load a policy. And then we will try again to reach the backend, why the name, and this should now work. Yeah, so it's working. So we now have functioning DNS again. All right, bonus question. We just loaded a policy. So we just loaded this policy. And this policy, look at the name here. It says allow pods, egress, allow DNS. It allows all of the pods to talk to DNS, which makes sense, right? You want all of your pods in the namespace to talk to DNS. We didn't limit this to frontend. So what is the side effect here? So let's look at the, let's look at the, this is very important. I think one of the most common mistakes, I'm gonna make it bigger. These are the policies that we have loaded. So we have all pods, egress, allow DNS. And we have all pods, ingress, allow within namespace. So ingress is wide open. And then we have backend ingress to our monitoring app in the other namespace. We have the ingress default deny. And we have a frontend egress deny. So like only the frontend is egress deny, right? And then the frontend can allow to the backend. So what do you expect? Do you think the backend is now restricted at egress? Or not? Like we don't have a deny, right? It doesn't, it doesn't say deny. Ha. This is, this is truly important to understand. If you remember what we said, as soon as you have a network policy that selects a pod and defines any rule in a particular traffic direction, that pod will go into default deny. This means that this policy, even though the intent of this policy is to allow to DNS, it will put all these pods, and this is an empty selector, so it matches all the pods in the namespace. It will put all of the pods in the namespace into default egress deny, right? You don't need to have a specific rule to put something in default deny. As soon as you have a policy, as soon as you select a pod, that pod goes into default deny. Let's validate this. This means that our backend is now also in egress default deny. This is reason number one, why you, how to shoot yourself in the foot with network policy. So let's try this, kubectl exec into the backend curl. We were talking to Kubernetes IO. We tried this before and that worked, right? Let's see if it still works because I didn't intend to lock this down, but yeah, it's locked down. So be careful. Do you see connection timed out? Look at the error closed closely. It doesn't say resolution timed out. It says connection timed out. So it was actually able to resolve the name Kubernetes IO, like the coordinates connection worked, but then when it attempted to reach out, that didn't work. That connection was dropped because there is no policy here that allows the backend to reach out and we all of a sudden put the backend into default deny. All right, so this was an introduction. There is many, many more pieces. In a couple of weeks, this repository will receive updates on a couple of additional parts, in particular, how to secure connectivity in and out of the cluster. So how do I allow external clients? Like let's say my mobile app running on my mobile phone, how can I allow that app to talk into my Kubernetes cluster? How do I secure this? How can I allow my pods to talk to outside of the cluster in a safe way without opening up everything? That will be part two, that will come. And we can look into that a little bit if you want. Special cases, we have not talked about host networking, for example, and we can look at that real quick if you want. Load balancers, health checking. So you have Kubernetes has network health checking and also how to troubleshoot. The troubleshooting part we have done a little bit, I think in particular the policy editor was very useful here to track down, it was DNS. So let's talk a little bit about the host networking part. Network policy only applies to non-host networking part. So as soon as you have a host networking part, it will, from a CNI perspective, it will look like this is coming from the Kubernetes note and not a pod. So if you have a policy, something like, let's see, let's say, where is our egress? Something like this, right? And you have a host networking pod with the label app equals backend. Then the policy will not allow to this host networking pod because it's not a pod. It's not a Kubernetes networking pod, it's a host networking pod. Question, can you talk about IPvlan networking in case of health checking as well? Super advanced question. Yeah, so the question here, I will try to give like 30 seconds of background why this matters. So IPvlan is in advanced mode. It's kind of a replacement for a Linux bridge that's a networking concept developed by Google and others specifically for containers. It has better performance than a standard bridge. The reason it can do this, or like the main benefit it brings is that it directly extends the interface into the container namespace. So pods use containers and containers use network namespaces. That's a kernel concept. And IPvlan is optimized for this specifically. The downside of this is that there is no representation of the host anymore because you basically, it's basically as if you were exposing your container directly to the network underneath. Like it's not really, there is no direct path to the host anymore. And health checking, Kubernetes health checking, if you are using network health checks is coming from the host. Like Cubelets will run the health check. So you will have a network connection from the host to the container. And with IPvlan, unless you do something specifically, this will simply not work. If you use Cilium in IPvlan mode, we have specifically added this. And I think the Lyft CNI, which also has an IPvlan mode, also offers this via a secondary interface. I can dive deeper into the Cilium details there. If anybody wants, we can I think maybe take that to the Cilium Slack. But the short answer is, it's more complicated with IPvlan. Cilium has an implementation that allows you to use IPvlan and health checking at the same time. So let's talk a little bit about the health checking, maybe what that means for network policy. Do I need to allow health checks with network policy? Yes or no? What do you think? Like, should it be blocked? If I put my pod into ingress default deny, should I, should the health checking continue working or should it not continue working? It's a philosophical question. And the answer is that early on the decision was made that any connection from the local host where the pod is running on should be allowed into the pod. So no matter what you do on the network policy side, so let's say you have an ingress, all ingress backend ingress deny, for example, the host can still open a connection to this pod and to network health checking. If this is not desirable, if you don't want this, and I think my recommendation from a security perspective is that this is actually not what you want. You want to explicitly allow these health checks, then you can put Cilium and probably other C&Is as well potentially, you can put Cilium into a special mode where you have to, it's basically disregarding the Kubernetes default and you have to specifically allow the local host to talk to the pod. We can quickly look at how that looks. I will just, because we're getting a little bit out of the standard network policy, you can do it as well. I will show it with like Cilium policy language real quick, which is simply a custom resource definition. So let's look at that. This is just a Cilium documentation. Cilium has something called entities, which are basically logical representations of things and one of them is the host. So you can, I think there is an example down here, yes. So you can do something like this, like this is a Cilium policy, it looks very, very similar to CRD, API version, it's just a Cilium API version. It's a Cilium network policy, not a network policy, it has a name. We call it the end point selector, Kubernetes it's a pod selector, and then there's like two entities, this could also be from entities, so you would be saying from entities host and you're specifically allowing from the host. You have other entities here, for example, you can say world, this is everything outside of the cluster. Unmanaged, this would be host networking pods and so on. But this is getting into the veto a bit more Cilium specific. You can do this with Kubernetes policy as well, but you will need to start using cider-based rules based on actual pod IPs or host IPs or subnets and so on. So I wanted to show this that you don't have to hard code IP addresses if you want to allow this type of traffic. All right, and I think for a couple of minutes left, what would people like to spend more time on? What do we wanna dive deeper? Relative STP support or network policies, Cates enables STP? What is the advantage of the protocol? Great question. Not really network policy specific, so there is a network policy specific aspect to STDP. Network policy, if you do a layer four rule, so like what we saw here, so if you do something like this, this is what's called, I guess I have to move it. There is I think some overlay on the screen. Here we go, yeah. So if you do something like this in your policy here, you basically specify that the policy only applies to particular port. It's going into layer four, that's like TCP, UDP or STDP. If you are doing this policies, then the CNI that you use has to support STDP because it has to extract the port number. So not all CNIs will be able to do policy enforcement for STDP. So STDP, what is the advantage? Traditionally that was UDP and TCP, UDP is unreliable. There is no guaranteed ordering. It's basically you just shout out to the world and hope the receiver receives as much as possible. TCP is designed to survive a nuclear blast, like it has retransmits and retries and is reliable and it will find new routes and so on. But it's also like slow and it has limitations. STDP is something in between. So it is reliable with unreliable benefits. Let's put it that way. So you have more control over what specifically you wanna do with STDP. There's also like a multi, I'm not sure what it's called, multi-session or basically where you can have multiple streams within a single STDP session, very similar to how HTTP offers this as well, like a single TCP connection or a single STDP connection and then HTTP, you can have multiple streams within that. STDP has something very similar. STDP was kind of seen as the future for a long time. I don't think that's necessarily really true anymore. I think if you look at modern usage, you probably see more things like Qwik where UDP is just the dumb transport layer that you use and then you build your own protocol like Qwik on top of that. So if you're interested in like how can I do better than TCP or UDP, STDP is something to look into but I would definitely recommend to look into Qwik as well. Cool, that was a good question. Yeah. It was really amazing. We have a few minutes on more, really amazing. I want to invite you to next one, next moment to talk more about this, the next steps of your tutorial. What amazing tutorial, really amazing. I learned a lot and I will study it again in this with, which is really amazing. The next steps was really amazing and part four, especially to talk about part three and four, it's something very, very interesting in my opinion. The commission, right. My one question is really, you show, first of all, it's very, it's more simple for me, understand this all concepts about network policy. But one question is about best practice. Suppose that I have a production environment, not a developer environment that it's much more open but when I plan a production environment, I should apply the best practice for security. And from your opinion, there are best practice for adopt network policy in a production environment, close all e-grass, open with think granularity. What's the better approach for that? Maybe there is many other. Exactly, no, that's a great question. Let's go into the editor and start with an empty policy because I think you want to secure your Kubernetes cluster and we got this question a lot. So we actually, we wrote down our expertise in a tutorial here. So in the lower right here, welcome to the now, this is a full tutorial that helps you to think about this from the right angle, like what are good steps and we can actually do this together. So right now, everything is wide open, like everything is green. Let me make it a bit bigger here. So I can, this is the explanation ingress, egress because like, okay, you know what I'm talking about. This is the explanation ingress, egress, because like, okay, ideally you should do, you should do both ingress and egress and default denies. So let's start with ingress and then let's allow our Kubernetes DNS. Yes. And then you can say, oh, I want to like take an easier step and allow everything in namespace or do pod level and so on. It has an explanation like the benefits. And then look at this, this is very interesting. There is a policy rating. So based on what we know, we are rating your policies. Like, and I think I can make an example. Like this is obviously very secure because it's like everything is disallowed except for QQ DNS, that's a very secure, that's five out of five. We could talk about DNS infiltration or something. And like, well, let's say we actually allow all traffic in the same namespace, let's do that. And now the policy rating actually went down. So like the policy rating ingress and default deny is enabled, that's good, that's five but then allowing everything within the namespace is not quite as secure as it could be. So it's only like a three out of five. So if like you see that you have room for improvement. So I think that's one good way to learn about like best practices and start moving into the right direction. So I think often it's obvious what the ideal and posture is like, yes, everything should be in default deny only like everything is least privileged, everything is zero trust. If you have existing clusters, it may not always be that simple to just get there in one step. You will have to do it this step by step. So this tutorial here, and this is like free, you can just use this like editor.stile.io shows you the way and also shows you the incremental steps. So like there's more here, like allow traffic incoming from outside the cluster and so on. We can allow outgoing traffic from the cluster. We can for example, say allow everything on certain ports. We can say allow egress using a DNS name. So we can use DNS names that's a that's a Cilium features. You can filter on ciders and so on. So it goes into all the options and it explains you what is the best option and what might be a simpler option. And you always have to pause your rating to kind of do the final assessment of everything. And then in the end, I think what gives you if you zoom out again, it basically gives you like the YAML in the end, right? And you can just download that, push it into your Git or something and then start enforcing it as well. I think that's for many users, this will be a great starting point. I think it doesn't completely avoid that you should also understand network policies. So I think going through this and understanding the core concepts and understand playing around with it is also useful. Like if you want to be secure, you need to understand your systems. Don't rely on some complete automation. Can be an easy win. I think it can be good as well, but don't fully rely on something like the policy editor. Like always also understand like policy editor looks good, but then if you don't know that like the health checking is actually allowed, you might have a hole that you are not aware of. One of the biggest holes that we often see is the unawareness that because traffic from the local nodes to a pod is allowed, that this then means that any traffic that gets masqueraded by Q-proxy on the local node is at risk of being seen as traffic from the node. I know this is already a kind of technical networking wise, but this can happen. And depending on the CNI that you're using, the CNI might not be able to differentiate between this is proper house traffic, like a health check, or this is just like masqueraded traffic from Q-proxy. Some CNIs, including Scyllium, can differentiate, not all CNIs can do this. Great, Jonathan. We are receiving many, many congratulations here. Thank you everyone. All right, very good. Thanks. Jonathan, we have so few minutes, but please show to us this interface, the Scyllium project, it's amazing. It's an open source, it's an open source project. Yeah, absolutely. Please, more information. Yeah, so Scyllium open source, I think many of you probably heard about it in some way or other. It's a cool CNI plus more. So we do CI networking, we do a lot of network observability, we do network security, but we also do transparent encryption. It's all open source. Let's prove it. Let's go to GitHub. You can see the source code here. So it's all open source. It's not just by ISOvalent, obviously we contribute to it heavily, but we have many external contributors as well, a wide set of people contributing, more and more users and cloud providers are starting to use us. I think the most notable one is GKE that has built us in recently. Yeah, like if you are interested in Scyllium, check out Scyllium.io. I think great starting point or just our GitHub page leads you into the documentation, leads you into like getting started guides where you can start playing around. So we can, for example, look at network security policy tutorials or like a bit more, we covered the basics today, but we could, for example, look at how can I inspect TLS encrypted connections? How can I secure Kafka? How can I secure CRPC? Locking down with DNS, like the more advanced topics as well. So as you dive deeper, feel free to check out Scyllium.io for more information as well. If you are interested in receiving updates on this tutorial as it receives more updates, I think the best way is to subscribe to the Scyllium Twitter handle because we will be pushing out updates there. So the handle is here at Scyllium Project. That's probably the best way to follow and get updates on how we, when we push new updates. Perfect, perfect, Jonathan. We have one question about, if Alibaba Cloud also uses Scyllium IRC, right, IRC. That's right, yeah. So obviously you can use Scyllium on all of the cloud providers. I mentioned GKE because they have embedded Scyllium and I'm using it for everything. Alibaba Cloud is also using Scyllium. Digital Ocean is using Scyllium. Maybe others are using it where we don't know specifically. The one like, I think maybe because this question was up there before, Alibaba is using specifically Scyllium in the IP VLAN mode as well for the high performance use cases. So if you have been, like if you are interested in IP VLAN and why it matters, there's a great blog post on Scyllium IO and why Alibaba Cloud is using Scyllium in IP VLAN mode. Yeah. Perfect, Jonathan. Really, I wasn't perceived presentation. I learned a lot. I'm very motivated to run this tutorial by myself. I will do that. Thank you so much. And we had a great collaboration from folks for our meeting. I want to invite you again. We have a lot of time to talk more about this and the other projects for us, Thomas. It was amazing. Please conclude your presentation. Yeah, thanks. This was a lot of fun. I love doing hands-on sessions. Please let me know what you like, what you didn't like. You can find me on Twitter. You can find me on the Scyllium Slack. The Scyllium Slack is also a good way to get involved in that policy in general or the CNCF Slack or the Kubernetes Slack. I'm available on all of them. Just look for my name, Teegrov in general. Always looking for feedback. And thanks for joining the session. And thanks for hosting me, Paulo. This was great. My pleasure and my honor to be here with you and learn with you. Thank you so much. Everyone, thank you so much for joining us in the last episode of this week in Cloud Native. It was great to have you, Jonathan. And I want to see you again here with us. We also really love the interaction and the question from the audience. We bring you all the last Cloud Native code every week at 3 p.m. versus time. Next week, we'll have another amazing presentation. Please join us. And thank you so much for this amazing session. See you, guys. Thank you, everybody. See you next time.