Overview

About this video

What You'll Learn

  1. Distinguish ClusterIP and NodePort services by how clients reach pods.
  2. Trace service selectors to endpoints, then watch readiness probes change traffic.
  3. Use port and targetPort, plus named ports, to map requests correctly.

Anaïs Urlichs and Philipp Strube join David to break down Kubernetes Services: ClusterIP, NodePort, port versus targetPort, selectors and endpoints, DNS-based service discovery, and load balancing across pods.

Chapters

Jump to a chapter

  1. 0:00 Holding screen
  2. 1:00 Introductions
  3. 1:05 Introduction
  4. 1:40 Speaker Introductions & Motivation
  5. 3:58 Setting up the Example (YAML)
  6. 6:00 Multi container pods
  7. 6:02 Networking within a Pod
  8. 7:49 Understanding Pod Port Conflicts
  9. 10:57 Sidecar Pattern
  10. 13:41 Networking Between Pods and the Need for Services
  11. 14:30 What are the 3 types of service?
  12. 14:38 Introduction to Kubernetes Services
  13. 15:05 Service Role: Discovery and Load Balancing
  14. 16:08 Kubernetes Service Types Overview
  15. 16:45 ClusterIP services
  16. 17:38 Defining a ClusterIP Service
  17. 18:09 Service Selectors and Labels
  18. 20:31 Inspecting Service Endpoints
  19. 22:00 Readiness Probes and Service Endpoints
  20. 24:16 Labels in Deployments, ReplicaSets, and Pods
  21. 28:00 NodePort services
  22. 29:10 Service Port Configuration (`port`, `targetPort`)
  23. 31:00 NodePort Service Type
  24. 33:07 Use Cases for Service Types
  25. 35:50 Exposing Multiple Ports in a Service
  26. 38:29 Demonstrating ClusterIP Service Discovery & Load Balancing
  27. 40:14 Attempting NodePort Demonstration
  28. 42:40 Detailed Explanation of `port` vs `targetPort`
  29. 45:09 Named Ports
  30. 46:50 Environment Variables for Service Discovery
  31. 47:48 Successful NodePort Demonstration
  32. 49:14 Summary and Q&A
  33. 51:44 Conclusion
Transcript

Full transcript

Generated from the English captions. Timestamps jump the player to that moment.

Read the full transcript

1:05 Introduction

1:05 Hello and welcome to today's rather impromptu episode of Rawkode Live. Today, we're gonna be taking a look at Kubernetes services, breaking it down and trying to understand how they work, how to use them and anything else that pops up. Today, I'm joined by Anna Ace and Philip. Hello. How are you both? Hello. Great. Thank you. So, at a moment Great to. Thanks for having me. Yeah. No. My my pleasure, honestly. Let's just quickly I'll have you both do a quick introduction, and then we'll talk about why we're here, what we wanna cover, and then we'll just

1:36 get straight into it and see what happens. So, Yves, would you like to go first? Awesome. Yeah. Sure. So I guess, also kind of the story of how it came to this episode in some way. I've just recently transitioned into DevOps. I've worked for the past years in the blockchain industry, mainly doing community management and developer relations, and then found out about Codefresh, which is a CICD platform, and joined Codefresh mid of October. And since then, I've embarked on this learning journey across DevOps and specifically learning everything that I can about Kubernetes. So I've made it my mission, so to say,

1:40 Speaker Introductions & Motivation

2:20 to put everything that I'm learning live on a public Notion page where you can read my notes and everything that I come across and any resources that I found particular useful. So I've just started, end of last year, a challenge called one hundred days of Kubernetes, where I aim to learn every day something new about Kubernetes. And I've realized in the past days, so to say, that I don't quite understand enough about services and specifically ports within Kubernetes resources. And so that's what this episode is going to be more about. Yeah. Awesome. Thank you. Philip?

3:00 Yeah. So I'm Philip. I ended up on this livestream mostly because I saw a tweet and offered to answer some questions. I've been in cloud and containers and Kubernetes for quite a long time. It's more like ten years than one hundred days. I started a PaaS company in 02/2009 and I'm currently spending my days working on an open source Terraform framework that helps people do GitOps with Terraform for Kubernetes, basically. And, yeah, well, I just am excited to see what the questions are gonna be and if we can figure it out together. Fingers crossed. I'm I'm I'm sure between us

3:37 we'll we'll get through this for sure. Alright. Yes. We'll I'm I'm pretty sure. Yeah. I mean, I'm confident. I mean, know it's one of those things. The more you use Kubernetes, I think the more things you learn that you just don't understand were there. So but Yeah. But That comes more natural. Exactly. Alright. So why don't we start with was there any YAML and specifically that you were working with, Anais, that you would like us to use and go through to try and break down? Or do you want me just to throw something together really quickly and

3:58 Setting up the Example (YAML)

4:08 we can talk about the different components as we kind of go? Yeah. So I was just using, like, a really basic React application and kind of deploying the container on my cluster and getting up and running through a deployment, and then started from there to integrate, like, services with it on the cluster. So it's really basic YAML. The main problem was basically that there's there are lots of resources, but there are little resources that go in detail of, like, the different components that make up that YAML file. So, yeah, feel free to throw something together.

4:43 That might be interesting. Hey. Well, yeah. Let's see if I can remember how to YAML. But what I'll do is throw together two NGINX services. So we'll call this NGINX one and I know it's state partially difficult to read, but hopefully the code here should be better. So we have a deployment, we'll call this NGINX one and we'll deploy NGINX. I'll just let this yell at me, and nginx runs on port 80. This is what I would just call a really standard deployment. And we'll have two. So let's do, oh, too much. And what we wanna do is, I'm assuming

5:26 when you were working through the YAML that you were working with us, want two services or two deployments or pods to be able to communicate with each other over the Kubernetes control plane. Yeah. Yeah. That as well. And also, I mean, starting, like, really simple, just how do you access how would you access starting from, like, the beginning? How would you create a note port and access your application, your running application? It's like one step back. Yeah. I don't think that's actually a step back. I would probably start from inside out. Right? So, I think it's better to first understand what

6:02 Networking within a Pod

6:07 a pod does and how the communication between multiple containers inside a pod would work. And then we can go how can two pods talk to each other. And then we can go to the point of how do we deploy a bunch of pods from a deployment. Right? Because that's again, it's another abstraction layer on top already. So I don't know how how I don't know how to start this. Should we just, like, look at the pod for a starting point? There is quite a lot on what you mentioned there. So let's let's So yeah, what you said there is we

6:45 could talk about the networking model with multiple containers in the single pod without ever reaching the network stack across the services first, That's your suggestion, okay. So let's modify our first pods back then, I'll add a second container, we'll deploy it to the cluster and then we can talk about what is actually here. So we'll call this NGINX one dot two and NGINX one dot one and that won't actually work, will it? Because the ports will try to bind on the same interface. So let's deploy something else. What's that? In this case? Yes, please. In this case, how do you

7:29 know that the container port is 80? Is it is it by default? I'm just yeah, I'm just really familiar with NGINX and I know that it runs on port 80 as does HTTPD, know, this is like the the standard non TLS HTTP port and maybe Philip can explain this slightly better than I can now. So if you run multiple containers in a single pod, they share the same namespace of networking space, which means that we cannot have two engine access running on port I believe, and we can confirm that just now actually, but if I try to

7:49 Understanding Pod Port Conflicts

8:01 deploy this, it will fail. Is that right, Philip? Yes. That's pretty right. So I think basically the way I look at this, and I'm no expert in networking at all, I just help myself by, you know, having like a bridge to understand this. Basically, I'm looking at a port as a computer. Right? It has one network interface, has one IP address, and so it shares the port namespace. Right? So any port inside this one computer can only be used once. Of course, that isn't true because you can have virtual interfaces. And then each virtual interface has its own

8:35 set of ports. Right? But for this specific example, it's just the port has one of those pod IPs. Right? And so any container you start inside shares the number of available ports. So you cannot use them twice. And if they want to talk to each other within that that port, they can talk to each other. So one container talking to another container inside the same port, they can talk to each other localhost and that port that you are listening on. So if you start nginx twice, you would have to have one of them listen on

9:09 a different port. Exactly. And we've just confirmed that. We can actually see here that our NGINX two pod is relatively happy here, but our NGINX one pod does keep adder in and that's because it cannot rebind that port number. So that means we have to, if we wanted to show how the networking works within a single pod, we need to run something else that doesn't listen on port 80. Any quick suggestions of an image that's I can throw in here? I'm not super familiar with the NGINX image, but it probably has an environment variable that

9:43 you can tell it to use different part now. Probably. I just don't know what it is. Well, so yeah. We would have to check out with the images documentation. I I just run MariaDB 10. I think that's the right tag. Yeah. It runs on it's the MySQL port, which is gonna be, I can't even remember, but it's not port 80. So let's put this in and we run our watch again. That should get healthy. That's the old one that I've heard so I'm not worried about that. And the second one just hasn't come up yet, so we'll

10:23 give that a moment. Yeah. We had a no, I've broken that one too. Oh yeah, MySQL. I I'm feeling miserably. So we had some good comments as well there at the same time. Let me see. So Costa said, TCO sector support, you are correct. And also use Redis. Yeah. That may have been easier. The reason the MariaDB slash MySQL one just failed there is that it actually can't run without some environment variables, so that was a very terrible choice in the image by myself. Does Redis need environment Yeah, also like a bit of an anti pattern, right? You shouldn't

10:57 Sidecar Pattern

10:58 run your NGINX and your database in the same pot. That's a bit of a Cut me some slack, fella. This is a demo. This isn't this isn't I'm not shipping it to production, I promise. But we should probably mention this to the viewers so they don't, you know, tune out because we're complete morons. Oh yeah, someone's just tuned in right there and went, they're doing what? No. It's closed. So, yeah, I wouldn't recommend that part and you're correct. Yeah, Redis I think is happy with any environment variable. So you can see now that this has worked. So let's talk about what

11:32 actually happened there. If we describe pod one seven which is our new one with Redis, We can see that we have two containers here running on a single pod. And what happens there is that they share the same networking space, they share the same port allocations, they can communicate over local host. Sorry. Anything we need to be able to add there. Does that even make sense to everyone what I've just said? Yes. Okay. I think it makes sense. Yeah. It does make sense. If engine x in this case, right, was a web application we had written and not

12:17 like this web server only, we could now talk to our Redis with local host and whatever the Redis port is. Yeah. But if you wanted this process in if the NGINX process was not NGINX but our own web application, it can now talk to Redis by connecting to local host and the Redis port. Yeah. And the benefits of that are that it doesn't go over your traditional kernel TCP network in the stack. Right? It's it's typically faster. There's no security risks, at least less security risks. Is that a that a fair Yeah. Well, if you this,

12:52 you're basically talking local host. Right? Those two processes will end up on the same node. So it's the same local host connection that you would have on if you were to do this on your single computer. If you had put those two containers into different pods, they may end up being scheduled to different nodes. And then you would actually have increased latency as a first step because you might actually end up talking through a real network on different machines And that adds latency, right? So for web applications, there sometimes is a use case where you would do

13:24 something like this because you want your cache to be very, very fast, right? And you put them right next to the actual process that uses the cache. Can, in certain applications, have benefits. It's kind of hard say with this And in this example, let's say they would be in different both containers would be in different pods, but they would be running in the same node? For instance, if I have only one node and I can be certain about that, they would not be able to communicate through localhost, or they would be? They would not. They would not be. If they are in

13:41 Networking Between Pods and the Need for Services

13:58 different pods, each pod has its own IP And if you want to Okay. Between pods Then they would have to know them. Have to go to the network for communication. Okay. Okay. So that covers networking within a pod using local hosts. You know, the only thing you really need to be aware of is port collisions. If you navigate that, there are use cases for using multiple containers in the same port. This in pods, this is generally what we call the sidecar pattern in Kubernetes land where we want to be able to add extra functionality to our

14:30 What are the 3 types of service?

14:30 applications without modifying our own code kind of. Yeah. Alright, so let's get back to then, I know you see the original question was networking across across pods and namespaces and all of our Kubernetes clusters and using services. Now there's three different types of services if I remember correctly. Do we wanna discuss what each of those are and the use cases for each? I think one thing I guess point out before we go there is Yeah. The service doesn't actually do the networking. Right? Any port can talk to any other port. The difficulty is just you don't know its

15:05 Service Role: Discovery and Load Balancing

15:10 IP address. Services So you wouldn't hard code it. Service discovery. They help you how to find out who to talk to. Right? Yeah. That is correct. The service concept or primitive within Kubernetes, right? I mean, service discovery, which is, you know, a pretty much a solved problem when you adopt Kubernetes and load balancing across the pods within that service. Right. On what service type you choose, then you also would get, for example, load balancing because the service has its service IP address. It announces the service IP address in DNS. And so when you try to talk to

15:47 this service, you can talk to a DNS name. It resolves to the service's IP address. And the service has endpoints which are all the pods that it can find via its selector labels. And this is how it can end up talking to these various pods. Okay. So this is like a big That was a nice explanation. To make this more understandable for everybody. I think it would be useful, like, for this demonstration to focus on the difference between cluster IP and node port, unless we want to, I mean. No. No. That makes sense. So To what

16:08 Kubernetes Service Types Overview

16:25 you might understand. Cluster IP is is the default service type. So we'll get one of those running. And node port is got some very specific use cases that, okay, I guess it's actually the four service tip. The third one would be a load balancer type, which is only supported in some environments and the fourth one would be a headless service, which actually handles traffic in a slightly unique way. But we're gonna disregard those and focus on cluster IP and node port and try and break that down for you. So let's expose. Oh, there's also there's also there's no port and host port

16:45 ClusterIP services

17:00 if you wanna make it really complicated. And then there is also I forgot the name, but there's a service type which does nothing but add an entry to the DNS, to the internal Kubernetes DNS. I think it's called external DNS or something like external name Yeah. It's a service type external or something, external DNS, something like this, or external name. Don't know how to up. Yeah. I don't think it's oh, the semantics aren't important, but you're right. Yeah. There is the ability to bring an external services and expose them as a Kubernetes service. Okay. So

17:38 Defining a ClusterIP Service

17:38 let's make a service available for our first deployment here, which has this label. Can the name be anything? Like in this case, when you named a service? It could be anything that is a DNS compatible name. And so you can't use dots, but you can use you know, alphanumeric and dashes. And it doesn't have to be connect in this case with the deployment. It just So it's connected to something called a selector, which is based on the labels. So you can see here what I'm telling that, I mean services are relatively simple as the definition.

18:09 Service Selectors and Labels

18:20 All we're saying here is we wanna make something available with this name NGINX one and it's gonna find any target which has a label called app with the value NGINX one. And we could Yeah. So I think the question, you're free to name the service anything you like as long as it is according to the Kubernetes naming convention. Right? But it probably makes sense to call it something that's related to your deployment so you keep track of which two things belong together. You know, if your deployment is called doc and the service is called cat,

18:57 that, you know, may not be the best idea. Exactly. Yeah. I think, you know, it's always valuable to remember that, well, Kubernetes is a computer and we'll do whatever is told that humans are usually working with this and we want to make it as simple as possible. Well, standard naming conventions do make a lot of sense but I'm gonna go against that now because I've already renamed it to anise one, so let's go with that. Alright, now we can get away with very little bit of config here and rely a lot on the defaults, so I'm just gonna apply

19:26 this, we'll see what we get and we'll try and understand what's actually happened here. So I've not set a service type in the spec, All I've done is configure the selector and tell it the port that we want the service to be available on. This is probably So On you go. Yeah. No. I wanted to drill more on the container port versus port On how is that the port that's the service and then the service forwards that to the container port and the container port could be something different or do they have to like, what is the relation between

19:57 those two ports or they don't have any relation? Yeah. Yeah. So the port will be the port number that the service IP is available on. You can then have that point to a different port within the container if you need. So like if you have an application that listens on a random port and you want to expose over a standard port, then you can configure that correctly and then node port brings in another variable to the mix as well that we cover when we do other node ports. I think that's right. Let's apply. So now if we run

20:31 Inspecting Service Endpoints

20:33 kubectl get services, you'll see here we have the annex one service that we created and then now gets a cluster IP because that's the default service type. And we can ignore external IP for now and it's exposed on the port that we told it to be available on. It just so happens to be the same port that NGINX is listening on, but that is most irrelevant right now. Another really viable command when working with services Kubernetes is to describe it and what you're looking for here every time is this endpoints and more often not if your service isn't

21:06 working within the cluster is because it has no endpoints and the number one reason at least in my experience here is if there are no endpoints on the service, you have your selector wrong. Meaning I cannot fetch any pods with that selector. A good way to confirm that that also works is to use a label selector when you do get pods. So we can run this command here and if that returns pods, then your endpoint is configured correctly. The endpoint in this case is the endpoint of the of the container like that refers to to the pod

21:40 that the containers run-in or? So when we apply the service to the cluster, the cluster will grab that selector. It will look up all of the pods. And if they're ready and available, they will be added to the endpoints list, which just means that they're available to handle any request to that service IP address. By default, it will just add all of them, but you have the readiness check to determine if it's actually ready. Right? So if you configure a readiness check-in your port, this is how you can control at what point your application is ready to

22:00 Readiness Probes and Service Endpoints

22:12 be added as an endpoint. Or because the readiness readiness check will run continuously along the lifetime of the pod, it would also remove it from the endpoints if at some point in the future your readiness check turns false again. A by default. The readiness check runs automatically, or that's something that will also be defined in the YAML in that case? No. In the pod, you have the ability to configure two health checks, the readiness check and the liveness probe. And the readiness one determines if it's inside the endpoints, if it's included in load balancing, basically.

22:50 And the other one determines if it's being it's going to be restarted according to whatever rules you put in there. And in that case, like, if I don't define the values, they are, by default, defined to certain numbers, to certain values? Or No. If you don't define it, then it's just included in the endpoints immediately as soon as Kubernetes has started the container. And then it doesn't basically determine if the process inside the container has had time to come up. For example, Java applications can take quite a bit of time to boot up in a lot of cases. Right? Yeah, couple

23:22 of weeks. So you might, may actually end up sending traffic to this process already before the process is ready to answer. Yeah. Yeah, maybe it makes sense to go into liveness and readiness problem, maybe we can do that after a little bit of the service stuff unless you wanna dive into it then let let me know. Yeah, said there is, you know, a % correct. Like if these exist, you can define when your application is actually handling traffic correctly or is ready to handle traffic and the services can add and remove them as needed to

23:56 make sure that you're not delivering, you know broken NGINX's to your customers and such. Yeah, great information. Okay. So we have two deployments, some pods, and a service that allows us to now communicate. So I guess, what do you think we should cover next? Will we talk about the DNS conventions for service discovery? Yeah. One thing about the selector, we mentioned that you have to set the selector, and if you don't get it right, then you usually end up having no endpoints and it doesn't work. Should we mention how you get it right? What labels you actually have to set where in

24:16 Labels in Deployments, ReplicaSets, and Pods

24:37 order for the selector to find your pods? Yes, it's more extensive. I found this super confusing because there's metadata labels everywhere. And I was like, do I put the metadata labels in the deployment or do they have to be under deployment spec templates spec metadata labels? That's one of my biggest frustrations with the the selectors on a deployment is that there's some replication and I don't understand why it's maybe not automated. But yeah, you wanna break that down then Philip? No, was a question. I'm not claiming I know everything. Alright. So hold on. Let me get a

25:19 comment on. So Costa has said, yeah, we should have a whole episode on live this already readiness approach. I I think you're right. There is a lot there. So maybe that's something that I'll get scheduled soon. Alright, Very cool. Yeah, when you define a deployment, so that, and much the same way that a service works out which pods or endpoints to load balance traffic over, a deployment has to understand, I don't want to go too deep in this because it's a bit of a segue, the deployment has to work out which replica sets are under its control, and

25:48 then the replica sets have to work out which pods are under its control, and this is labels all the way down. So what we have here in the deployment selector is say, all of replicate sets which have a label of app and the value of NGINX are under our control. And then we have a template on the pod spec which also adds labels of app and NGINX to each of the pods. And it's just like labels and all of these different resources that grip them all together in something like homogenous fashion to be queried against the control plane.

26:20 If I got anything wrong there, feel free to jump in and fix it. And in that case, like I mean, as a complete newbie looking at that, you would wonder at the beginning, why can't you use the name for that as a form of label? Do you have to define the name? Or what happens if I don't define the name and a random name is set? The labels have the benefit that you could have multiple of those and you can query for a combination also. Right? So there's some rules you could say, you can have like an app, engine x1,

26:53 like we have now, and you could have another label for example, for an environment for staging or prod. And then you could make sure that the staging service will only ever include staging pods by also querying for the environment. Okay? Yeah. That would be one way. It's there's also more advanced use for this. But I think what's important here is the reason why we can set those templates here inside the deployment spec is only because the deployment is a higher level abstraction already. Yep. And it has some things it does to the resources that it

27:30 controls, replica sets and pods eventually. Right? But if we were to use a naked pod, which you almost never do unless you want to understand this, then you would have to set the labels on the pod itself for the service to find it. Yeah. I mean, I try to avoid talking about replica sets as much as possible. And as people are learning Kubernetes, I don't think there's a lot of value initially to understand what their their role is. So maybe that's a rather I actually have a have a recruiting. If you if you apply for a job and I end up recruiting

28:00 NodePort services

28:04 you, I'll ask about this quite a lot because I think it's important to understand how these things work together. Because if it breaks and you have to figure out why, it's better to know. Like my question is usually how does a rolling update work? What happens inside the Kubernetes control plane when you change the image tag of your deployment? What does it do? I do think that it's ported, but as someone on their first month of Kubernetes, does that make a lot of sense to break it down? Oh, I don't know. Let's say we're conflicted on that one.

28:37 Do you want to go next, This was your question, and I don't want us to get bogged down by details and random things. I want to make No. I think I think this is great. I To be honest, there is also aspects that I wouldn't, like, think about it in a complex manner, like replicasets. For me, it's just like, oh, I want to have two of the same thing, I just use a replica set kind of style. Right? So I guess it's something you also discover through using it of, like, of the specifics of how they work and what might go

29:06 wrong or not. But what would be cool to maybe go into more detail is actually a lot of, like, examples when you look at basic deployment resources is they they show multiple port naming. They have, like, target port, port, container port, and and then also when you introduce node port, they have, like yeah, node port, they have a node port. Right? And I think that's then when I'm not too sure if people, like, also who have used it who have been using it over time know the exact connection or it's just something that people know

29:10 Service Port Configuration (`port`, `targetPort`)

29:42 and they don't really write about. So, that might be interesting to go into more detail. Okay. Service has I think services are a little bit overloaded. Right? They have multiple use cases. We already talked about the cluster IP ones, which gives you another IP address inside your cluster, basically, you can talk to. A way to find this IP address via DNS. And then also the load balancing, whenever you talk to this cluster IP address, it will forward the traffic to one of the ports that's behind it via this endpoint mechanic that we just discussed. Right? But other

30:17 deployment types sorry, service types may actually do something quite different. For example, the node port you mentioned, basically what node port does is instead of reserving an IP address, I think it reserves an IP address too, but that's out of the point here, is it also sets up kube proxy to start listening on the host, the worker, on that specific port. So now you can talk to the host's IP address. And then in case of the I sometimes get this wrong and correct me. Maybe Chad will correct me if I'm wrong. But basically, there's a node port and host

30:52 port. Node port would set up Kube proxy on any node in the cluster independently if the port is running on that node or not to listen on this port that you specify and set up IP tables magic so that when you talk to any node IP address and that port, the traffic will end up at your port. Okay? And host port does something similar except it only does this on the node that does actually have your pod running. Does that make sense? It just saves you a hop basically. Let's let's show this by example. I think that's going to make sense. So

31:00 NodePort Service Type

31:40 what I'm going to do is firstly, we're going to update this to be something more useful. So instead of MariaDB, what we're actually going to use is something from the open files project called node info, which I should call the right thing. And because this is going to expose as we request the HTTP server on that container, it's going to return information about the pod to answer the request and that's going to show us the load balancing. We'll expose that as a cluster IP and I'm also gonna expose it as a node port and then

32:12 we will take a look at how that actually functions and hopefully that answers a lot of the questions that we have. So we need to expose the port and it runs on eighty eighty I believe, so we should be okay running that side by side with engine X. That's already exposed as, oh it's not, engine X is exposed as annex one and we'll also have Anais node info as another service, gonna have the same selector running on a different port. And finally, we'll do this again, only this time, we'll add a type of node port,

32:53 same selector and we'll expose the node info. And well, I'm not gonna say any other fields right now, I'm just gonna leave that as as we'll take a look at what is created, but hopefully we'll to explain it and show how it works. I think what we'll probably have to look at is when do you use one or the other, right? They have different use cases and I think that's what really matters in the end. I mean in my opinion, that's a really, really simple question to answer. So I'm gonna throw out my simple approach and let you

33:07 Use Cases for Service Types

33:22 shoot that down. But the only time you should ever, ever, ever, ever, ever use a node port service is if you want to expose something outside of your cluster and it's not the best way to do it. It's a kind of a hacky quick way to do it because you don't have any ingress controlled or configured for your cluster. So yeah, node port is only there if you want a hacky quick expose us to the wild or the Internet kind of thing. Would you agree with that? Yeah, I would agree with that. Yeah. No. I if you

33:50 want to expose something outside of the cluster, the first thing you should look into is ingress. Right? However, there may be some edge cases where you have to go down to a lower level and then those node port host port services are useful. You'll if you ever end up setting up, for example, NGINX Ingress, if you deploy your own Ingress, then you will eventually have to touch on this, right, because you need a way to somehow get the traffic to the NGINX Ingress controller in the first place. That's also where this host port, node port

34:24 difference comes into play. So just clarifying in the in the ML resources that you defined, in those services where you didn't say node port, it's by default cluster IP? That is correct. If you emit it, the default by Kubernetes control plane or the defaulters is to set this to cluster IP. Okay. And the ports you just out of simplicity reason named them and the service the same as in the deployment? Yeah. So let's run over that again quickly then. So the first cluster IP I have, I have matched the name with the deployment that we want to expose and the selectors

35:03 also match up. This is the ideal approach. Right? Generally, this everything lines up, everything's the same, if anything differs you can spot it right away from the YAML, you understand what's going on. Something else that's important to note from all of these definitions that I've only ever configured port and the only port that is important is the one in the container that I want to expose over the service. You can get away nine times out of 10 without ever tweaking that and you'll be okay. The next one we have is the node info service, so the selector is the same and that

35:32 I want this deployment, oops, excuse me. I still want to target this deployment, but I'm exposing a different port numbers. I've just named the service to be slightly different. Okay here, but obviously looking at it as first glance, I'd go, oh, something's a little different about this. And then finally the note, sorry, and you go Philip. Could you expose both of them in the same service? Which is tricky. You can expose multiple ports in the same service. Yes. I guess And in this case, we could because they're inside the same pod. Right? So if you look at the first

35:50 Exposing Multiple Ports in a Service

36:06 one, we could have both of them exposed there. And because they're in the same pod, this works. But if they were in the different pods, then the selectors would be different and then we couldn't do this. Then we would need to use two services. Yes, you're correct. And right, yeah, we should show that as well. Okay. And then the last one is a node port. So we have a special name for that, we're using the same selector, and again, we're just targeting the one that we want to expose. So this node port is the exact

36:34 same only instead of a cluster IP, it's gonna, well you'll still get a cluster IP I think, but it's gonna also expose a high port number that is available in any node within your cluster and it will use the cube proxy to route that to a port regardless of the node it is on. And we won't see that working, but we can try and explain it just because that's a local cluster, there is only one node. Okay, so let me reapply this so we get the changes. Oh yeah. When you expose multiple ports like this, you

37:03 do need to provide a name to give it some form of uniqueness. Do you need in that case both if they have different labels, both labels or how how would it know which one to So when you call the service IP, you can specify a port number and I believe it will route you to the right one. We'll confirm that actually. I think I've maybe maybe just confused myself there. Okay. So let's take a look at our service definitions. So we have our first one which is here. So annex one cluster IP, we have an

37:36 IP address and we can see that two ports are available and we can query either one. So we can query on port 80 default and get the NGINX service, we can hit 8,080 and we'll get the node info service. We have our node info one, which is the same as the first one, but separate definition. And then we have our node port one here, so you can see we still get cluster IP, so we can still reference it within the cluster, but we can also see here with this colon that we have this high port number

38:03 of 30,202, which actually means I can query from outside of the cluster on any node IP on that port number and it will route me to one of the pods in that service. Can you try it out? Yes. I can. I was gonna say that's a lot of work. Let's just actually finally show it working. And I I know there's lots of comments coming in. Let me get back to that in a second once we've actually shown something here. So let's jump inside one of these pods. Let's get pods exec and two NGINX two because we haven't exposed us at all yet

38:29 Demonstrating ClusterIP Service Discovery & Load Balancing

38:41 and hopefully I've got bash. Yeah, okay. Do I have curl? Yes. So we're we could use the cluster IPs for all of this, but one of the nice things about Kubernetes is that we DNS based discovery, which means we can actually use a service name, but then the namespace with very little configuration. So what that means is I can just query and it is one, and you'll see I get the nginx response. I can also change the port and I get the node info response. Okay. Now I wanna change one more thing here to show the load balancing as well. So

39:20 I'm gonna modify the replicas on this deployment here. Let's just run four and then we'll go back in here. So we can have that on Port 80 as many times as we want and we get NGINX. We can head it as many times as we want on Port 8080. And you'll see the last part of the tuple, the naming convention here is the pod ID and then you can see we had load balanced across two different pods there, when we requested that service name. Does that make sense? We understand what's going on there. Okay. The one question was also about port and

40:04 target port. Maybe we should talk about this also a little bit. Yes. Let's let me demo the node port then we'll we'll tackle the target port as well then. Okay. And we're gonna do so let's try and get nodes, wait I get an IP address. Yes. Okay, so this is my IP address of my node, I think Docker for Mac is going to let me query that, we're about to find out and I'm gonna target on 30202, which is that node port, so this is me outside of the cluster, this is me on my local machine.

40:14 Attempting NodePort Demonstration

40:43 Of course that doesn't work, that was saying, docker for Mac does provide a DNS name. I have no idea if that's the right one. Should I use Linux? Anyone know how Docker for Mac works? Is there a way to SSH into the virtual machine that it starts? No, you cannot SSH into the virtual machine. There is a DNS name though, let me, let's just use the docs, right? I mean, don't know everything, I Google stuff more than I actually know stuff, so Docker for Mac DNS name node port. Let's see what the internet says. Well, I also don't know any of this,

41:22 I have KubeCuttle explain all the time in the background here. Yeah, exactly. There is a DNS name for Docker for Mac that allows you to Docker for Mac dot local host. Maybe I was close. Docker from Mac did actually resolve and the Docker from Mac. Okay, let's try that IP address. I don't think the node port works then with Docker for Mac, so I can't show you that. And I don't know if I have any clusters available. However, that would work, trust me. Right? I'm a very trustable person. The node port just means this, I think what happens is the

42:16 CNI implementation or cube proxy whatever one it is configures an IP table on all of the nodes that says listening on this port number, the 30202 and when the request comes in, it will forward it to some pod on your cluster somewhere. Unfortunately, don't think I can show you it working. Which leads us on to Philips thing now. Target ports. You wanna what one would you like to change, Philip? Well, I think we should actually change the second one because we have the second one we listen on eighty eighty in the actual process, right? Yeah. Which is

42:40 Detailed Explanation of `port` vs `targetPort`

42:54 beneficial because we would rather want to have all our ports listen on high level ports because it doesn't require root or fancy capability magic, right? There's like a whole discussion if unprivileged processes should be able to require low level ports. But by default, on Linux, they cannot. So anything that's not root, started by root, cannot bind to any port that's below ten twenty four, if I'm not mistaken. And so we would need to run our web server as root in order to bind to port 80, which is usually not encouraged. It's actually discouraged. I think that's the

43:32 word. The benefit here is that we can use a service and have the services port be 80 but have the target port be 8,080. And this way, we can still talk to our process by talking to some IP on port 80. But in the background, it's actually running under and listening on port 8,080 and can be run as an unprivileged user then. Yes. Let me try and Okay. Surmise that in one lane then. The reason we would use target port is when we want our service to be available on more traditional or privileged port numbers,

44:08 like we probably always want our web services available on four forty three or 80. However, the container port or the pod doesn't expose the service on that port. The chances are your pod is gonna be using something higher like eighty eighty or 3,000 or 4,000 or 3,006 etcetera. And instead, what we do is we say, make our service available on 80, however the pod is going to be listening on 8,080. Now we can now reapply this, and if we exec back into this pod, we can do curl and the service name here was, I know

44:46 it's node info. We had on port 80, you know, so it's just a default web port. It's been forwarded to the pod on port 8,080 using the target port definition and then gives us our response. That's when you would choose target port is when you wanna do a little bit of juggling to get privileged port numbers available on the service that aren't available on your pod. Okay. In that case, the target port has to match the pod port. Yes. And then that's when container port comes in and you can juggle things even more if you really, really, really want to. So

45:09 Named Ports

45:21 I think you mentioned this at the start. Yeah. When you're configuring your ports here is that you can actually expose this. I think it's just port, is my auto complete wrong or am I wrong? Okay. Maybe it is supposed to port. Correct me, Philip. What have I got wrong there? I thought you could specify container port and expose it as a different port here, but maybe I'm completely wrong. I I think the most useful part of this is you can name them and then address them with the name. You don't have to name here. Say name something, web for example. Then

46:06 when you reference it from somewhere else, you can reference it as the name. Yeah. That's a good point as well, actually. So you can see What is the benefit of that? You don't have to remember the port number that you possibly. Yeah. So here It refers the same. Right? It refers yeah. To the name port number. If we add a name wipe here and a name node info here, that means on our service definition instead of of referencing this. Can you put web there or is it just named like that? No. I thought you could name it.

46:50 Environment Variables for Service Discovery

46:53 No. Here you can. Oh, no. No. That's yeah. I'm I'm sorry. I'm being really silly. Yeah. This is the pod. This is the port we expose it on and then the name is the one that is looking up. Well, I think what you can do here with the name is Kubernetes will set environment variables automatically inside the process's runtime environment that expose certain information about service discovery. The two ways how you can use Kubernetes service discovery is DNS and those environment variables. And based on these names, it will have these environment variables that tell you how to

47:26 find that thing. But you it will be something like I don't don't you know, don't quote me on this, but it's something like There. Oh, yeah. You can see them there. Right? So it's a service name port four four three, And if you give them a name, they will probably show up there with that name also. All right. We had a comment from Noel who said try NodePort on localhost. Just why not? Docker for Mac makes it easier than even I thought it was supposed to be. So you can see Docker for Mac does actually

47:48 Successful NodePort Demonstration

48:01 handle the node port on my local networking. So there you go. Node port does work. Thank you, Noel. Okay. Let's see. Do we get any I think this is a very special case because that's like, you know, there's networking magic many many times now at this point already when you do this on Mac and on local host. What's I think what's important to remember is this. If you have actual for example, you start cloud VMs and you were to start Kubernetes by hand using kubeadm, that those VMs would probably have an IP address and minus

48:34 security groups or something like this from the cloud provider, you could talk to those IP addresses. Right? And if you say node port, some port, you can talk to this IP address under this port from outside the cluster, and the traffic will end up in your container. Right? Because now that you can do localhost and this port is just another layer of networking magic to somehow go from his local networking stack on the Mac into this Linux virtual machine and then inside there eventually to the container. Yes. Lots of magic going on, with Docker for Mac.

49:12 Alright. So we're kind of approaching the the end of the time that I have available at least here. So I I wanna just check back and make sure we actually explained more things than than raising more questions. I hope that services are a little bit more comprehendible now and if if you have any final questions, let's try and tackle them. I think that was great. Like, more of a hands on example than what you would get the documentation where it's kind of explained from one perspective on what the different components are. Are there any questions from the comments maybe

49:14 Summary and Q&A

49:50 that or anything? So we do have a few comments and not particularly questions, just mostly people telling me that I'm wrong, which I love. So, Kustis says thank you for host port, you don't know about that, he's gonna look it up. We also have another comment from Kustis who says that developers should or would use ingress or load balancer services most of the time. Yeah, you're right, I mean I would discourage node ports as much as possible. They're a temporary solution for clusters that don't have a proper ingress route yet. But they are they're hacking and

50:23 balancer. Load balancer is an edge case also. It's it's a leftover from previous days. Yes. Ingress is the new way, and it should always be the default. You set this, and I totally agree with this. And the default for services should be cluster IP. You should use services by default to expose a number of pods together within your cluster so you can talk to them more easily. You can find them and you can talk to them with a load balancing. If you want to expose outside of the cluster, the default should always be ingress. And then if you have a very specific

50:58 use case, there are some other more technical things that you then can look into like load balancer, like node port, host port, all those other things. Then we have another comment from Andreas, which I'm gonna try and shorten a little bit. But when I complained that I didn't know why we had to have the selector different from the template specs, selectors or labels within the deployment spec. Apparently that was, it didn't used to be enforced. So now if I were to try and apply that to the customer and they were different, I would complain. But

51:29 that's just a legacy thing that's kind of hung around unfortunately. And to say another comment from Noah just in remembrance in the past, So that's all covered and that's all our comments. I think we are all good. I'll just say thank you both joining me. Thank you for your questions. Thank you Philip for bringing all of that knowledge and helping us And I hope we didn't raise more questions than we answered. It's great. Thank you. Alright. Have a great day. Thank you again and I'll speak to both soon. Have a nice day. Bye. Bye bye.

Technologies featured

Meet the Cast

Weekly Cloud Native insights

Stay ahead in cloud native

Tutorials, deep dives, and curated events. No fluff.

Comments, transcript, and resources

More from Rawkode Live

View all 173 episodes
Kubernetes

More about Kubernetes

View all 172 videos