Developing for Kubernetes involves more than just building and deploying containers. This course will cover how to manage communication both inside and outside of your Kubernetes cluster. You will learn how to organize your pods with namespaces, map IP addresses to a group of pods, and how to control communication with your pods using network policies.
If you have any comments or feedback, feel free to reach out to us at: support@cloudacademy.com.
Learning Objectives
- Create and use namespaces
- Connect to your pods using services
- Define and enforce network policies
Intended Audience
- Engineers who want to deploy applications on a Kubernetes cluster
- People who want to get GCP certified (eg: Professional Cloud Developer)
Prerequisites
- Basic understanding of Kubernetes
- Experience building and deploying containers
Now that you understand namespaces, let's talk about Cluster networking. Say I have a containerized web server running. I want users to be able to connect to it and start making requests. Every pod in a Cluster is automatically assigned an IP address. So in theory, I could just direct traffic to a pod via its IP. However, there are a couple of problems. First, pods are constantly being created and destroyed. That means the IP address of my web server could be constantly changing and the address that works today might not work tomorrow. It might not even work in an hour.
So if I were to try to create a DNS record, I'm going to need to update it. Probably a lot. And because of DNS caching, users might still have connection issues. The second problem is that with something like a web server, I usually don't want just one pod. I will probably want many, in fact, ideally I want the number of pods to scale up and down to keep up with user demand.
So how am I going to direct users to a constantly shifting pool of IP addresses? Now this is what a Kubernetes service takes care of. A service defines a set of pods and sets a policy by which to access them. Services handle discovery and routing between pods. You can think of them as being similar to an internal LoadBalancer. They map a single IP address to a group of pods. Now by service, I do not mean microservice. A Kubernetes service acts like a LoadBalancer and makes it easy to connect to the pods you were interested in.
Now there are five different types of services. The first one is called ClusterIP. Now this will map an internal private IP to a group of pods. This does support multiple pods, but your pods can only be accessed internally. That means from other pods in the same Cluster. Now this is useful for when you want to prevent external access. And this is also the default service type.
The second service type is called Headless. Now Headless we'll map a public IP to a single pod. This only supports one pod, but your pod can be accessed externally that you would choose this. If you just need to expose a single pod to the outside, or, if you were going to build some other sort of service discovery mechanism outside of Kubernetes, the third service type is called Nodeport. Nodeport will map the IPs of your pods to the corresponding nodes. So unlike Headless, this will support multiple pods and your pods can be accessed externally. However, in order to make it externally accessible, you're going to need to expose the IP address of the worker node it's running on this isn't very secure. So, this service is usually something you would use to build upon and not use it directly to expose your pods to the internet.
The fourth service type is called LoadBalancer This uses one of your cloud providers LoadBalancer to map an IP address to your pods. This does support multiple pods and your pods can be accessed externally. And this is generally the more secure way to publicly share access to a group of pods.
The fifth and final type of surface is called ExternalName. Now this service will map to a DNS record, not a group of pods. So, if you want a service to point to something outside of your Cluster, this can be useful. You'll often use this for things like migration purposes, like say if you removing pods from one Cluster to another.
So the two most commonly used services are the ClusterIP and LoadBalancer. The other three tend to have more limited use cases. With LoadBalancer, you're mapping a public IP to a group of pods, and often you will have a DNS entry associated with that IP. So you can always just connect to the DNS entry and know that you will be sent to one of the correct pods as pods are created and destroyed.
The LoadBalancer Service will keep track of everything and make sure all connections around in successfully ClusterIP works similarly, but only for internal access. It automatically creates and updates internal DNS records. When you create a ClusterIP Service, it will create a DNS entry of the form service-name.namespace.svc.cluster.local. So if you have a service called database running in the production namespace, you could access it by connecting to database.production.svc.cluster.local. Any pod can find the service as long as you know, the service name and the namespace.
You also can you shorten forms of the internal DNS name as well. So if a pod wants to connect to a service in the same namespace, it can just point to service name and Kubernetes will automatically expand to fill in the rest. If I wanted to connect to a service named database running in the same namespace as my pod, I could just connect to database.
So I think it's time for another quick demo. This time, I'm going to show you how to create the two main types of services, LoadBalancer, and ClusterIP. Now I'm going to continue using the same Cluster from the last demo. It still has the two namespaces and we see that the hello world app is still running in each namespace. So first I'm going to create a LoadBalancer service for the app running in demo namespace one.
Now you can see this command will create a service of type LoadBalancer. It's going to map the service to run on port 80 of the external IP, and it's going to create the service in demo namespace-1. Okay the service has been created. I'm going to need to wait a little while for the service to be assigned an external IP address. Now that it has been assigned an external IP, I should be able to verify that the service works by connecting to it with the curl command. And look, it works.
I can connect to the hello world app and get a response. Now, I currently just have one pod running under the service, but I could easily have 10 or a 100, however many I needed Next I'll show you how to create a ClusterIP Service. Now the command looks very similar to the previous one, except here I'm specifying a different type of ClusterIP, and this one is going to exist in demo namespace-2. Now the service has been successfully created. You'll notice that no external IP has been assigned. Recall that a ClusterIP service only accepts connections from inside the Cluster. So it's not going to have an external IP.
Now this makes it a little bit more difficult to test. I can't just run a curl command for my local machine. If I tried to connect to the ClusterIP, it's not going to work the commands just going to hang and eventually time out. So in order for me to verify that the service is working, I need to try to connect from a pod inside the Cluster.
Now, luckily I can do this by getting access to a shell. So let me get the full pod name in demo namespace-2, and now I'll use this command to connect to the pod shell. So now I should be able to run the curl command and successfully connect to the ClusterIP Service. So let's see, I need to copy the IP address again.
Alright, I need to install curl since that is an automatically installed in this container. All right, now it should work. The ClusterIP Service is working as well. So you can see that creating a service is really pretty simple. Now I would encourage you to try playing around with the commands and to try different things. Once you're done experimenting, we'll move on to our next topic.
Daniel began his career as a Software Engineer, focusing mostly on web and mobile development. After twenty years of dealing with insufficient training and fragmented documentation, he decided to use his extensive experience to help the next generation of engineers.
Daniel has spent his most recent years designing and running technical classes for both Amazon and Microsoft. Today at Cloud Academy, he is working on building out an extensive Google Cloud training library.
When he isn’t working or tinkering in his home lab, Daniel enjoys BBQing, target shooting, and watching classic movies.