K3s traefik ingress returns gateway timeout - kubernetes

I am currently playing around with a rpi based k3s cluster and I am observing a weird phenomenon.
I deployed two applications.
The first one is nginx which I can reach on the url http://external-ip/foo based on the following ingress rule:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: foo
namespace: foo
annotations:
kubernetes.io/ingress.class: traefik
traefik.ingress.kubernetes.io/rule-type: "PathPrefixStrip"
traefik.ingress.kubernetes.io/rewrite-target: "/"
spec:
rules:
- http:
paths:
- path: /foo
backend:
serviceName: foo-service
servicePort: 8081
And the other one is grafana which I cannot reach on the url http://external-ip/grafana based on the below ingress rule:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: grafana
namespace: grafana
annotations:
kubernetes.io/ingress.class: traefik
traefik.ingress.kubernetes.io/rule-type: "PathPrefixStrip"
traefik.ingress.kubernetes.io/rewrite-target: "/"
spec:
rules:
- http:
paths:
- path: /grafana
backend:
serviceName: grafana-service
servicePort: 3000
When I do a port-forward directly on the pod I can reach the grafana app, when I use the port-forward on the grafana service it also works.
However as soon as I try to reach it through the subpath I will get a gateway timeout.
Does anyone have a guess what I am missing?
Here the deployment and service for the grafana deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: grafana
namespace: grafana
labels:
app: grafana
tier: frontend
service: monitoring
spec:
selector:
matchLabels:
app: grafana
tier: frontend
template:
metadata:
labels:
app: grafana
tier: frontend
service: monitoring
spec:
containers:
- image: grafana
imagePullPolicy: IfNotPresent
name: grafana
envFrom:
- configMapRef:
name: grafana-config
ports:
- name: frontend
containerPort: 3000
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
name: grafana-service
namespace: grafana
labels:
app: grafana
tier: frontend
service: monitoring
spec:
selector:
app: grafana
tier: frontend
type: NodePort
ports:
- name: frontend
port: 3000
protocol: TCP
targetPort: 3000
Solution
I had to add the following two parameters to my configmap to make it work:
GF_SERVER_ROOT_URL=http://localhost:3000/grafana/
GF_SERVER_FROM_SUB_PATH=true

As I mentioned in comments grafana is not listening on / like default nginx.
There is related github issue about this, and if you want to make it work you should specify root_url
grafana.ini:
server:
root_url: https://subdomain.example.com/grafana
Specifically take a look at this and this comment.
#tehemaroo add his own solution which include changing root url and sub_path in configmap
I had to add the following two parameters to my configmap to make it work:
GF_SERVER_ROOT_URL=http://localhost:3000/grafana/
GF_SERVER_FROM_SUB_PATH=true
And related documentation about that
To serve Grafana behind a sub path:
Include the sub path at the end of the root_url.
Set serve_from_sub_path to true.
[server]
domain = example.com
root_url = %(protocol)s://%(domain)s:%(http_port)s/grafana/
serve_from_sub_path = true

Related

GKE Ingress with Multiple Backend Services returns 404

I'm trying to create a GKE Ingress that points to two different backend services based on path. I've seen a few posts explaining this is only possible with an nginx Ingress because gke ingress doesn't support rewrite-target. However, this Google documentation, GKE Ingresss - Multiple backend services, seems to imply otherwise. I've followed the steps in the docs but haven't had any success. Only the service that is available on the path prefix of / is returned. Any other path prefix, like /v2, returns a 404 Not found.
Details of my setup are below. Is there an obvious error here -- is the Google documentation incorrect and this is only possible using nginx ingress?
-- Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
annotations:
kubernetes.io/ingress.global-static-ip-name: app-static-ip
networking.gke.io/managed-certificates: app-managed-cert
spec:
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-service
port:
number: 80
- path: /v2
pathType: Prefix
backend:
service:
name: api-2-service
port:
number: 8080
-- Service 1
apiVersion: v1
kind: Service
metadata:
name: api-service
labels:
app: api
spec:
type: NodePort
selector:
app: api
ports:
- port: 80
targetPort: 5000
-- Service 2
apiVersion: v1
kind: Service
metadata:
name: api-2-service
labels:
app: api-2
spec:
type: NodePort
selector:
app: api-2
ports:
- port: 8080
targetPort: 5000
GCP Ingress supports multiple paths. This is also well described in Setting up HTTP(S) Load Balancing with Ingress. For my test I've used both Hello-world v1 and v2.
There are 3 possible issues.
Issue is with container ports opened. You can check it using netstat:
$ kk exec -ti first-55bb869fb8-76nvq -c container -- bin/sh
/ # netstat -plnt
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 :::8080 :::* LISTEN 1/hello-app
Issue might be also caused by the Firewall configuration. Make sure you have proper settings. (In general, in the new cluster I didn't need to add anything but if you have more stuff and have specific Firewall configurations it might block).
Misconfiguration between port, containerPort and targetPort.
Below my example:
1st deployment with
apiVersion: apps/v1
kind: Deployment
metadata:
name: first
labels:
app: api
spec:
selector:
matchLabels:
app: api
template:
metadata:
labels:
app: api
spec:
containers:
- name: container
image: gcr.io/google-samples/hello-app:1.0
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: api-service
labels:
app: api
spec:
type: NodePort
selector:
app: api
ports:
- port: 5000
targetPort: 8080
2nd deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: second
labels:
app: api-2
spec:
selector:
matchLabels:
app: api-2
template:
metadata:
labels:
app: api-2
spec:
containers:
- name: container
image: gcr.io/google-samples/hello-app:2.0
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: api-2-service
labels:
app: api-2
spec:
type: NodePort
selector:
app: api-2
ports:
- port: 6000
targetPort: 8080
Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
spec:
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-service
port:
number: 5000
- path: /v2
pathType: Prefix
backend:
service:
name: api-2-service
port:
number: 6000
Outputs:
$ curl 35.190.XX.249
Hello, world!
Version: 1.0.0
Hostname: first-55bb869fb8-76nvq
$ curl 35.190.XX.249/v2
Hello, world!
Version: 2.0.0
Hostname: second-d7d87c6d8-zv9jr
Please keep in mind that you can also use Nginx Ingress on GKE by adding specific annotation.
kubernetes.io/ingress.class: "nginx"
Main reason why people use nginx ingress on GKE is using rewrite annotation and possibility to use ClusterIP or NodePort as serviceType, where GCP ingress allows only NodePort serviceType.
Additional information you can find in GKE Ingress for HTTP(S) Load Balancing

Expose services via Istio ingress gateway

I am new to istio and I want to expose three services and route traffic to those services based on the port number passed to "website.com:port" or subdomain.
services deployment config files:
apiVersion: v1
kind: Service
metadata:
name: visitor-service
labels:
app: visitor-service
spec:
ports:
- port: 8000
nodePort: 30800
targetPort: 8000
selector:
app: visitor-service
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: visitor-service
spec:
replicas: 1
selector:
matchLabels:
app: visitor-service
template:
metadata:
labels:
app: visitor-service
spec:
containers:
- name: visitor-service
image: visitor-service
ports:
- containerPort: 8000
second service:
apiVersion: v1
kind: Service
metadata:
name: auth-service
labels:
app: auth-service
spec:
ports:
- port: 3004
nodePort: 30304
targetPort: 3004
selector:
app: auth-service
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: auth-service
spec:
replicas: 1
selector:
matchLabels:
app: auth-service
template:
metadata:
labels:
app: auth-service
spec:
containers:
- name: auth-service
image: auth-service
ports:
- containerPort: 3004
Third one:
apiVersion: v1
kind: Service
metadata:
name: gateway
labels:
app: gateway
spec:
ports:
- port: 8080
nodePort: 30808
targetPort: 8080
selector:
app: gateway
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: gateway
spec:
replicas: 1
selector:
matchLabels:
app: gateway
template:
metadata:
labels:
app: gateway
spec:
containers:
- name: gateway
image: gateway
ports:
- containerPort: 8080
If someone can help setting up the gateway and virtual service configuration it would be great.
It seems like you simply want to expose your applications, for that reason istio seems like a total overkill since it comes with a lot of overhead that you won't be using.
Regardless of whether you want to use istio as your default ingress or any other ingress-controller (nginx, traefik, ...) the following construct applies to all of them:
Expose the ingress-controller via a service of type NodePort or LoadBalancer, depending on your infrastructure. In a cloud environment the latter one will most likely work the best for you (if on GKE, AKS, EKS, ...).
Once it is exposed set up a DNS A record to point to the external IP address. Afterwards you can start configuring your ingress, depending on which ingress-controller you chose the following YAML may need some adjustments (example is given for istio):
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: istio
name: ingress
spec:
rules:
- host: httpbin.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
serviceName: httpbin
servicePort: 8000
If a request for something like httpbin.example.com comes in to your ingress-controller it is going to send the request to a service named httpbin on port 8000.
As can be seen in the YAML posted above, the rules and paths field take a list (indicated by the - in the next line). To expose multiple services simply add a new entry to the list, e.g.:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: istio
name: ingress
spec:
rules:
- host: httpbin.example.com
http:
paths:
- path: /httpbin
pathType: Prefix
backend:
serviceName: httpbin
servicePort: 8000
- path: /apache
pathType: Prefix
backend:
serviceName: apache
servicePort: 8080
This is going to send requests like httpbin.example.com/httpbin/ to httpbin and httpbin.example.com/apache/ to apache.
For further information see:
https://istio.io/latest/docs/tasks/traffic-management/ingress/kubernetes-ingress/
https://kubernetes.io/docs/concepts/services-networking/ingress/

How to manage 'link forwarding' for a website inside a kubernetes cluster

I have a website that uses relative href links (eg. the link directs to "/login", rather than "http://somesite.com/login"). This works A-OK in a normal server but I'd like to use the website inside a docker container as part of a kubernetes cluster. My goal is to have multiple replicas of the website to manage high load times, defaulting to two nodes with dynamic scaling.
I set us the service as a 'loadbalancer' as follows:
apiVersion: v1
kind: Service
metadata:
name: websiteservice
spec:
selector:
app: websiteapp
type: LoadBalancer
ports:
- protocol: TCP
port: 80
targetPort: 80
The issue here is that if I navigate to the URL of the load balancer (that's automatically created at my host - digital ocean) then although the homepage of the website loads, any other pages give me a 404 because rather than loading the "/login" page of the container it loads the "/login" page of the load balancer which doesn't exist. How can I configure my cluster or load balancer to forward all subdirectories (anything after the .com) to the webserver?
EDIT 1
In comments I was advised to set up ingress. I think I've done so with this change to my yaml:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: test-ingress
annotations:
kubernetes.io/ingress.class: nginx
spec:
rules:
- host: somesite.co.uk
http:
paths:
- backend:
serviceName: websiteservice
servicePort: 80
---
apiVersion: v1
kind: Service
metadata:
name: websiteservice
spec:
selector:
app: websiteapp
type: ClusterIP
ports:
- protocol: TCP
port: 80
targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: websiteapp
spec:
replicas: 2
selector:
matchLabels:
app: websiteapp
template:
metadata:
labels:
app: websiteapp
spec:
containers:
- name: websiteapp
image: mydocker.co.uk/websiteimg
imagePullSecrets:
- name: regcred
nodeSelector:
beta.kubernetes.io/instance-type: s-2vcpu-4gb
But I'm still not able to navigate beyond the home page of my website.
Your Ingress file should look like this:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: test-ingress
annotations:
kubernetes.io/ingress.class: nginx
spec:
rules:
- host: somesite.co.uk
http:
paths:
- path: /*
backend:
serviceName: websiteservice
servicePort: 80
Simply you have add path to redirect traffic.
Take a look: host-path-routing, ingress-path-matching.

Minikube ingress is not responding

I am trying to redirect traffic to my Cluster Deployment object. My Deployment object is a node image which depends on a SQL server image.
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: example-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- http:
paths:
- path: /
backend:
serviceName: simptekapi-api-service
servicePort: 5000
MY Cluster IP service ====>
apiVersion: v1
kind: Service
metadata:
name: simptekapi-api-service
spec:
selector:
component: api
type: ClusterIP
ports:
- port: 5000
targetPort: 5000
My deployment Object ===>
apiVersion: apps/v1
kind: Deployment
metadata:
name: simptekapi-api-deployment
spec:
replicas: 3
selector:
matchLabels:
component: api
template:
metadata:
labels:
component: api
spec:
containers:
- name: simptekapi-api
image: nayan2/simptekapi
ports:
- containerPort: 5000
My node image is basically a Test API Project. I am sharing the SignIn url (http://Minikube_ip/api/v1/auth/SignIn)
Seems like everything ok to me. As am still literally a newbie with Kubernetes. It's hard for me to figure out what I am doing wrong.
While I have tried to reach my pods through Node-Port, everything was perfect. I don't know why I am unable to react it out through ingress.
kubectl get ingress example-ingress ==> Result
AND kubectl get pods -n ingress-nginx ==> Result

Bad Gateway with traefik Ingress

I'm using minikube with traefik ingress to create a sticky sessions.
So i have done the deploy of traefik that user guide kubernetes provides me. https://docs.traefik.io/user-guide/kubernetes/
I deploy traefik using DaemonSet. Cause it's a small project and is my first time using kubernetes and docker.
This is my ingress yaml file
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: cp-pluggin
annotations:
kubernetes.io/ingress.class: traefik
spec:
rules:
- host: cppluggins.minikube
http:
paths:
- path: /
backend:
serviceName: cp-pluggin
servicePort: 80
My service yaml file
apiVersion: v1
kind: Service
metadata:
name: cp-pluggin
annotations:
traefik.ingress.kubernetes.io/affinity: "true"
traefik.ingress.kubernetes.io/session-cookie-name: "sticky"
spec:
type: NodePort
ports:
- port: 80
targetPort: 8080
protocol: TCP
name: http
selector:
app: cp-pluggin-app
Finally, my deployment yaml file
apiVersion: apps/v1
kind: Deployment
metadata:
name: cp-pluggin-app
labels:
app: cp-pluggin-app
spec:
replicas: 3
selector:
matchLabels:
app: cp-pluggin-app
template:
metadata:
labels:
app: cp-pluggin-app
spec:
containers:
- name: cp-pluggin-app
image: essoca/ubuntu-tornado
ports:
- containerPort: 8080
I expected
Hello world from: [ipserver]
But i get a
bad gateway
I assume you are using Traefik 2.0, the latest version as of now. There are quite some changes in this version, i.e. the annotations are not used anymore. Besides that, I think the code that you posted is missing a big part of the required changes.
Also, it's not very useful to use a DaemonSet because you are using minikube and that's always one node. Using a Deployment will at least allow you to play with the scale up/down functionality of Kubernetes.
I wrote this article that might be useful for you Traefik 2 as Ingress Controller