Networking in Kubernetes
Tags: tutorial, kubernetes, devops, cloud
Published: 2021-01-18 12:09:17

When working with Kubernetes we have different microservices running in different containers. Now, these different containers might be part of the same pod or present in different pods. Very often these microservices need to interact with each other. This is where the concept of Networking comes into place.

We'll be taking a look at Networking in two situations in this article:
1. Pod Internal
2. Between Different Pods

We have already learned a bit about what a Kubernetes service is in a [previous article](https://dev.to/rinkiyakedad/learning-to-use-kubernetes-1l6g). To give you a brief recap, services in K8s gave us a stable IP address that doesn't change all the time and they also can be configured to allow access from the outside world which is not possible by default.

In this article, I'm going to assume that microservice A is making a request to microservice B. If microservice B was running locally on port 5000 the code in microservice A would look something like this:
```
const response = await axios.get(`http://localhost:5000/something/`);
```
> Note the above example is in JavaScript but the concepts discussed will be true regardless of the language and framework you use.

But since we aren't running the microservices locally let us modify the code to use an environment variable:
```
const response = await axios.get(`http://${process.env.SOME_ADDRESS}/something/`);
```

We will now be having a look at what values to use for this environment variable depending on different cases.

## Pod Internal
Let's say that the two different containers are running in the same pod. The change we have to make in this case is fairly simple. 

For pod internal communication, K8s allows us to send a request to the `localhost` address. So you would simply use `localhost` as a value for the environment variable `SOME_ADDRESS`. Yes, it is that easy!

## Between Different Pods
When an app running in one pod has to make a request to another app in another pod the situation gets a bit trickier. There are three different values we can use for the `SOME_ADDRESS` environment variable in this case. Let's have a look at them one by one.

### Using ClusterIP
If we run
```
kubectl get services
```
we will be able to see all the services currently running in our K8s cluster. In the output of this command, there would be a column titled `ClusterIP`. This would show you the IP Address which you can use to reach that service from **inside** the cluster. 

Since pods are inside the cluster, they would have no problem using this IP Address. So we can simply use the IP address of the service we want to reach as the value of the `SOME_ADDRESS` environment variable.

But manually finding the address each time can be a bit cumbersome so let's have a look at a better way of doing so.

## Using Automatically Generated Environment Variables

There are many reasons to love Kubernetes. One of them is that it gives us automatically generated environment variables (which we can directly use in our code) that have info about all the services running in our cluster.

The pattern for these generated variables is based on the name of the service. So if your service has a name `some-service` the generated environment variable for that would be `SOME_SERVICE_SERVICE_HOST`.
 
Basically, you would take your service name, make it all caps, replace '-' with '_' and add '_SERVICE_HOST' in the end. So the code snippet above would now look like this:

```
const response = await axios.get(`http://${process.env.SOME_SERVICE_SERVICE_HOST}/something/`);
```

K8s is so awesome, isn't it?!

It gives you one more way :P

### Using CoreDNS

K8s clusters by default come with a built-in service called [CoreDNS](https://kubernetes.io/docs/tasks/administer-cluster/coredns/). It is a Domain Name Service, which helps with creating domain names. Here we're talking about **cluster internal** domain names. This means these can't be used outside the cluster but are perfect for inter pod communication.

CoreDNS creates domain names like this:
`service name` + `.` + `namespace the service is a part of`

By default, our deployments and services get assigned to the `default` namespace unless we specify otherwise. So the value for our environment variable, in this case, would be: `some-service.default`. 

<br/>

And this is it! You should now be able to facilitate communication between different microservices successfully regardless of whether they are in the same pod or not. 

Thanks for reading! :) 

If you have any feedback for me or just want to talk feel free to connect with me on [Twitter](https://twitter.com/RinkiyaKeDad). I'll be more than happy to hear from you! :D