Ingress cannot resolve NodePort IP in GKE - kubernetes

I have an ingress defined as:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: foo-ingress
annotations:
kubernetes.io/ingress.global-static-ip-name: zaz-address
kubernetes.io/ingress.allow-http: "false"
ingress.gcp.kubernetes.io/pre-shared-cert: foo-bar-com
spec:
rules:
- host: foo.bar.com
http:
paths:
- path: /zaz/*
backend:
serviceName: zaz-service
servicePort: 8080
Then the service zap-service is a nodeport defined as:
apiVersion: v1
kind: Service
metadata:
name: zaz-service
namespace: default
spec:
clusterIP: 10.27.255.88
externalTrafficPolicy: Cluster
ports:
- nodePort: 32455
port: 8080
protocol: TCP
targetPort: 8080
selector:
app: zap
sessionAffinity: None
type: NodePort
The nodeport is successfully selecting the two pods behind it serving my service. I can see in the GKE services list that the nodeport has an IP that looks internal.
When I check in the same interface the ingress, it also looks all fine, but serving zero pods.
When I describe the ingress on the other hand I can see:
Rules:
Host Path Backends
---- ---- --------
foo.bar.com
/zaz/* zaz-service:8080 (<none>)
Which looks like the ingress is unable to resolve the service IP. What am I doing wrong here? I cannot access the service through the external domain name, I am getting an error 404.
How can I make the ingress translate the domain name zaz-service into the proper IP so it can redirect traffic there?

Seems like the wildcards in the path are not supported yet.
Any reason why not using just the following in your case?
spec:
rules:
- host: foo.bar.com
http:
paths:
- path: /zaz
backend:
serviceName: zaz-service
servicePort: 8080

My mistake was, as expected, not reading the documentation thoroughly.
The port stated in the Ingress path is not a "forwarding" mechanism but a "filtering" one. In my head it made sense that it would be redirecting http(s) traffic to port 8080, which is the one where the Service behind was listening to, and the Pod behind the service too.
Reality was that it would not route traffic which was not port 8080 to the service. To make it cleaner I changed the port in the Ingress from 8080 to 80 and in the Service the front-facing port from 8080 to 80 too.
Now all requests coming from the internet can reach the server successfully.

Related

Problem configuring websphere application server behind ingress

I am running websphere application server deployment and service (type LoadBalancer). The websphere admin console works fine at URL https://svcloadbalancerip:9043/ibm/console/logon.jsp
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
was-svc LoadBalancer x.x.x.x x.x.x.x 9080:30810/TCP,9443:30095/TCP,9043:31902/TCP,7777:32123/TCP,31199:30225/TCP,8880:31027/TCP,9100:30936/TCP,9403:32371/TCP 2d5h
But if i configure that websphere service behind ingress using ingress file like:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: nginx-ingress-check
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- http:
paths:
- path: /ibm/console/logon.jsp
backend:
serviceName: was-svc
servicePort: 9043
- path: /v1
backend:
serviceName: web
servicePort: 8080
The url https://ingressip//ibm/console/logon.jsp doesn't works.
I have tried the rewrite annotation too.
Can anyone help to just deploy the ibmcom/websphere-traditional docker image in kubernetes using deployment and service. With the service mapped behind the ingress and the websphere admin console should somehow be opened from ingress
There is a helm chart available from IBM team which has the ingress resource as well. In your code snippet, you are missing SSL related annotations as well.
https://hub.helm.sh/charts/ibm-charts/ibm-websphere-traditional
https://github.com/IBM/charts/tree/master/stable/ibm-websphere-traditional
I have added the Virtual Host configuration for admin console to work with port 443 in the following code sample.
Please Note: Exposing admin console on the ingress is not a good practice. Configuration should be done via wsadmin or by extending the base Dockerfile. Any changes done through the console will be lost when the container restarts.
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
name: websphere
spec:
type: NodePort
ports:
- name: admin
port: 9043
protocol: TCP
targetPort: 9043
nodePort: 30510
- name: app
port: 9443
protocol: TCP
targetPort: 9443
nodePort: 30511
selector:
run: websphere
status:
loadBalancer: {}
---
apiVersion: v1
kind: ConfigMap
metadata:
name: websphere-admin-vh
namespace: default
data:
ingress_vh.props: |+
#
# Header
#
ResourceType=VirtualHost
ImplementingResourceType=VirtualHost
ResourceId=Cell=!{cellName}:VirtualHost=admin_host
AttributeInfo=aliases(port,hostname)
#
#
#Properties
#
443=*
EnvironmentVariablesSection
#
#
#Environment Variables
cellName=DefaultCell01
---
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: websphere
name: websphere
spec:
containers:
- image: ibmcom/websphere-traditional
name: websphere
volumeMounts:
- name: admin-vh
mountPath: /etc/websphere/
ports:
- name: app
containerPort: 9443
- name: admin
containerPort: 9043
volumes:
- name: admin-vh
configMap:
name: websphere-admin-vh
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: nginx-ingress-check
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/secure-backends: "true"
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
spec:
rules:
- http:
paths:
- path: /ibm/console
backend:
serviceName: websphere
servicePort: 9043
Exposing both the adminhost and defaulthost via ingress isn't possible, or at least I've never figured out how to accomplish it. The crux of the issue is that ingress listens on port 80 or port 443 and forwards your request to the corresponding port on the container. Thus, the Host header of your request contains that port. I don't know enough about WAS channels/virtualhosts to understand how this works exactly, but in order for accessing WAS endpoints over any port other than the one listed for the endpoint in WAS config to work, the websphere-traditional image has to set a property to extract the port it should use for things like checking against virtualhost hostalias entries and issuing redirects from the Host header (com.ibm.ws.webcontainer.extractHostHeaderPort).
The problem becomes, when it uses that port, that port needs to be listed as a host alias for the virtual host in order for the traffic to be let through to the application. And since a combination of wildcard host and specific port can only be a host alias on one virtual host at a time, they were set up as host aliases on defaulthost so that web applications will work via ingress, but this makes it impossible to also access the admin console since that is served via a separate virtualhost which doesn't (and as far as I know can't) have the host alias entries set up to allow traffic with port 443 in its host header through. I haven't had to figure out how to get this working because kubectl port-forward has been sufficient to get at the admin console for the times I've needed to consult something, and you can't make changes anyway because they'll disappear when the pod restarts and a new one is started from the same (unchanged) image.

Ingress without ip address

I create a ingress to expose my internal service.
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: app-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: example.com
http:
paths:
- path: /app
backend:
serviceName: my-app
servicePort: 80
But when I try to get this ingress, it show it has not ip address.
NAME HOSTS ADDRESS PORTS AGE
app-ingress example.com 80 10h
The service show under below.
apiVersion: v1
kind: Service
metadata:
name: my-app
spec:
selector:
app: my-app
ports:
- name: my-app
nodePort: 32000
port: 3000
targetPort: 3000
type: NodePort
Note: I'm guessing because of the other question you asked that you are trying to create an ingress on a manually created cluster with kubeadm.
As described in the docs, in order for ingress to work, you need to install ingress controller first. An ingress object itself is merely a configuration slice for the installed ingress controller.
Nginx based controller is one of the most popular choice. Similarly to services, in order to get a single failover-enabled VIP for your ingress, you need to use MetalLB. Otherwise you can deploy ingress-nginx over a node port: see details here
Finally, servicePort in your ingress object should be 3000, same as port of your service.

How to get two ingress ports accessible for single service using NGINX kubernetes controller

We have one service which has two exposed ports- one is for server and second is for management. Kubernetes cluster have NGINX controller running. Is there any way to expose both the ports of service in Ingress YAML file?
Details:
Service server Port : 8081
Service Management Port: 8082
We tried with two "backends" in Ingress YAML file but it works only for default port which is 80 and fail for any other port.
ingress.yml file is as below:
kind: Ingress
apiVersion: extensions/v1beta1
metadata:
name: bw-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: my.host.net
http:
paths:
- path: "/controller/"
backend:
serviceName: bw-svc1
servicePort: 80
- path: "/actuator/"
backend:
serviceName: bw-svc2
servicePort: 5612
The indentation level of both paths is not equal in your config sample.
Other than that your config looks correct and should result in the following behavior:
All traffic coming to the cluster via my.host.net/controller will be sent to service bw-svc1:80
All traffic coming to the cluster via my.host.net/actuator will be sent to service bw-svc2:5612
If this is not what you'd like to achieve, could you please re-phrase your question?

How can I generate External IP when creating an ingress that uses nginx controller in kubernetes

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: helloworld-rules
spec:
rules:
- host: helloworld-v1.example.com
http:
paths:
- path: /
backend:
serviceName: helloworld-v1
servicePort: 80
- host: helloworld-v2.example.com
http:
paths:
- path: /
backend:
serviceName: helloworld-v2
servicePort: 80
I'm making kubernetes cluster and I will apply that cloudPlatform Isolated(not aws or google).
When creating an ingress for service I can choose host url but that is not exist anywhere(that address is not registrated something like DNS server) So I can't access that url. Visiting this IP just gives a 404.
how can I get or configure URL that can access external browser
:(...
It depends on how you configure your nginx controller.
You should have a Service configured which is the entry point when accessing from outside see the docs https://kubernetes.io/docs/concepts/services-networking/ingress/#what-is-ingress.
So basically you have a Service that points to the ingress controller and this will redirect the traffic to your pods based on Ingress Objects.
Ingress -> Services -> Pods
Since you don't run on aws or google You would have to use externalIp or NodePort and configure the service accordingly
kind: Service
apiVersion: v1
metadata:
name: ingress-nginx
namespace: ingress-nginx
labels:
app: ingress-nginx
spec:
selector:
app: ingress-nginx
ports:
- name: http
port: 80
targetPort: http
- name: https
port: 443
targetPort: http
externalIPs:
- 80.11.12.10
And DNS needs to be managed with whatever you have for your domains in order to resolve, or for locally testing you can just edit your /etc/hostnames
Basically in AWS or Google you just create a service with type: LoadBalancer and point your dns records to the balancer address (CNAME for aws and the IP for google)

Loadbalancing with reserved IPs in Google Container Engine

I want to host a website (simple nginx+php-fpm) on Google Container Engine. I built a replication controller that controls the nginx and php-fpm pod. I also built a service that can expose the site.
How do I link my service to a public (and reserved) IP Address so that the webserver sees the client IP addresses?
I tried creating an ingress. It provides the client IP through an extra http header. Unfortunately ingress does not support reserved IPs yet:
kind: Ingress
metadata:
name: example-ingress
spec:
rules:
- host: example.org
http:
paths:
- backend:
serviceName: example-web
servicePort: 80
path: /
I also tried creating a service with a reserved IP. This gives me a public IP address but I think the client IP is lost:
apiVersion: v1
kind: Service
metadata:
name: 'example-web'
spec:
selector:
app: example-web
ports:
- port: 80
targetPort: 80
loadBalancerIP: "10.10.10.10"
type: LoadBalancer
I would setup the HTTP Loadbalancer manually, but I didn't find a way to configure a cluster IP as a backend for the loadbalancer.
This seems like a very basic use case to me and stands in the way of using container engine in production. What am I missing? Where am I wrong?
As you are running in google-container-engine you could set up a Compute Engine HTTP Load Balancer for your static IP. The Target proxy will add X-Forwarded- headers for you.
Set up your kubernetes service with type NodePort and add a nodePort field. This way nodePort is accessible via kubernetes-proxy on every nodes IP address regardless of where the pod is running:
apiVersion: v1
kind: Service
metadata:
name: 'example-web'
spec:
selector:
app: example-web
ports:
- nodePort: 30080
port: 80
targetPort: 80
type: NodePort
Create a backend service with HTTP health check on port 30080 for your instance group (nodes).