I am running some highly frequented LAMP stack web applications on Kubernetes. I strive to achieve highest possible availability of these applications. That's why I utilize deployments with several replicas for my apache and php-fpm pods. As database we use mariadb galeraclusters.
So these components can be easily updated without service interruption at any time. Rolling updates will always ensure, that my apps stay responsive. Even in case of a hardware node failure, it won't bother the apps, because the replicas have node-anti-affinity-rules, so they are always scheduled on different nodes at the same time.
However, there is still one remaining single point of failure in my setup. And that's the php sessions. How can I make php sessions highly available?
Right now, I have just one standalone redis pod, where all php-fpm pods store their sessions. It has a pvc to persistently store session information to disk. But if this redis pod needs an update, or if I'd need to update its hardware-node, I would have to move the redis pod to another node, which will cost me about 45 seconds of downtime, causing annoying lost sessions and customer logouts in the frontends.
A while ago, I thought redis-cluster could help. But I was wrong, because redis-cluster is not about high-availability and fail-over, but more about breaking up bigger databases into smaller party, aka sharding.
Then I thought, redis-sentinel could be my choice. But reading more about that approach, I find that a failover there will not work without a downtime either: https://github.com/bitnami/charts/tree/main/bitnami/redis#master-replicas-with-sentinel Also, there is no php session handler available for redis-sentinel. It's not compatible with the default redis php session handler, as it requires to ask for the current writer first. I'd also need to rework the existing applications, if reads should have to be sent to a different service than writes.
So I started to look for further options, but I seem to get stuck sooner or later on any technology. My results so far:
- files: Not an option if you have several php-fpm pods (and no, I don't want to use a shared filesystem like NFS or cephfs)
- mysql: Not an option if you have high traffic and many many sessions, and if speed matters
- redis-standalone: my current solution, but not suitable as a high-availbility solution
- redis-cluster: Not suitable because not a high-availbility solution
- redis-sentinel: no native session handler for php, rework of application, failover obviously not without downtime
- memcache: Not suitable because missing session locks, which can mess up session data in scenarios where several calls could occur simultaneously (e.g. AJAX requests)
- memcached: Session locking works, but there is no option to write data to several memcached-servers at the same time, or sync memcached instances
- hazelcast: no session locking implemented
- membase / couchbase: This could be an approach, from what I have been reading so far. Initially there was some memcache compatibility, but this seems to be deprecated nowadays. A memcached compatibility would make integration into php easy, because existing php session handlers could be used.
So at the moment, couchbase seems to be the most promising approach. Has anyone gone this way before for php session handling?
If I start looking for it, I find articles from 10 years ago and older, like this: https://github.com/daschl/blogposts/blob/master/content/post/How-to-store-PHP-sessions-in-Couchbase.md - no recent development in this area?
Or maybe there is a completely different approach / technology, which I am missing in my list above? How are you dealing with php sessions in Kubernetes or generally in multi-server environments nowadays?