HAproxy as ingress controller - kubernetes

What kind of load balancing HAproxy ingress controller capable of.
Can it do load balancing on a Pod level ? or it does it on a Node level load-balancing.
Thanks
Yaniv

An ingress provides load balancing, name based virtual hosting, SSL/TLS termination. Yes, it will do load balancing on services ( backed by pods ). Here is the sample Ingress kubernetes object manifest file.
Example:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: sample-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: foo.bar.com
http:
paths:
- path: /foo
backend:
serviceName: service1 ( Backed by service1 pod )
servicePort: 4200
- path: /bar
backend:
serviceName: service2 ( Backed by service2 pod )
servicePort: 8080

As mentioned in the official documentation:
The ingress controller gives you the ability to:
Use only one IP address and port and direct requests to the correct pod based on the Host header and request path
Secure communication with built-in SSL termination
Apply rate limits for clients while optionally whitelisting IP addresses
Select from among any of HAProxy's load-balancing algorithms
Get superior Layer 7 observability with the HAProxy Stats page and Prometheus metrics
Set maximum connection limits to backend servers to prevent overloading services
Also I recommend the following resources:
HAProxy Kubernetes Ingress Controller
L7 routing is one of the core features of Ingress, allowing incoming
requests to be routed to the exact pods that can serve them based on
HTTP characteristics such as the requested URL path. Other features
include terminating TLS, using multiple domains, and, most
importantly, load balancing traffic.
GitHub
I hope it helps.

Related

Traefik behind ssl terminating load balancer return 404

I have a K8s setup with traefik being exposed like this
kubernetes:
ingressClass: traefik
service:
nodePorts:
http: 32080
serviceType: NodePort
Behind, I forward some requests to different services
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: my-name
annotations:
kubernetes.io/ingress.class: traefik
spec:
rules:
- host: my-host.com
http:
paths:
- path: /my-first-path
backend:
serviceName: my-nodeJs-services
servicePort: 3000
When the DNS is set directly to resolve to my ip, the application works fine with HTTP
http://my-host.com:32080/my-first-path
But when some one add SSL through AWS ALB / API Gateway, the application fail to be reached with 404-NotFound error
The route is like this
https://my-host.com/my-first-path
On the AWS size, they configured something like this
https://my-host.com => SSL Termination and => Forward all to 43.43.43.43:32080
I think this fail because traefik is expecting http://my-host.com but not https://my-host.com which lead to its failure to find the matching route? Or maybe at the ssl termination time, the hostname is lost so that traefik can not find a route?
What should I do in this situation?
I am not very familiar with ALB but what is probably happening is that the requests received by the loadbalancer contain the header Host: my-host.com and when it gets forwarded to your ingress controller, the header is replaced by Host: 43.43.43.43. If this is the case, I see 3 solutions:
ALB might be able to pass the original Host header to the target. (You will have to check in the doc if it's possible)
If the application behind your ingress doesn't check the host header, you can write an ingress that doesn't check a specific host. For example on these examples you can see that the host field is not specified.
If the name resolution works internally, you can define a name for your target, use this name in your ALB and in your ingress.

How to configure HAproxy Ingress controller in Kubernetes

So we have a SQL server deployment with replica=2 in K8s which I need to make load balanced. I'm using Haproxy ingress controller to achieve this goal but I'm stuck in configuring Haproxy. I'm trying to configure the Haproxy based on this link and I don't know how to present my two pods to the ingress!
There is this part of the link says:
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: web-ingress
namespace: default
spec:
rules:
- host: foo.bar
http:
paths:
- path: /
backend:
serviceName: app
servicePort: 80
The issue is that in "spec.rules.host" section, I don't have any domain rather I have two IPs belong to my SQL pods! How am I supposed to represent my pods to the ingress? Am I doing right?
I've looked it up alot, but no luck!
P.S: What is the best practice for Load Balancing SQL server?
A DNS system translates hostname to IPs.With a domain registered with DNS system you can add a mapping of hostname to IP in the /etc/hosts file of the system from where you want to access the hostname.

Difference between kunernetes Service and Ingress

I want to create a load balancer for 4 http server pods.
I have one mysql pod too.
Everything works fine, i have created a loadbalancer service for http, and another service for mysql.
I have read i should create an ingress too. But i do not understand what is an ingress because everything works with Services.
What is the value-add of an Ingress ?
Thanks
Since you have single service serving http, your current solution using LoadBalancer service type works fine. Imagine you have multiple http based services that you want to make externally available on different routes. You would have to create a LoadBalancer services for each of them and by default you would get a different IP address for each of them. Instead you can use an Ingress, which sits infront of these services and does the routing.
Example ingress manifest:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: test-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- http:
paths:
- path: /cart
backend:
serviceName: cart
servicePort: 80
- path: /payment
backend:
serviceName: payment
servicePort: 80
Here you have two different HTTP services exposed by an Ingress on a single IP address. You don't need a LoadBalancer per service when using an Ingress.
The Service of type LoadBalancer relies on a third-party LoadBalancer and IP provisioning thing somewhere that deals with getting Layer 3 traffic (IP) from outside to the Nodes on some high-numbered NodePort.
A Ingress relies on a third-party Ingress Controller to accept Layer 3 traffic, open it up to Layer 7 (eg, terminate TLS) and do protocol-specific routing (eg by http fqdn/path) to some other Service (probably of type ClusterIP) inside the cluster.
If all your service should be explictly exposed without any further filtering or other options, a LoadBalancer and no Ingress might be the right choice....but LoadBalancers dont do much on their own....they just expose the Service to the outside world....very little in the way of traffic shpaing, A/B testing, etc
However, if you want to put multiple services behind a single IP/VIP/certificate, or you want to direct traffic in some weird ways (like based on Header:, client type, percentage weighting, etc), you'd probably want an Ingress (which itself would be exposed by a LoadBalancer Service)

Ingress Controller Layer 7 load balancing

Services, as defined by the Service API, allow for a basic level of Layer 3/4 load balancing.
Ingress is the most useful if you want to expose multiple services under the same IP address, and these services all use the same L7 protocol (typically HTTP).
If ingress controller routes request to service itself and service allows a basic level Layer3/4 round robin load balancing to pods , where is Layer 7 load balancing here ? It is just layer 7 for routing not load balancing, right?
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/rewrite-target: /
name: web-ingress
spec:
rules:
- host: kubernetes.foo.bar
http:
paths:
- backend:
serviceName: appsvc
servicePort: 80
path: /app
Ingress's main job is L7 routing. The backend services do the actual pod level load balancing. But some Ingress controllers are bootstrapped with some load balancing policy settings, such as the load balancing algorithm, backend weight scheme, rate limiting etc.
https://kubernetes.io/docs/concepts/services-networking/ingress/#loadbalancing
See the features's supported by Traefik other than just L7 routing here:
https://docs.traefik.io/v1.7/configuration/backends/kubernetes/#general-annotations

Why is there an ADDRESS for the ingress-service? What's the use of that ADDRESS?

I deploy my cluster on GKE with an Ingress Controller
I use Helm to install the following:
Installed Ingress Controller
Deployed Load Balancer Service (Create a Load Balancer on GCP as well)
I also deployed the Ingress Object (Config as below)
Then I observed the following status ...
The Ingress Controller is exposed (By Load Balancer Service) with two endpoints: 35.197.XX.XX:80, 35.197.XX.XX:443
These two endpoints are exposed by the Cloud load balancer.
I have no problem with it.
However, when I execute kubectl get ing ingress-service -o wide, it prints out the following info.
NAME HOSTS ADDRESS PORTS AGE
ingress-service k8s.XX.com.tw 34.87.XX.XX 80, 443 5h50m
I really don't under the use of the IP under the ADDRESS column.
I can also see that Google add some extra info to the end of my Ingress config file about load balancer IP for me.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
....(ommitted)
spec:
rules:
- host: k8s.XX.com.tw
http:
paths:
- backend:
serviceName: client-cluster-ip-service
servicePort: 3000
path: /?(.*)
- backend:
serviceName: server-cluster-ip-service
servicePort: 5000
path: /api/?(.*)
tls:
- hosts:
- k8s.XX.com.tw
secretName: XX-com-tw
status:
loadBalancer:
ingress:
- ip: 34.87.XX.XX
According to Google's doc, this (34.87.XX.XX) looks like an external IP, but I can't access it with http://34.87.XX.XX
My question is that since we already have an external IP (35.197.XX.XX) to receive the traffic, why do we need this ADDRESS for the ingress-service?
If it's an internal or external IP ADDRESS?
What is this ADDRESS bound to?
What exactly is this ADDRESS used for?
Can anyone shed some light? Thanks a lot!
If you simply go take a look at the documentation you will have your answer.
What is an ingress ressource: https://kubernetes.io/docs/concepts/services-networking/ingress/#what-is-ingress
So following the doc:
Ingress exposes HTTP and HTTPS routes from outside the cluster to services within the cluster. Traffic routing is controlled by rules defined on the Ingress resource.
To be more precise on cloud provider, the ingress will create a load-balancer to expose the service to the internet. The cocumentation on the subject specific to gke: https://cloud.google.com/kubernetes-engine/docs/tutorials/http-balancer
That explains why you have an external ip for the ingress.
What you should do now:
If you don't want to expose HTTP or/and HTTPS ports just delete the ingress ressource, you don't use it so it's pretty much useless.
If you are using HTTP/HTTPS ressources, change your service type to nodePort and leave the management of the load balancer to the ingress.
My opinion is that, as you are deploying the ingress-controller, you should select the second option and leave the management of the load-balancer to it. For the ingress of the ingress-controller, don't define rules just the backend to the nodePort service, the rules should be defined in specific ingress for each app and be managed by the ingress-controller.