You should use some kind of load-balancing solution, at least for these main reasons:
- To equally balance the load between the nodes.
- To check availability of the nodes and make it transparent as possible to your app.
If you use an HAproxy server you should have it replicated, so it's not a single point of failure, e.g. you can have two HAproxies in active/passive with a VIP* managed by keepalived, so if one dies, the other one starts taking the connections.
As you say, there are other options, as having local MySQL proxies in your application servers, or a pool of connections with health checks in your app backend.
If anyway you don't want to deploy any proxy, you can try to have a VIP (or some of them) managed by
keepalived directly in your nodes, but with this solution it'd be more difficult to have fair balancing between the nodes and probably you wouldn't benefit so much of the cluster.
The best solution probably depends on the kind of load your cluster is going to have.
* VIP - Virtual IP. In
keepalived terms it's an IP that is managed by
keepalived. It's initially configured in the "active" host and if it dies, or some of its checks fail, or it's preempted by any other reason, then the
keepalived daemons ensure that the IP is down in the failing host and is configured in the "passive" one.