'Kubernetes Ingress to External Service?

Say I have a service that isn't hosted on Kubernetes. I also have an ingress controller and cert-manager set up on my kubernetes cluster.

Because it's so much simpler and easy to use kubernetes ingress to control access to services, I wanted to have a kubernetes ingress that points to a non-kubernetes service.

For example, I have a service that's hosted at https://10.0.40.1:5678 (ssl required, but self signed certificate) and want to access at service.example.com.



Solution 1:[1]

So I got this working using ingress-nginx to proxy an managed external service over a non-standard port

apiVersion: v1
kind: Service
metadata:
  name: external-service-expose
  namespace: default
spec:
  type: ExternalName
  externalName: <external-service> # eg example.example.com
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: external-service-expose
  namespace: default
  annotations:
    nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" #important
spec:
  rules:
  - host: <some-host-on-your-side> # eg external-service.yourdomain.com
    http:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: external-service
            port:
              number: <port of external service> # eg 4589
  tls:
  - hosts:
    - external-service.yourdomain.com
    secretName: <tls secret for your domain>

of-course you need to make sure that the managed url is reachable from inside the cluster, a simple check can be done by launching a debug pod and doing

curl -v https://example.example.com:4589

Solution 2:[2]

If your external service has a dns entry configured on it, you can use kubernetes externalName service.

---
apiVersion: v1
kind: Service
metadata:
  name: my-service
  namespace: prod
spec:
  type: ExternalName
  externalName: myexternal.http.service.com
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: externalNameservice
  namespace: prod
spec:
  rules:
  - host: service.example.com
    http:
      paths:
      - backend:
          serviceName: my-service
          servicePort: 80
        path: /

In this way, kubernetes create cname record my-service pointing to myexternal.http.service.com

Solution 3:[3]

I just want to update @Moulick answer here according to Kubernetes version v1.21.1, as for ingress the configuration has changed a little bit. In my example I am using Let's Encrypt for my nginx controller:

apiVersion: v1
kind: Service
metadata:
  name: external-service
  namespace: default
spec:
  type: ExternalName
  externalName: <some-host-on-your-side> eg managed.yourdomain.com
  ports:
  - port: <port of external service> eg 4589

---
kind: Ingress
apiVersion: networking.k8s.io/v1
metadata:
  name: external-service
  namespace: default
  annotations:
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
    nginx.ingress.kubernetes.io/proxy-body-size: 100m
    nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" #important
spec:
  tls:
  - hosts:
    - <some-host-on-your-side> eg managed.yourdomain.com
    secretName: tls-external-service
  rules:
  - host: <some-host-on-your-side> eg managed.yourdomain.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: external-service
            port:
              number: <port of external service> eg 4589

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3 Ralph