2 min read

Proxying External Services Using Kubernetes Services

There are various reasons why setting up external service proxying from a Kubernetes cluster becomes essential. For example:

  • Managing a hybrid deployment where certain services operate within a Kubernetes cluster, while others remain on-premises.
  • Handling services with specific requirements, such as object storage or databases, that need to stay outside the cluster.
  • Dealing with a service situated in a different data center than the Kubernetes cluster.
  • Undertaking significant restructuring or refactoring within the Kubernetes cluster, aiming to minimize downtime and establish a seamless traffic redirection during migration.

On this occasion, I have an external service, called code-server, which I had previously deployed on my blog here.

Setup Code Server: VS Code in the browser
Run VS Code on any machine anywhere and access it in the browser. Requirements See requirements for minimum specs, as well as instructions on how to set up a Google VM on which you can install code-server. TL;DR: Linux machine with WebSockets enabled, 1 GB RAM, and 2 vCPUs

I intend to proxy/expose it using a Kubernetes service.

Proxy to external services with Kubernetes Service

Let’s start by creating a default ClusterIP Service:

cat<<EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
  name: rj-codeserver-service
spec:
  ports:
  - port: 8080
    targetPort: 8080
  type: ClusterIP
EOF

Now,  since we’re creating a Service without selectors, no Endpoint is being created for us so we need to create an Endpoint manually and provide an IP address of the external service/application that we want to proxy the requests to.

cat<<EOF | kubectl apply -f -
apiVersion: v1
kind: Endpoints
metadata:
  name: rj-codeserver-service  # Must be equal to Service name for automatic mapping
subsets:
- addresses:
  - ip: 13.212.177.111  # IP address of your external service
  ports:
  - port: 8080  # Listen Port of your external service
EOF

Next, let’s create an Ingress resource in order to enable traffic routing to the newly created Service. If the backend service only accepts HTTPS traffic and using NGINX, in addition to updating the destination port accordingly we will need to add nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" annotation to the Ingress resource definition.

cat<<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt
    nginx.ingress.kubernetes.io/rewrite-target: /
  name: rj-codeserver-ingress
spec:
  ingressClassName: nginx
  rules:
  - host: code.rjhaikal.my.id
    http:
      paths:
      - backend:
          service:
            name: rj-codeserver-service
            port:
              number: 8080
        path: /
        pathType: Prefix
  tls:
  - hosts:
    - 'code.rjhaikal.my.id'
    secretName: code-rjhaikal-secret
EOF

The Flow would look something like this:

And it's done😎.  Now go to https://code.rjhaikal.my.id