Kubernetes: DNS Proxy With Services

When building an application it is common that you’ll need to interact with external services to complete your business goals. When working within a Kubernetes cluster you may be enjoying using internal service routing to have one of your services communicate with another one of your services. If you want to use the Kubernetes DNS server to mask external services so they look like internal services then you’re in luck — it is possible! This article will go through how to use the Kubernetes DNS Server to mask external services to look like internal services.

Architecture Diagram Of GCP GKE With DNS Service Proxy

If you haven’t gone through or even read the first part of this series you might be lost, have questions where the code is, or what was done previously. Remember this assumes you’re using GCP and GKE. I will always provide the code and how to test the code is working as intended.

Why Proxy Your Services

There are many reasons you may want to use your Kubernetes DNS server to mask external services. One example is around changing endpoints. You may know that a service endpoint will change and rather than have your developers changing the endpoint in code we can have the developers point to an easy to use internal service endpoint no matter what is really happening.

Now you can change your external service endpoint at any time through Kubernetes YAML configuration files rather than going into your application code.

Create An External Name Proxy

To create an External Name Proxy is super simple. Most of the work we need to do is in the Kubernetes yaml Files. In this case, we will create a new yaml file as you see below.

apiVersion: v1
kind: Service # a way for the outside world to reach the Pods
metadata:
# the name of our external Service
name: external-service
spec:
# Service ports
ports:
- name: http
port: 80
targetPort: 8080
protocol: TCP
# Points to external name
type: ExternalName
externalName: www.jonbcampos.com # the external url
selector:
app: kubernetes-series

This configuration file creates a new Service of type ExternalName and points the external name to the url of our choosing.

Now with our external service configured we just need to call to the external service in our application code.

router.get('/foreign', function (req, res, next) {
const url = 'http://external-service.default/some_path/';
http.get(url, response => {
let data = '';
response.on('data', chunk => {
data += chunk;
});
response.on('end', () => {
res.status(200).json(JSON.parse(data));
});
}).on('error', err => {
throw err;
});
});

See Our External Name Proxy In Action

I’ve setup an experiment for you so that it is easy for you to see this in action. As I’ve done previously you can run a startup script to setup your Kubernetes Cluster in Google Cloud and deploy your application code.

$ git clone https://github.com/jonbcampos/kubernetes-series.git
$ cd ~/kubernetes-series/external-communication/scripts
$ sh startup.sh
$ sh deploy.sh
$ sh check-endpoint.sh service

Once your service is available you’ll be able you can hit the /foreign endpoint to see the results of the call. Depending on your cluster’s IP Address this would be http://[your cluster IP Address]/foreign.

Note: If you run the code you’ll get back an error as jonbcampos.com is hosted via Bluehost and therefore I don’t have direct IP Address access. You can always go change this value to whatever value works for your test.

With this test complete you are done! You can now use the Kubernetes DNS server (via kube-proxy) to call an external service just like it was an internal service.

Teardown

Before you leave make sure to cleanup your project so you aren’t charged for the VMs that you’re using to run your cluster. Return to the Cloud Shell and run the teardown script to cleanup your project. This will delete your cluster and the containers that we’ve built.

$ cd ~/kubernetes-series/external-communication/scripts
$ sh teardown.sh


Jonathan Campos is an avid developer and fan of learning new things. I believe that we should always keep learning and growing and failing. I am always a supporter of the development community and always willing to help. So if you have questions or comments on this story please ad them below. Connect with me on LinkedIn or Twitter and mention this story.