This article has a marketing and buzzword oriented title. I know.

Let me introduce you to what I am going to speak with you here with better worlds: VPN, private, DNS, kubernetes, security.

I hope we all agree that VPN should be a must-have when you set up an infrastructure. It doesn’t matter what you are doing, how many people are working with you.

When you design a new system usually you need to expose to the public only some service over HTTP and HTTPS all the rest: Jenkins, monitoring tools, dashboards, log management should be locked-down and accessible just in a private network. An intranet.

An intranet is a private network accessible only to an organization’s staff. Often, a wide range of information and services are available on an organization’s internal intranet that is unavailable to the public, unlike the Internet.

All these concepts apply to “Cloud Native” ecosystem as well.

Kubernetes has a powerful dashboard and CTL that you can use to interact with the API. That API doesn’t need to be publicly exposed, and to use the CLI from your laptop, you should set up a VPN.

OpenVPN

Usually, I configure an OpenVPN using the image kylemanna/openvpn available on Docker Hub. It is straightforward to apply, and it offers a set of utilities around user creation and certification management.

apiVersion : v1 kind : Service metadata : name : openvpn namespace : openvpn labels : app : openvpn spec : ports : - name : openvpn nodePort : 1194 port : 1194 protocol : UDP targetPort : 1194 selector : app : openvpn type : NodePort --- apiVersion : apps/v1 kind : Deployment metadata : name : openvpn namespace : " openvpn" labels : app : openvpn spec : replicas : 1 strategy : type : Recreate selector : matchLabels : app : openvpn template : metadata : labels : app : openvpn spec : nodeSelector : role : vpn containers : - name : openvpn image : docker.io/kylemanna/openvpn command : [ " /etc/openvpn/setup/configure.sh" ] env : - name : VPN_HOSTNAME valueFrom : configMapKeyRef : name : vpn-hostname key : hostname - name : VPN_DNS valueFrom : configMapKeyRef : name : vpn-hostname key : dns ports : - containerPort : 1194 name : openvpn securityContext : capabilities : add : - NET_ADMIN volumeMounts : - mountPath : /etc/openvpn/setup name : openvpn readOnly : false - mountPath : /etc/openvpn/certs name : certs readOnly : false volumes : - name : openvpn configMap : name : openvpn defaultMode : 0755 - name : certs persistentVolumeClaim : claimName : openvpncerts

I put the persistentVolumeClaim to remember you to store in a persisted and safe place (and you should backup them too) the certificates used and generated by the VPN /etc/openvpn/certs .

I won’t write more about this topic; we are all excellent yaml developers!

How to create users, configuration and so on is a well knows topic that you can easily find in the OpenVPN’s documentation.

I don’t know if you realized that, but this VPN runs inside a Kubernetes Cluster, so well configurated allow us to reach pods via a private network and a bonus point also via kubedns to ping services, pods and all the other resources registered to it.

To do that OpenVPN server can be configured to push kubedns to the client:

dhcp-option DNS <kube-dns-ip>

Something with learned is that if you are using Linux the NetworkManager-OpenVPN plugin pushes the DNS correctly, but the OpenVPN cli tool doesn’t if you are using the last one you need to set it up in another way.

Tips: You can take the <kube-dns-ip> doing cat /etc/resolv.conf from inside a pod.

DNS

Push the KubeDNS or the DNS used by kubernetes is not enough to have a complete intranet. You should be able to set up a custom domain to have friendly or short URL.

You can take two different directions. KubeDNS can have static record configured, but some person is not happy to touch or customize too much the KubeDNS because Kubernetes itself use it and if you mess it up all it can be a problem.

A possible solution is to deploy another DNS like CoreDNS and configures it to resolve KubeDNS as a fallback. In this way, you will be free to register custom LTDs and records. Kubernetes is going to use KubeDNS as usual, and if you mess up CoreDNS, only a fraction of your system will blow out.

Naturally to resolve your custom domains from the VPN you need to push the CoreDNS ip and not the one used by Kubernetes.

If two DNSs are too much take the option one or from Kubernetes 1.10 you can use CoreDNS as kubernetes DNS so it is a bit more flexible and you can use only that one if you are brave enough.

I suggested CoreDNS because it supports records configuration via etcd. Here an example of Corefile:

. { errors etcd *.myinternal { stubzones path /skydns entrypoint http://etcd-1:2379,http://etcd-2:2379,http://etcd-3:2379 upstream /etc/resolv.conf } proxy . /etc/resolv.conf }

Running this configuration inside a pod automatically fallback to kubedns (that automatically fallback to the one configured to reach internet). Because of upstream point to resolv.conf that inside a pod contains kubedns.

Benefits

Resolve Kubernetes DNS record from your local environment is very comfortable to build a shared or dynamic development environment for you and your colleagues.

You can set up per-developer namespaces that they can use to deploy services reachable from the program that they are writing. Or you can deploy your application, and another person connected to the VPN will be able to use it.