Haproxy ingress and regex pathType - kubernetes

I'm migrating an architecture to kubernetes and I'd like to use the Haproxy ingress controller that I'm installling with helm, according the documentation (version 1.3).
Thing is, when I'm defining path rules through an ingress file, I can't define Regex or Beging path types as seen on documentation here : https://haproxy-ingress.github.io/docs/configuration/keys/#path-type.
My configuration file :
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: bo-ingress
annotations:
haproxy.org/path-rewrite: "/"
kubernetes.io/ingress.class: haproxy
spec:
rules:
- host: foo.com
http:
paths:
- path: /
pathType: Beging
backend:
service:
name: foo-service
port:
number: 80
When I install my ingress helm chart with this configuration, I have that error message :
Error: UPGRADE FAILED: cannot patch "bo-ingress" with kind Ingress: Ingress.extensions "bo-ingress" is invalid: spec.rules[2].http.paths[12].pathType: Unsupported value: "Begin": supported values: "Exact", "ImplementationSpecific", "Prefix"
Am I missing something ? Is this feature only available for Enterprise plan ?
Thanks, Greg

HAProxy Ingress follows “Ingress v1 spec”, so any Ingress spec configuration should work as stated by the Kubernetes documentation.
As per the kubernetes documentation, the supported path types are ImplementationSpecific, Exact and Prefix. Paths that do not include an explicit pathType will fail validation. Here the path type Begin is not supported as per kubernetes documentation. So use either of those 3 types.
For more information on kubernetes supported path types refer to the documentation.

Related

searching annotations within kubernetes controllers

I was trying to find annotations to do some basic auth in Nginx controller.
Most of the resources on the internet specify this annotation:
"nginx.ingress.kuberenetes.io/..."
While I found that in the nginx docs:
https://docs.nginx.com/nginx-ingress-controller/configuration/ingress-resources/advanced-configuration-with-annotations/
It was switched to "nginx.org"
Searching external docs for answers seems a bit of a detour.
Is there a way to browse what annotations are supported on a contoller with local commands, maybe something similar to kubectl explain?
Any ideas?
you can use kubectl explain ingress, but it will just show documentation about Kubernetes resources about ingress, something like
KIND: Ingress
VERSION: networking.k8s.io/v1
DESCRIPTION:
Ingress is a collection of rules that allow inbound connections to reach
the endpoints defined by a backend. An Ingress can be configured to give
services externally-reachable urls, load balance traffic, terminate SSL,
offer name based virtual hosting etc.
FIELDS:
apiVersion <string>
APIVersion defines the versioned schema of this representation of an
object. Servers should convert recognized schemas to the latest internal
value, and may reject unrecognized values. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
kind <string>
Kind is a string value representing the REST resource this object
represents. Servers may infer this from the endpoint the client submits
requests to. Cannot be updated. In CamelCase. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
metadata <Object>
Standard object's metadata. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
spec <Object>
Spec is the desired state of the Ingress. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
status <Object>
Status is the current state of the Ingress. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
In short, for annotation better to check helm-chart and official documentation
This how you can add basic auth to the ingress
Frist, create basic auth secret
htpasswd -c auth admin
kubectl create secret generic basic-auth --from-file=auth
then refer to this secret in the annotation
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/auth-type: basic
nginx.ingress.kubernetes.io/auth-secret: basic-auth
nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required to access Linkerd'
name: linker-basicauth-ingress
namespace: linkerd-viz
spec:
tls:
- hosts:
- mybasic-auth.example.com
secretName: ingres-tls-secret
rules:
- host: mybasic-auth.example.com
http:
paths:
- backend:
service:
name: web
port:
number: 8084
path: /
pathType: Prefix
nginx-configuration/annotations.md

Google GKE and Ingress where prefix give error: invalid ingress spec

I'm trying to setup a ingress network for my Google GKE, I have tested locally on Minikube and its working as I expect.
When I hit the domain with the prefix /test-1 or /test-2 its sending me to the root of the my service /.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: api-test-domain-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
tls:
- hosts:
- api.test-domain.com
secretName: tls-secret
rules:
- host: api.test-domain.com
http:
paths:
- path: /test-1(/|$)(.*)
pathType: Prefix
backend:
service:
name: test-1-port-forwarding
port:
number: 8080
- path: /test-2(/|$)(.*)
pathType: Prefix
backend:
service:
name: test-2-port-forwarding
port:
number: 8081
The issue is when I put it into my Kubernetes cluster on Google (GKE) then I get this error
Translation failed: invalid ingress spec: failed to validate prefix
path /test-1(/|$)(.) due to invalid wildcard; failed to validate
prefix path /test-2(/|$)(.) due to invalid wildcard
I have trying in hours to trying to get it to working and what's going on, whiteout any kind of result, so really hope some one here can explain about what I did wrong and what I shut change to resolved my problem.
GKE Built-in Ingress supports wildcard but with some conditions. From the doc:
The only supported wildcard character for the path field of an Ingress is the * character. The * character must follow a forward slash (/) and must be the last character in the pattern. For example, /*, /foo/*, and /foo/bar/* are valid patterns, but *, /foo/bar*, and /foo/*/bar are not.
If you want to use NGINX you will have to deploy it, GKE doesn't ship with NGINX out of the box. Keep in mind that this is something you will have to maintain and take care of yourself. It's a valid choice to make if the GKE default ingress doesn't support what you need to do (like headers re-write for example) but just be aware of the fact that it's an extra piece of software.

Kubernetes Ingress not forwarding routes

I am fairly new to Kubernetes and have just deployed my first cluster to IBM Cloud. When I created the cluster, I get a dedicated ingress subdomain, which I will be referring to as <long-k8subdomain>.cloud for the scope of this post. Now, this subdomain works for my app. For example: <long-k8subdomain>.cloud/ping works from my browser/curl just fine- I get the expected JSON response back. But, if I add this subdomain to a CNAME record on my domain provider's DNS settings (I have used Bluehost and IBM Cloud's Internet Services), I get a 404 response back from all routes. However this response is the default nginx 404 response (it says "nginx" under "404 Not Found"). I believe this means that this means the ingress load balancer is being reached, but the request does not get routed right. I am using Kubernetes version 1.20.12_1561 on VPC gen 2 and this is my ingress-config.yaml file:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress-resource
annotations:
kubernetes.io/ingress.class: "public-iks-k8s-nginx"
nginx.ingress.kubernetes.io/configuration-snippet: |
more_set_headers "Host: <long-k8subdomain>.cloud";
spec:
rules:
- host: <long-k8subdomain>.cloud
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-service-name
port:
number: 80
I am pretty sure this problem is due to the annotations. Maybe I am using the wrong ones or I do not have enough. Ideally, I would like something like this: api..com/ to route correctly. I have also read a little bit about default backends, but I have not dove too much into that just yet. Any help would be greatly appreciated, as I have spent multiple hours trying to fix this.
Some sources I have used:
https://cloud.ibm.com/docs/containers?topic=containers-cs_network_planning
https://cloud.ibm.com/docs/containers?topic=containers-ingress-types
https://cloud.ibm.com/docs/containers?topic=containers-comm-ingress-annotations#annotations
Note: The reason why I have the second annotation is because for some reason, requests without that header were not being routed directly. So that was part of my debugging process and I just ended up leaving it as I am not sure if that annotation solves that, so I left it for now.
For the NGINX ingress controller to route requests for your own domain's CNAME record to the service instead of the IBM Cloud one, you need a rule in the ingress where the host identifies your domain.
For instance, if your domain's DNS entry is api.example.com, then change the resource YAML to:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress-resource
annotations:
kubernetes.io/ingress.class: "public-iks-k8s-nginx"
spec:
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-service-name
port:
number: 80
You should not need the second annotation for this to work.
If you want both of the hosts to work, then you could add a second rule instead of replacing host in the existing one.

Setting service name dynamically based on path in Kubernetes Ingress

In a Kubernetes ingress, I'd like to dynamically change the service name to a match on a certain part of the path in an ingress. Something like this:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: example
spec:
rules:
- host: example.com
http:
paths:
- path: /api/(^/+)/(.*)
backend:
serviceName: api-(&1)
servicePort: 80
Where &1 in the example above would resolve to the first regular expression match in the string /api/(^/+)/(.*)
So basically if a path is something like this /api/asset/fetch/anything-at-all, then it would direct the call to a service named api-asset
I know that this can potentially lead to some security issues, but if I force the prefix 'api-' to the service name then only services with the prefix 'api-' would technically be exposed to the internet. And all other services would still be protected inside the Kubernetes cluster. I can even change the prefix to be 'public-' for simplicity's sake.
Is this something that is possible? And what is the correct syntax to set it up?

Trying to rewrite url for Grafana with Ingress

In my kubernetes cluster I would like to do monitoring so I installed grafana.
I would like to access the grafana dashboard as http://example.com/monitoring, so I tried to include this in my ingress configuration
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: example-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
rules:
- host: example.com
http:
paths:
- path: /monitoring/(.*)
backend:
serviceName: grafana
servicePort: 80
The idea is to add other paths there as well, for example / for the website.
I noticed that Grafana redirects http://example.com/monitoring to http://example.com/login. Of course this should have been http://example.com/monitoring/login. What would be the preferred way to fix this. Can it be done with ingress or should I somehow tell Grafana that it is behind a /monitoring path (if possible)?
I've installed grafana using this using Helm.
UPDATE: I've modified as suggested below the grafana chart's file values.yaml as follows
grafana.ini:
server:
domain: example.com
root_url: http://example.com/monitoring/
Now I get:
And the heml command I use to install grafana:
$> helm install stable/grafana -f values.yaml --set persistence.enabled=true --set persistence.accessModes={ReadWriteOnce} --set persistence.size=8Gi -n grafana
This is a common problem with services that are behind an HTTP reverse-proxy. Luckily, Grafana offers a way to let it know the context path it is running behind.
In grafana.ini (which is most possibly supplied via a ConfigMap to its Kubernetes deployment), you need to specify the variables like the following:
[server]
domain = example.com
root_url = http://example.com/monitoring/
See the full documentation here: https://grafana.com/docs/installation/behind_proxy/