Pragmatic CS #4: The Kubernetes Microservices vs Optimised Monolithic Debate
The unsuspected choice between Kubernetes Microservices or a Rust server
Hey folks,
With the death of George Floyd and the subsequent protests which are happening across the US, I took some time this week to reflect. I think this video by Trevor Noah nailed it. Also, if you want to better understand racism and what Blacks in America have experienced, the 13th documentary on Netflix was helpful for me.
Back to CS, we touch on the considerations over an important decision you might have to make for all your web projects – a microservices or monolithic architecture? We also highlight the technical details of a zero-day vulnerability in Sign-in With Apple discovered last month which allowed full account takeovers with just an Email ID.
Distributed System Using Kubernetes or Performance Optimisation?
One of the main debates in this Hacker News thread on the popularity of Kubernetes, was framed as a choice between a microservices architecture on Kubernetes or a single statically linked, optimised server (using eg. C++, Rust or Go).
On one account, using a distributed system affected developer productivity:
as simple as a web app with frontend and backend code, probably upwards of 80% of my time is spent on things I wouldn’t need to do if it weren’t distributed…
Everything is fragile narrow laggy asynchronous mismatched untrusted pipes…
all these costs mean you should try really hard to avoid making your system distributed if you don’t have to.
Fragile: The network connection or the other end can have hardware failures, these have different implications but both manifest as just a timeout. Everything needs to handle failure.
Narrow: Bandwidth is limited so we need to carefully design protocols to only send what they need.
Laggy: Network latency is noticeable so we need to carefully minimize round-trips.
Asynchronous: Especially with >2 input sources (UIs count) all sorts of races and edge cases can happen and need to be thought about and handled.
Mismatched: It’s often not possible to upgrade all systems atomically, so you need to handle different ends speaking different protocol versions.
Untrusted: If you don’t want everything to be taken down by one malfunction you need to defend against invalid inputs and being overwhelmed. Sometimes you also need to defend against actual attackers.
Pipes: Everything gets packed as bytes so you need to be able to (de)serialize your data.
On the Kubernetes camp, from the article:
one of the big shifts with Kubernetes has been the move from infrastructure as code towards infrastructure as data—specifically, as YAML.
This allows for easy scalability as having resources defined as YAML makes it super easy for cluster operators to change one or two numbers in a Kubernetes resource to change the scaling behavior.
Having Kubernetes YAML files under git repositories also allows you to know precisely when a change was made, who made the change, and what exactly changed.
This is corroborated with the experience of several commentators on Hacker News:
I find that the big problems that k8s solve is the usual change management issues in production systems.
Other benefits from Kubernetes allowing Infrastructure as YAML include use of the cloud-provider component which allows every cluster to integrate with the cloud provider it’s running on, and better security and control by allowing validation of what and how things get deployed.
How a Zero-day in Sign-in With Apple Using Only Email ID For Full Account Takeover Happened
The attacker could request JSON Web Tokens for any Email ID from Apple and when the signature of these tokens was verified using Apple’s public key, they showed as valid. This means an attacker could forge a JWT by linking any Email ID to it and gaining access to the victim’s account.