Kubernetes: exposing NGINX Ingress with Let's Encrypt - nginx

I'm trying to set up the LetsEncrypt SSL ceritficate using cert manager.
I have successfully deployed Cert Manager by Helm and stuck at configuring ingress.yaml.
$ sudo kubectl create --edit -f https://raw.githubusercontent.com/jetstack/cert-manager/master/docs/tutorials/quick-start/example/ingress.yaml
I've got this:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
name: kuard
namespace: default
spec:
rules:
- host: example.example.com
http:
paths:
- backend:
serviceName: kuard
servicePort: 80
path: /
tls:
- hosts:
- example.example.com
secretName: quickstart-example-tls
So I just replaced hosts from example.com to my external IP and got this:
A copy of your changes has been stored to "/tmp/kubectl-edit-qx3kw.yaml"
The Ingress "kuard" is invalid: spec.rules[0].host: Invalid value: must be a DNS name, not an IP address
Is there any way to set it up using just my external IP? I have't yet chosen the domain name for my app and want to use just plain IP for demoing and playing around.

No. You cannot use an IP address for the Ingress. To use an IP address, you'd need to configure it to point to your worker nodes and create a NodePort Service, which will allow you to browse to http://IP:NODEPORT.

Related

nginx cannot access domain

the load balancer and ingress controller are working fine.
I install Nginx deployment and Nginx service, then expose Nginx deployment to port 80
#kubectl describe ing minimal-ingress
- Name: minimal-ingress
- Namespace: default
- Address:
- Default backend: default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
- Rules:
- Host Path Backends
- ---- ---- --------
- mywebsite.com
- / nginx-deployment:80 (10.52.2.38:80,10.52.2.39:80)
- Annotations: nginx.ingress.kubernetes.io/rewrite-target: /
- Events: <none>
it's working fine when I access my Nginx through my deployment IP address:
> #curl 10.52.2.38
I accessed through the command line and browser it's working fine, with or without specifying port 80.
just 10.52.2.38 or 10.52.2.39
but when I try to access use my host domain I showing
#curl mywebsite.com
curl: (7) Failed to connect to mywebsite.com port 80: No route to host
I am also cannot do curl to localhost or IP localhost 127.0.0.1
it is only working on my IP pods
I flush my iptables and disable ufw
I add my domain to /etc/hosts and put my loadbalancer IP there
but still not working.
thank you, I am kubernetes K3S user.
Finally, I got the answer to my problem.
what are you need to add is ingressClassName:nginx
so basically it would look like this
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-ingress
namespace: ingress
spec:
ingressClassName: nginx
good luck everyone

Kubeadm Kubernetes cluster cannot map External IP address to domain name using ingress

I am trying to setup a Kubernetes cluster using Kubeadm in GCE. I was able to access the deployment using a Nodeport service from the external IP. I am trying to set up an ingress that maps to a domain name but was not able to do it. So far what I have done:
Created a baremetal nginx ingress controller (I am using kubeadm)
Created a Nodeport service on the deployment (was able to connect it from the outside of the cluster)
Created an ingress resource using the configuration below:
and the command kubectl describe ingress my-ingress returns
my-ingress <none> sample.com 10.160.15.210 80, 443 32h which is the internal IP
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
annotations:
ingressClassName: nginx
spec:
tls:
- hosts:
- sample.com
secretName: sample-tls
rules:
- host: sample.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: sample # the nodeport service name of the deployment
port:
number: 8000 # nodeport target port
I cannot access the deployment using sample.com . I double checked the DNS name, using the command dig sample.com and it returns the external IP.
If you created your cluster using GCP, you should have used GCE-GKE installation instructions.
Important difference is that GCE-GKE installation creates LoadBalancer instead of NodePort

Kubernetes Nginx Ingress partial ssl termination

I'd like to split incoming traffic in Kubernetes Nginx in the following way:
Client --> Nginx --> {Service A, Service B}
The problem I am facing is Service A is an internal service and does not support HTTPS therefore SSL should be terminated for Service A. On the other hand, Service B is an external service (hosted on example.com) and only works over HTTPS.
I cannot manage to get this work easily with Kubernetes Nginx. Here is what I have come with:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-proxy
annotations:
nginx.ingress.kubernetes.io/backend-protocol: HTTPS
nginx.ingress.kubernetes.io/upstream-vhost: example.com
spec:
tls:
- hosts:
- proxy.com
secretName: secret
rules:
- host: proxy.com
http:
paths:
- path: /api/v1/endpoint
backend:
serviceName: service-a
servicePort: 8080
- path: /
backend:
serviceName: service-b
servicePort: 443
kind: Service
apiVersion: v1
metadata:
name: service-b
namespace: default
spec:
type: ExternalName
externalName: service-b.external
ports:
- port: 443
I have got a route for service-b.external:443 to point to example.com.
This solution only works if service-b is over HTTPS, but in my case, I cannot change to HTTPS for this service because of some other internal dependencies.
My problem is the backend-protocol annotation works for the whole kind and I cannot define it per path.
P.S: I am using AWS provider
Following the suggested solution and question from comments.
Yes, like mentioned below it is possible to have two ingress items. In your case
only one should have backend-protocol in it.
According to nginx ingress documentation:
Basic usage - host based routingĀ¶
ingress-nginx can be used for many use cases, inside various cloud provider and supports a lot of configurations. In this section you can find a common usage scenario where a single load balancer powered by ingress-nginx will route traffic to 2 different HTTP backend services based on the host name.
First of all follow the instructions to install ingress-nginx. Then imagine that you need to expose 2 HTTP services already installed: myServiceA, myServiceB. Let's say that you want to expose the first at myServiceA.foo.org and the second at myServiceB.foo.org. One possible solution is to create two ingress resources:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: ingress-myservicea
annotations:
# use the shared ingress-nginx
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: myservicea.foo.org
http:
paths:
- path: /
backend:
serviceName: myservicea
servicePort: 80
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: ingress-myserviceb
annotations:
# use the shared ingress-nginx
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: myserviceb.foo.org
http:
paths:
- path: /
backend:
serviceName: myserviceb
servicePort: 80
When you apply this yaml, 2 ingress resources will be created managed by the ingress-nginx instance. Nginx is configured to automatically discover all ingress with the kubernetes.io/ingress.class: "nginx" annotation. Please note that the ingress resource should be placed inside the same namespace of the backend resource.
On many cloud providers ingress-nginx will also create the corresponding Load Balancer resource. All you have to do is get the external IP and add a DNS A record inside your DNS provider that point myServiceA.foo.org and myServiceB.foo.org to the nginx external IP. Get the external IP by running:
kubectl get services -n ingress-nginx
It is also possible to have separate nginx classes as mentioned here.

kubernetes ingress controller with cluster ip service and default nginx not working as expected

There is a kubernetes baremetal cluster which has 7 nodes.
Installed is helm and added a helm repo added
ingress-nginx https://kubernetes.github.io/ingress-nginx
In my lan i created a dns A record which is resolvable in my lan.
What works:
https://matthewpalmer.net/kubernetes-app-developer/articles/kubernetes-ingress-guide-nginx-example.html
I am able to access the apple and the banana location on the dns A record mentioned before.
When i deploy a default nginx image with a service with port 80 and of type cluster-ip the following nginx-ingress resource does not work
kubectl run nginx --image=nginx ; kubectl exposed pod nginx --port=80
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-test
annotations:
ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: kubernetes.somename.lan
http:
paths:
- path: /test
pathType: Prefix
backend:
serviceName: nginx
servicePort: 80
I am seeing in the logs that the file is being deployed in the nginx-ingress image, not seeing anything strange in comparison to the apple and banana ingress entry. Only difference i can come up with is that ingress controller and nginx image are bot using port 80
So what i need is that when i access http://somelan.lan/test i will end up at the placeholder of the nginx server (which is accessible by nginx service )
Question:
How can i access nginx on my A dns record under the path /test
Thank you in advancee
The provided apple / banana example was working because the pod is path insensitive. It does not react to path changes (ignores paths). While for nginx it is exactly opposite.
The blog has a mistake with annotation and its missing the nginx prefix. This is the one that you used:
ingress.kubernetes.io/rewrite-target
And this is the correct one as per docs:
nginx.ingress.kubernetes.io/rewrite-target
Ok, after research i found out how to solve this.
Hope this helps anyone
https://www.reddit.com/r/kubernetes/comments/j2neuf/nginxingress_path_routing/
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-precious
annotations:
nginx.org/rewrites: "serviceName=nginx-ingress rewrite=/;"
spec:
rules:
- host: kubernetes.somelan.lan
http:
paths:
- path: /test1
backend:
serviceName: nginx-ingress
servicePort: 80

nginx ingress controller forward source ip

I have setup an ingress for an application but want to whitelist my ip address. So I created this Ingress:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
cert-manager.io/cluster-issuer: letsencrypt
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/whitelist-source-range: ${MY_IP}/32
name: ${INGRESS_NAME}
spec:
rules:
- host: ${DNS_NAME}
http:
paths:
- backend:
serviceName: ${SVC_NAME}
servicePort: ${SVC_PORT}
tls:
- hosts:
- ${DNS_NAME}
secretName: tls-secret
But when I try to access it I get a 403 forbidden and in the nginx logging I see a client ip but that is from one of the cluster nodes and not my home ip.
I also created a configmap with this configuration:
data:
use-forwarded-headers: "true"
In the nginx.conf in the container I can see that has been correctly passed on/ configured, but I still get a 403 forbidden with still only the client ip from cluster node.
I am running on an AKS cluster and the nginx ingress controller is behind an Azure loadbalancer. The nginx ingress controller svc is exposed as type loadbalancer and locks in on the nodeport opened by the svc.
Do I need to configure something else within Nginx?
If you've installed nginx-ingress with the Helm chart, you can simply configure your values.yaml file with controller.service.externalTrafficPolicy: Local, which I believe will apply to all of your Services. Otherwise, you can configure specific Services with service.spec.externalTrafficPolicy: Local to achieve the same effect on those specific Services.
Here are some resources to further your understanding:
k8s docs - Preserving the client source IP
k8s docs - Using Source IP
It sounds like you have your Nginx Ingress Controller behind a NodePort (or LoadBalancer) Service, or rather behind a kube-proxy. Generally to get your controller to see the raw connecting IP you will need to deploy it using a hostNetwork port so it listens directly to incoming traffic.

Resources