Kubernetes routing to specific pod in function of a param in url - kubernetes

The need I have just looks like this stuff :
apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
name: http
spec:
serviceName: "nginx-set"
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: gcr.io/google_containers/nginx-slim:0.8
ports:
- containerPort: 80
name: http
----
apiVersion: v1
kind: Service
metadata:
name: nginx-set
labels:
app: nginx
spec:
ports:
- port: 80
name: http
clusterIP: None
selector:
app: nginx
Here is the interesting part :
apiVersion: voyager.appscode.com/v1beta1
kind: Ingress
metadata:
name: test-ingress
namespace: default
spec:
rules:
- host: appscode.example.com
http:
paths:
- path: '/testPath'
backend:
hostNames:
- web-0
serviceName: nginx-set #! There is no extra service. This
servicePort: '80' # is the Statefulset's Headless Service
I'm able to target a specific pod because of setting the hostName in function of the url.
Now I'd like to know if it's possible in kubernetes to create a rule like that
apiVersion: voyager.appscode.com/v1beta1
kind: Ingress
metadata:
name: test-ingress
namespace: default
spec:
rules:
- host: appscode.example.com
http:
paths:
- path: '/connect/(\d+)'
backend:
hostNames:
- web-(result of regex match with \d+)
serviceName: nginx-set #! There is no extra service. This
servicePort: '80' # is the Statefulset's Headless Service
or if I have to wrote a rule for each pod ?

Sorry that isn't possible, the best solution is to create multiple paths, each one referencing one pod:
apiVersion: voyager.appscode.com/v1beta1
kind: Ingress
metadata:
name: test-ingress
namespace: default
spec:
rules:
- host: appscode.example.com
http:
paths:
- path: '/connect/0'
backend:
hostNames:
- web-0
serviceName: nginx-set
servicePort: '80'
- path: '/connect/1'
backend:
hostNames:
- web-1
serviceName: nginx-set
servicePort: '80'

Related

ingress get the 503 feedback

I want to config the ingress to work with my domain name.
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: app-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
tls:
- hosts:
- example.com
secretName: app-tls
rules:
- host: example.com
http:
paths:
- path: /my-api1(/|$)(.*)
backend:
serviceName: app1
servicePort: 80
- path: /my-api2
backend:
serviceName: app2
servicePort: 80
---
apiVersion: v1
kind: Service
metadata:
name: my-api
spec:
selector:
app: my-api
ports:
- name: app1
port: 3000
targetPort: 80
- name: app2
port: 4000
targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: user-api
spec:
selector:
matchLabels:
app: user-api
template:
metadata:
labels:
app: user-api
spec:
hostNetwork: true
dnsPolicy: ClusterFirstWithHostNet
containers:
- name: app1
image: XXX
ports:
- name: app1
containerPort: 3000
- name: app2
image: XXX
ports:
- name: app2
containerPort: 4000
I can reach the app1 service by serverIP:3000(example. 172.16.111.211:3000/my-api1). But remotely it always return the 503 status code(curl https://example.com/my-api1).
# kubectl describe ingress app-ingress
Name: app-ingress
Namespace: default
Address: serverIP
Default backend: default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
TLS:
app-tls terminates example.com
Rules:
Host Path Backends
---- ---- --------
example.com
/my-api1(/|$)(.*) app1:80 (<error: endpoints "app1" not found>)
/my-api2 app2:80 (<error: endpoints "app2" not found>)
First thing is your service name is not matching, you have created a service with name my-api but in ingress you have referred it as app1 and app2 which is not available.
Second error is selector label between your deployment and service are not matching. Deployment created with label user-api but in service selector is mentioned as my-api.
If you need 80 port for both the application then you have to create two different services and refer that in your ingress.
Below should work for your requirement.
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: app-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
tls:
- hosts:
- example.com
secretName: app-tls
rules:
- host: example.com
http:
paths:
- path: /my-api1(/|$)(.*)
backend:
serviceName: app1
servicePort: 80
- path: /my-api2
backend:
serviceName: app2
servicePort: 80
---
apiVersion: v1
kind: Service
metadata:
name: app1
spec:
selector:
app: user-api
ports:
- name: app1
port: 3000
targetPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: app2
spec:
selector:
app: user-api
ports:
- name: app2
port: 4000
targetPort: 80
----
apiVersion: apps/v1
kind: Deployment
metadata:
name: user-api
spec:
selector:
matchLabels:
app: user-api
template:
metadata:
labels:
app: user-api
spec:
hostNetwork: true
dnsPolicy: ClusterFirstWithHostNet
containers:
- name: app1
image: XXX
ports:
- name: app1
containerPort: 3000
- name: app2
image: XXX
ports:
- name: app2
containerPort: 4000
You made a mistake on port and targetPort.
It should be:
apiVersion: v1
kind: Service
metadata:
name: my-api
spec:
selector:
app: my-api
ports:
- name: app1
port: 3000
targetPort: 3000
- name: app2
port: 4000
targetPort: 4000
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: app-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
tls:
- hosts:
- example.com
secretName: app-tls
rules:
- host: example.com
http:
paths:
- path: /my-api1(/|$)(.*)
backend:
serviceName: my-api
servicePort: app1
- path: /my-api2
backend:
serviceName: my-api
servicePort: app2
port is for exposing service port
targetPort is targeting a pod exposed port

Error in implementing WebSocket in Kubernetes

We are trying to implement WebSocket in Kubernetes by following steps given in GCP document "https://cloud.google.com/kubernetes-engine/docs/concepts/ingress#support_for_websocket" & "https://cloud.google.com/kubernetes-engine/docs/how-to/configure-backend-service" . but we are getting "Error during WebSocket handshake: Unexpected response code: 502”.
Error Message : “WebSocket connection to 'wss://..../backend-channeladaptor-web/socket.io/?EIO=3&transport=websocket' failed: Error during WebSocket handshake: Unexpected response code: 502”.
I have also attached Files created for gke implementation:
Backend-channeladaptor-web.yaml
Deployment content
Service content
Backendconfig content
Converse-ingress.yaml (It has details of other services as well you can ignore that except backend-channeladaptor-web).
Converse-ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: converse-ingress
annotations:
kubernetes.io/ingress.global-static-ip-name: $Static-Ip-Name
kubernetes.io/ingress.allow-http: "false"
spec:
tls:
- secretName: $SSL-certificate
rules:
- host: $HostName
http:
paths:
- path: /*
backend:
serviceName: frontend-chat-client
servicePort: 3040
- path: /socket-io/*
backend:
serviceName: backend-channeladaptor-engineerportal
servicePort: 11009
- path: /login/*
backend:
serviceName: frontend-engineeringportal
servicePort: 3021
- path: /frontend-engineeringportal/*
backend:
serviceName: frontend-engineeringportal
servicePort: 3021
- path: /backend-channeladaptor-web/*
backend:
serviceName: backend-channeladaptor-web
servicePort: 11006
Backend-channeladaptor-web.yaml
apiVersion: cloud.google.com/v1beta1
kind: BackendConfig
metadata:
name: backend-channeladaptor-web-backendconfig
spec:
timeoutSec: 3600
connectionDraining:
drainingTimeoutSec: 3600
---
apiVersion: v1
kind: Service
metadata:
name: backend-channeladaptor-web
annotations:
beta.cloud.google.com/backend-config: '{"ports": {"8081":"backend-channeladaptor-web-backendconfig"}}'
spec:
type: NodePort
ports:
- port: 8081
targetPort: 11006
protocol: TCP
nodePort: 30078
name: http
selector:
app: backend-channeladaptor-web
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: backend-channeladaptor-web
spec:
selector:
matchLabels:
app: backend-channeladaptor-web
replicas: 1
template:
metadata:
labels:
app: backend-channeladaptor-web
spec:
containers:
- image: gcr.io/acn-careful-granite-240620/backend-channeladaptor-web:0.2
name: backend-channeladaptor-web
ports:
- name: http
containerPort: 11006
hostPort: 11006
env:
- name: NODE_ENV
value: dev
I expect the response status code 101 but getting 502 Bad Gateway
It looks like your ingress has the URI /backend-channeladaptor-web/* pointed to the Service backend-channeladaptor-web and is expecting the Service to be listening in 11006. However, the NodePort configuration is listening in 8081.
The confusion might come from the targetPort directive, pointing to 11006 in the actual backend (the Deployment).
This is causing 502's, meaning that althought you're reaching an intermediary (the load balancer in your case), it is unable to reach the backend (the Deployment, served by the NodePort Service).
You can change the ingress definition to point to 8081 instead, matching the current NodePort configuration.

Cannot create Ingress for Prometheus

I would like to create an entry for Prometheus.
I have nodePort service deployed like this :
---
apiVersion: v1
kind: Service
metadata:
name: prometheus
namespace: monitoring
labels:
app: prometheus
spec:
type: NodePort
ports:
- port: 9090
targetPort: 9090
nodePort: 31190
protocol: TCP
selector:
app: prometheus
And my Ingress is :
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: prometheus-ingress
namespace: monitoring
annotations:
ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: prometheus.example.com
http:
paths:
- path: /
backend:
serviceName: prometheus
servicePort: 9090
Can you explain me why my ingress didn't work ?
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: prometheus-ingress
namespace: monitoring
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
rules:
- http:
paths:
- pathType: Prefix
path: /prometheus(/|$)(.*)
backend:
service:
name: prometheus
port:
number: 9090

default backend - 404 returned from nginx-controller when dns is used

a bit of background is that I have setup an Azure Kubernetes Service cluster and deployed a basic .Net Core api as a deployment object. I then deployed a nodeport service to expose the api and then deployed a nginx-controller and an ingress object to configure it. I use the IP of the ingress-controller to route the request and that works eg.http://1.2.3.4/hello-world-one/api/values.
But when I replace the Ip with the generated dns, somehow the path is ignored and I get the default backend - 404 returned from the nginx controller. The expected behaviour is that the dns will resolve then the path "api/values" will be sent to my service.
Can anyone help me with this?
Thanks in advance.
My deployment, service and ingress configs are below.
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: test-deployment
labels:
app: test
spec:
replicas: 1
selector:
matchLabels:
app: test
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
template:
metadata:
labels:
app: test
spec:
containers:
- name: test-service
image: <my-repo>.azurecr.io/testservice
imagePullPolicy: Always
ports:
- name: tcp
containerPort: 80
imagePullSecrets:
- name: regsecret
---
apiVersion: v1
kind: Service
metadata:
name: frontend
spec:
type: NodePort
selector:
app: test
ports:
- name: http
port: 32768
targetPort: 80
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: hello-world-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/ssl-redirect: "false"
nginx.ingress.kubernetes.io/rewrite-target: /
kubernetes.io/ingress.global-static-ip-name: dev-pip-usw-qa-aks
kubernetes.io/ingress.class: addon-http-application-routing
spec:
rules:
- host: hello-world-ingress.be543d4af69d4c7ca489.westus.aksapp.io
- http:
paths:
- path: /
backend:
serviceName: frontend
servicePort: http
- path: /hello-world-one
backend:
serviceName: frontend
servicePort: http
- path: /hello-world-two
backend:
serviceName: frontend
servicePort: http
pretty sure rules should look like this:
rules:
- host: hello-world-ingress.be543d4af69d4c7ca489.westus.aksapp.io
http:
paths:
- path: /
backend:
serviceName: frontend
servicePort: http
- path: /hello-world-one
backend:
serviceName: frontend
servicePort: http
- path: /hello-world-two
backend:
serviceName: frontend
servicePort: http
reading: https://kubernetes.io/docs/concepts/services-networking/ingress/#types-of-ingress

Expose multiple apps in gcloud kubernetes cluster

I have 2 apps running on gcloud kubernetes cluster and exposed via services. I followed steps from https://cloud.google.com/kubernetes-engine/docs/tutorials/http-balancer, for serving multiple applications on load balancer.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: fanout-ingress
spec:
rules:
- http:
paths:
- path: /
backend:
serviceName: nginx
servicePort: 80
- path: /app1
backend:
serviceName: app1server
servicePort: 8080
- path: /app2
backend:
serviceName: app2server
servicePort: 8080
services looks like this :
apiVersion: v1
kind: Service
metadata:
name: app1server
spec:
ports:
- name: app1-port
port: 8080
type: NodePort
----
apiVersion: v1
kind: Service
metadata:
name: app1server
spec:
ports:
- name: app2-port
port: 8080
type: NodePort
But I am getting default backend - 404 error when I try to access http://ip/app1/test or http://ip/app2/test
Can anyone please tell me how I can achieve this?