Access service via custom HTTPS port using nginx-ingress - kubernetes

When using nginx-ingress in Kubernetes, how can I define a custom port which should be used for HTTPS, instead of 443? My configuration looks as follows:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/tls-acme: "true"
creationTimestamp: "2019-04-17T14:15:25Z"
generation: 3
name: foo
namespace: foo
resourceVersion: "1535141"
selfLink: /apis/extensions/v1beta1/namespaces/foo/ingresses/foo
uid: f1b4dae9-6072-1239-a12a-fa161aff25ae
spec:
rules:
- host: example.com
http:
paths:
- backend:
serviceName: foo
servicePort: 80
path: /
tls:
- hosts:
- example.com
secretName: foo-ingress-tls
status:
loadBalancer:
ingress:
- {}
Preferably, I would like to be able to access the service via HTTPS on both the default 443 port and an additional custom port.

Unfortunately in ingress-nginx it is impossible to listen to more than one HTTPS port. You can change HTTPS port number using --https-port command line argument, but there can only be one HTTPS port.

Related

K8S traffic to one service via two separate ingress (http + https)

So I have a bunch of services running in a cluster, all exposed via HTTP only ingress object, example:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
name: some-ingress
spec:
ingressClassName: nginx
rules:
- http:
paths:
- backend:
service:
name: some-svc
port:
number: 80
path: /some-svc(/|$)(.*)
pathType: Prefix
They are accessed by http://<CLUSTER_EXTERNAL_IP>/some-svc, and it works ofc.
Now I want to create an additional ingress object for every service which will force SSL connections and allow the use of a domain instead of an IP address.
The problem is that the newer SSL ingresses always return 404 while testing the connection.
The manifests are as follows:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: "some-ingress-ssl"
annotations:
ingress.kubernetes.io/ssl-redirect: "true"
ingress.kubernetes.io/app-root: "/some-svc"
spec:
tls:
- hosts:
- foobar.com
secretName: foobar-tls
rules:
- host: foobar.com
http:
paths:
- path: /some-svc(/|$)(.*)
pathType: Prefix
backend:
service:
name: some-svc
port:
number: 80
tests (foobar.com point to CLUSTER_EXTERNAL_IP):
> curl -I http://<CLUSTER_EXTERNAL_IP>/some-svc
HTTP/1.1 200 OK
> curl -I https://foobar.com/some-svc
HTTP/2 404
Is it possible to have both ingresses simultaneously? (one enforcing SSL, the other not)
If so what am I doing wrong here?
Figured out I was missing this annotation:
nginx.ingress.kubernetes.io/rewrite-target: /$2
in SSL ingress...
works like a charm now, maybe someone will find this usefull

im trying to set up a kubernetes service that points to an external api that is secured with tls so needs to keep the original host header

i'm trying to set up the following
external user calls https://service1.mycluster.com, my cluster calls https://service1.externalservice.com and then returns the response to the user
i'm doing this to leverage istio and kubernetes thats deployed in my cluster to provide centralised access to services but some of my legacy services can't be moved into the cluster
i believe i'm going to need a service with an externalName to represent the external service but unsure how to get it to resolve the tls and keep the hostname of service1.externalservice.com so the tls will pass
any ideas would be much appreciated thanks
Currently i have the following
service
apiVersion: v1
kind: Service
metadata:
annotations:
name: testservice1
spec:
externalName: https://service1.externalservice.com
internalTrafficPolicy: Cluster
ports:
- name: https
port: 443
protocol: TCP
targetPort: 443
sessionAffinity: None
type: ExternalName
ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
cert-manager.io/cluster-issuer: xxx
traefik.ingress.kubernetes.io/router.tls: "true"
name: test1
spec:
ingressClassName: xxx
rules:
- host: service1.mycluster.com
http:
paths:
- backend:
service:
name: testservice1
port:
number: 443
path: /
pathType: Prefix
tls:
- hosts:
- service1.mycluster.com
secretName: tls-test1-ingress

ingress can not get the default http backend

The ingress I config to run with the controller ingress-nginx.
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: app-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
tls:
- hosts:
- XXX.XX.com
secretName: app-tls
rules:
- host: XXX.XX.com
http:
paths:
- path: /my-api(/|$)(.*)
backend:
serviceName: app
servicePort: 80
---
apiVersion: v1
kind: Service
metadata:
name: my-api
spec:
selector:
app: my-api
ports:
- name: app
port: 3000
targetPort: 3000
I can run the api locally curl localIP:3000/testapi, but it can not run remotely.
# kubectl describe ingress app-ingress
Name: app-ingress
Namespace: default
Address: XX.XX.XX.XX
Default backend: default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
TLS:
app-tls terminates www.daichenchen.cn
Rules:
Host Path Backends
---- ---- --------
XXX.XX.com
/my-api(/|$)(.*) app:80 (<error: endpoints "app" not found>)
I already succeed install the ingress-nginx and all the pod work without error.
Your defined serviceName in Ingress rules and Service should be same.
Like this :
...
rules:
- host: XXX.XX.com
http:
paths:
- path: /my-api(/|$)(.*)
backend:
serviceName: app
servicePort: 80
apiVersion: v1
kind: Service
metadata:
name: app
spec:
selector:
app: my-api
ports:
- name: app
port: 3000
targetPort: 3000
If Ingress and the Service is in different namespace, you can also add the service name to the ingress rule. In this case you need to use dns name for service <service-name>.<namespace>.
For example:
rules:
- host: example.com
http:
paths:
- path: /my-api
backend:
serviceName: test-service.test-namespace
servicePort: 80
apiVersion: v1
kind: Service
metadata:
name: test-service
namespace: test-namespace
The way ingress controller finds out Endpoints of a service is it searches for a kubernetes service with the serviceName provided in the ingress resource in the namespace where you have created the ingress resource. If there is no kubernetes service with serviceName found you get endpoints not found.
The Endpoints of the service contains the IPs of pods behind the kubernetes service.
So in your case either the kubernetes service does not exist or it's in a different namespace than where ingress resource is created.
Some variant of nginx ingress controller does not support default backend and for this it's expected to have the error: endpoints "default-http-backend" not found
Another variant of nginx ingress controller supports default backend.
Double check which variant of nginx ingress controller you installed

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.

How to configure ingress to deploy services to subdomains without creating a new loadbalancer

I am new to Kubernetes and have an application deployed via GKE on mydomain.com and now want to add another service which should be available on api.mydomain.com without adding a new expensive load balancer. What should the new ingress file for api.mydomain look like? I read the documentation, but cannot figure out how to do this.
This is my first service running on mydomain.com:
kind: Service
apiVersion: v1
metadata:
name: app-service
spec:
selector:
app: app
ports:
- protocol: TCP
port: 80
targetPort: 80
type: NodePort
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: app-ingress
annotations:
kubernetes.io/ingress.global-static-ip-name: "ip"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
acme.cert-manager.io/http01-edit-in-place: "true"
kubernetes.io/tls-acme: "true"
spec:
rules:
- host: mydomain.com
http:
paths:
- backend:
serviceName: app-service
servicePort: 80
tls:
- hosts:
- mydomain.com
secretName: my-certs
I tried to use the same configuration for the subdomain api.mydomain.com, but this does not work.
kind: Service
apiVersion: v1
metadata:
name: api-service
spec:
selector:
app: api
ports:
- protocol: TCP
port: 80
targetPort: 80
type: NodePort
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: api-ingress
annotations:
kubernetes.io/ingress.global-static-ip-name: "ip"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
acme.cert-manager.io/http01-edit-in-place: "true"
kubernetes.io/tls-acme: "true"
spec:
rules:
- host: api.mydomain.com
http:
paths:
- backend:
serviceName: api-service
servicePort: 80
tls:
- hosts:
- api.mydomain.com
secretName: my-certs-api
Maybe I'm approaching the problem in the wrong way, I'm new in GKE, any suggestions?
Try "nginx" ingress.class . The config shall be like the following (I have removed tls part out it).
Nginx Ingress controller
is quite easy and functional.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: double-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
# nginx.ingress.kubernetes.io/rewrite-target: /$2 ### you can use it to route different paths to different services under the same host
spec:
rules:
- host: mydomain.com
http:
paths:
- path: /
# - path: /doc/common(/|$)(.*) ### if you are using rewrite
backend:
serviceName: app-service
servicePort: 80
- host: api.mydomain.com
http:
paths:
- path: /
backend:
serviceName: api-service
servicePort: 80
tls:
- hosts:
- api.mydomain.com
secretName: my-certs-api
Hope that helps!
You would generally use a different Ingress Controller than the default ingress-gce. ingress-nginx is very common and easy to get started with, but there are many options so I recommend you research them and pick which one matches your use case best.
As per my understanding you are trying to create one HTTP load balancer with one public IP address for two different domains.
It's doable using standard GKE ingress controller GCE L7 at least for HTTP protocol (see example below).
Please also find documentation page about using multiple SSL certificates with GCE L7 ingress.
Example:
( mydomain.com is replaced with example.com, because... an answer body cannot contain it.)
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: app-ingress
spec:
rules:
- host: example.com
http:
paths:
- backend:
serviceName: app-service
servicePort: 80
- host: api.example.com
http:
paths:
- backend:
serviceName: api-service
servicePort: 80
Applying this yaml to GKE cluster results creating one HTTP load-balancer with the following Host and path rules:
http://example.com:80/* -> app-service:80 (if app-service health-check passed)
http://example.com:80/* -> default-backend:80 (return 404) (if app-service heath-check fails and default-backend health-check passed)
http://api.example.com:80/* -> api-service:80 (if app-service health-check passed)
http://api.example.com:80/* -> default-backend:80 (return 404) (if api-service heath-check fails and default-backend health-check passed)
http://lb.ip.address:80 -> default-backend:80 (return 404) (if default-backend health-check passed)
HTTP LB returns 502 if all backends' health-checks are failed.