Kubernetes Ingress to External Service? - kubernetes

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.

You can do it by manual creation of Service and Endpoint objects for your external server.
Objects will looks like that:
apiVersion: v1
kind: Service
metadata:
name: external-ip
spec:
ports:
- name: app
port: 80
protocol: TCP
targetPort: 5678
clusterIP: None
type: ClusterIP
---
apiVersion: v1
kind: Endpoints
metadata:
name: external-ip
subsets:
- addresses:
- ip: 10.0.40.1
ports:
- name: app
port: 5678
protocol: TCP
Then, you can create an Ingress object which will point to Service external-ip with port 80:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: external-service
spec:
rules:
- host: service.example.com
http:
paths:
- backend:
serviceName: external-ip
servicePort: 80
path: /

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

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

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

Related

Ingress redirect to a localhost tcp service

I have a local website.
The website was created by a docker-compose and it is listening on a localhost port 3000.
When I try:
curl 127.0.0.1:3000
I can see the response.
What I did:
From my domain provider I edited the DNS to point to my server, then I changed nginx-ingress:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: virtual-host-ingress
namespace: ingress-basic
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/use-regex: "true"
cert-manager.io/cluster-issuer: "letsencrypt-pp"
spec:
tls:
- hosts:
- nextformulainvesting.com
secretName: ***
rules:
- host: "nextformulainvesting.com"
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: e-frontend-saleor
port:
number: 80
and I created the service:
apiVersion: v1
kind: Service
metadata:
name: e-frontend-saleor
spec:
ports:
- protocol: TCP
port: 80
targetPort: 3000
But with the service or without the service I receive the error 503 Service Temporarily Unavailable.
How can I use nginx-ingress to point to my local TCP service?
To clarify the issue I am posting a community wiki answer.
The answer that helped to resolve this issue is available at this link. Based on that - the clue of the case is to create manually a Service and an Endpoint objects for external server.
After that one can create an Ingress object that will point to Service external-ip with adequate port .
Here are the examples of objects provided in similar question.
Service and an Endpoint objects:
apiVersion: v1
kind: Service
metadata:
name: external-ip
spec:
ports:
- name: app
port: 80
protocol: TCP
targetPort: 5678
clusterIP: None
type: ClusterIP
---
apiVersion: v1
kind: Endpoints
metadata:
name: external-ip
subsets:
- addresses:
- ip: 10.0.40.1
ports:
- name: app
port: 5678
protocol: TCP
Ingress object:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: external-service
spec:
rules:
- host: service.example.com
http:
paths:
- backend:
serviceName: external-ip
servicePort: 80
path: /
See also this reference.
Your service that you have created is for forwarding the traffic to deployments
As your service is running out side of Kubernetes cluster you should be using the Endpoint in this case
apiVersion: v1
kind: Endpoints
metadata:
name: my-service
subsets:
- addresses:
- IP: <External IP>
ports:
- port: 3000
and you can use this Endpoint to ingress so that it will route the traffic.
Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: virtual-host-ingress
namespace: ingress-basic
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/use-regex: "true"
cert-manager.io/cluster-issuer: "letsencrypt-pp"
spec:
tls:
- hosts:
- nextformulainvesting.com
secretName: ***
rules:
- host: "nextformulainvesting.com"
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: my-service
port:
number: 3000

Get client IP address in GRPC service behind Kubernetes nginx ingress

I am still struggling with kubernetes.
I have issue with preserving request IP address on service for logging purposes. Logging is done with GRPC server. This code is working outside kubernetes as intended.
Service is defined similar to this.
apiVersion: v1
kind: Service
metadata:
annotations: {}
labels:
name: grpc-api
name: grpc-api
namespace: myns
spec:
ports:
- name: ext-5000
port: 5000
targetPort: 5000
- name: grpc-5050
port: 5050
targetPort: 5050
selector:
name: grpc-api
type: ClusterIP
Ingress is:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
certmanager.k8s.io/cluster-issuer: letsencrypt-myns
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/backend-protocol: GRPC
nginx.ingress.kubernetes.io/service-upstream: "true"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
labels:
name: api-grpc
name: api-grpc
namespace: myns
spec:
rules:
- host: api.example.org
http:
paths:
- backend:
serviceName: grpc-api
servicePort: 5000
path: /
tls:
- hosts:
- api.example.org
secretName: grpc-api-ingress-cert
Documentation mentions externalTrafficPolicy: Local in service, where type is LoadBalancer. Would it be enough to add parameter above to ClusterIP type service or do I have to change it to something else?
Thank you in advance.

kubernetes ingress-nginx gives 502 error and the address field is empty

I am setting up kubernetes on a AWS environment using kubeadm. I have setup ingress-nginx to access the service on port 443. I have checked the service configurations which look good. I am receiving 502 bad gateway and also the Address field in ingress is empty.
Front end service
apiVersion: v1
kind: Service
metadata:
labels:
name: voyager-configurator-webapp
name: voyager-configurator-webapp
spec:
ports:
-
port: 443
targetPort: 443
selector:
component: app
name: voyager-configurator-webapp
type: ClusterIP
Ingress yml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nginx-ingress-resource
spec:
tls:
- hosts:
- kubernetes-test.xyz.com
secretName: default-server-secret
rules:
- host: kubernetes-test.xyz.com
http:
paths:
- backend:
serviceName: voyager-configurator-webapp
servicePort: 443
NAME CLASS HOSTS ADDRESS PORTS AGE
nginx-ingress-resource <none> kubernetes-test.xyz.com 80, 443 45m
What could be the issue here ? Any help will be appreciated.
Make sure that your service is created in proper namespace - if not add namespace field in service definition. It is not good approach to add label called name with the same name as your service, instead you can use different one to avoid mistake and configurations problem.
Read more about selectors and labels: labels-selectors.
Your frontend service should look like that:
piVersion: v1
kind: Service
name: voyager-configurator-webapp
metadata:
labels:
component: app
appservice: your-example-app
spec:
ports:
- protocol: TCP
port: 443
targetPort: 443
selector:
component: app
app: your-example-app
type: ClusterIP
Your ingress should look like this:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nginx-ingress-resource
annotations:
kubernetes.io/ingress.class: nginx
spec:
tls:
- hosts:
- kubernetes-test.xyz.com
secretName: default-server-secret
rules:
- host: kubernetes-test.xyz.com
http:
paths:
- path: /
backend:
serviceName: voyager-configurator-webapp
servicePort: 443
You have to define path to backend to with Ingress should send traffic.
Remember that is good to follow some examples and instructions during setup to avoid problems and waste of time during debugging.
Take a look: nginx-ingress-502-bad-gateway, aws-kubernetes-ingress-nginx.

externally access the application using hostname/subdomain in ingress resource

Need to access the application from external using Ingress hostname/sub-domain for the application that is specified in the below code. eg. test-app.dev-cluster-poc.company.domain.
cat app-ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
namespace: ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
name: app-ingress
spec:
rules:
- host: test-app.dev-cluster-poc.company.domain
http:
paths:
- backend:
serviceName: appsvc1
servicePort: 80
path: /app1
- backend:
serviceName: appsvc2
servicePort: 80
path: /app2
While troubleshooting using steps in the url, I found that there is no ADDRESS in the "kubectl get ingress" output. expecting an ip address like below.
but, I am seeing like below, 3rd column is empty.
what are the necessary configuration required to externally access the application like registering the hostname(test-app.dev-cluster-poc.company.domain) or adding A-record or running any dns service in the kubernetes cluster.
what is causing the ADDRESS column empty in "kubectl get ingress" command.
[EDIT]
apiVersion: v1
kind: Service
metadata:
name: appsvc1
namespace: ingress
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: app1
Nginx controller service like below.
cat nginx-ingress-controller-service.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-ingress
namespace: ingress
spec:
type: NodePort
ports:
- port: 80
nodePort: 30000
name: http
- port: 18080
nodePort: 32000
name: http-mgmt
selector:
app: nginx-ingress-lb
1.you can deploy an ingress deployment
2.expose your ingress deployment through port 80
kubectl expose deploy your-deployment-name --port 80
source
3.you can add ingressClassName in your deploy
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-ingress
namespace: ingress
spec:
ingressClassName: nginx
ingress configuration sample

Forward to ExternalName with traefik in kubernetes as the documenation suggests

Following the Official Guide I got to the section onForwarding to ExtternalNames. Where it says:
When specifying an ExternalName, Træfik will forward requests to the given host accordingly
which points to the docs from kubernetes services without selectors
Which led me to create a service
kind: Service
apiVersion: v1
metadata:
name: my-service
namespace: prod
spec:
type: ExternalName
externalName: my.database.example.com
Of which Traefik happily ignores when I point to it:
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: my-service
namespace: kube-system
spec:
rules:
- host: my-service.example.com
http:
paths:
- path: /
backend:
serviceName: my-service
servicePort: 4080
I have also tried as an endpoint.
---
kind: Service
apiVersion: v1
metadata:
name: my-service
namespace: kube-system
spec:
ports:
- protocol: TCP
port: 80
targetPort: 4080
---
kind: Endpoints
apiVersion: v1
metadata:
name: my-service
subsets:
- addresses:
- ip: 10.0.0.3
ports:
- port: 4080
Does anyone know how to get traefik to point to an externalname as the documentation suggests?
As I see, you missed at least one line in your Ingress object - traefik.frontend.passHostHeader: "false".
Also, you need to create an Ingress object in a same Namespace with your Service.
So, your Ingress should be like:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: my-service
namespace: prod
annotations:
traefik.frontend.passHostHeader: "false"
spec:
rules:
- host: my-service.example.com
http:
paths:
- path: /
backend:
serviceName: my-service
servicePort: 4080
And service:
kind: Service
apiVersion: v1
metadata:
name: my-service
namespace: prod
spec:
type: ExternalName
ports:
- name: app-port
port: 4080
externalName: my.database.example.com