Bad Analogy Time
So last week I promised a less incendiary topic for this week's post, and I'm talking about Kubernetes and C++ today, so, well, I guess you can decide for yourselves whether or not I kept my promise1.
A few days ago I had the distinct pleasure to give a talk at the University of California, Santa Cruz Computer Science & Engineering colloquium. It was really fun, and I had a lot of good conversations as a part of it; I understand it was recorded, so I'll post a link when it's available. Anyways, as a part of this presentation I made an analogy which initially I intended to be a bit of a throw-away, but as I kept thinking about it, the more it captivated me. So I'm going to use this blog post as a space for me to think out loud and explore this analogy some more.
"It's like C++, but for distributed systems"
So what is this analogy?
C++ : Kubernetes :: Rust/Golang/Swift/... : ???
If you remember your middle school grammar lessons, you might recall that the above notation is a compact way of comparing the relationship between two sets of thing that are otherwise incomparable. The above statement says that "C++ is to Kubernetes as Rust, Golang, and Swift are to some unknown entity", or put another way "C++ and Kubernetes occupy the same space in their respective domains," namely programming languages and distributed systems.
Just as it's difficult to say that one is an expert in C++, I think it's similarly difficult to say that one is an expert in Kubernetes, but just to establish my credentials a little bit—I've been doing distributed systems work since 2016, first on Mesos and then on Kubernetes, so you can say I've been around the block a few times. On the C++ front, I haven't seriously written C++ in about 10 years, and I know a lot has changed in the language in that intervening period, but it was my language of choice all through grad school, and I would say at the time that I was a very proficient C++ developer2. So I think I can at least argue that I have the credentials to plausibly make a comparison between the two technologies.
Let's start with the basic stuff first:
✅ Arcane, difficult-to-understand syntax
✅ Arcane, difficult-to-understand error messages
✅ Arcane, difficult-to-understand footguns
Ok, comparison over, I think we're done here.
A look at the origins
I jest, I jest. I think there are some deeper comparisons we can draw between C++ and Kubernetes, and I'd like to first examine where the both came from. C++, perhaps obviously, came from C. In fact, even today, every C program is a valid C++ program3. C++ grew up in the "object-oriented programming" phase of software engineering, and for a long time it was common to describe C++ as "C with objects"; however, I think this is too simplistic. C++ was, and continues to be, a reaction to the perception that C is too low-level, and most (if not all) of C++'s features are an attempt to abstract away some of the things that are hard about C.
Now, in this analogy, we could argue that Kubernetes has two potential predecessors: since it was developed at Google as an "open source Borg", you could make the argument that Borg is Kubernetes' predecessor, but I actually think it's more accurate to say that Mesos is Kubernetes' predecessor. Mesos was4 very widely used by a lot of the tech industry for a long time, and I think that one of the reasons it quote-unquote "lost" was because it was too low-level. It was difficult to do a lot of things that developers wanted to do with it, and when Kubernetes came along and made it easier to do those things, I think it's fairly understandable why people jumped ship.
However, in the same way that C paved the way for C++ by introducing ideas like an abstract memory model + pointers, I think that Mesos paved the way for Kubernetes by introducing the idea of treating a distributed compute cluster as a large abstract blob of resources. I think that C and Mesos are foils for their respective successors: just like C++ probably wouldn't exist if C hadn't come along first, I don't think Kubernetes would be nearly as popular as it is today if Mesos hadn't shown the way5.
C++ is dead. Long live C++!
Today, a lot of people like to talk down about C++. The problems (of which there are many) are well-documented but still easy to fall into, and the common criticism is that the language continues to bolt on new features instead of trying to fix some of its fundamental issues. I think this is a disingenuous argument. Modern C++ looks completely different from C++ twenty years ago. Things that were once considered best practices are now considered anathema. And yes, there are a lot of new features, but there has also been a lot of effort to address issues. RAII was a huge paradigm shift in the language that solves (some of) the issues with memory management and pointers, and there are new features today that are pushing the boundaries of safe programming in C++ in new ways6.
It's also true that C++ isn't going anywhere, possibly ever. Despite all the cries of "rewrite it in Rust" or "just use Golang", there are huge legacy codebases in C++ that will never go away. There are extremely valid reasons to start new projects in C++ as well. I can almost guarantee that "knowing C++" will be an extremely employable skill for many years to come.
In the same way: a lot of people talk smack about Kubernetes. The problems (of which there are many) are well-documented but still easy to fall into, and the common criticism is that the platform continues to bolt on new features instead of trying to fix some of its fundamental issues. I think this is a disingenuous argument. Modern Kubernetes deployments look very different from Kubernetes even five years ago. Five years ago, sidecars were all the rage. Then, I think people started to realize that "running 20 sidecars in every pod" is maybe an anti-pattern, and so we started to walk back from that a bit, and the developers introduced some new primitives to help manage sidecars7. The arguments about whether or not to use CPU limits will continue to rage for another decade, I'm sure.
But, it's also true that Kubernetes isn't going anywhere, possibly ever. It has soaked into the fabric of tech reality, and hundreds of non-tech industries are also investing in Kubernetes. Yes, it's hard to use, manage, and maintain, and no, you don't need Kubernetes to deploy your static website, but there are many valid technical and organizational reasons why you might reach for Kubernetes as a platform, and I don't think that's going to change. Knowing Kubernetes will continue to be an extremely employable skill for many years to come.
So what comes next?
In the analogy I started this post off with, it's clear that there are successors to C++. Each of these successors tries to address a different subset of problems with C++. Rust, for example, wants to make a provably-memory-safe language. Go, on the other hand, wants to make a modern C with a garbage collector. Swift, TypeScript, etc. are also all reactions to C and C++, although possibly more remote.
What I don't think we know is "What comes after Kubernetes?" I don't mean this in the sense of "What's going to make all these companies rip out their Kubernetes platform?", we've already established that that won't happen. But I do wonder what things we're going to build on top of (or in response to) Kubernetes. What problems will we all decide are so important to solve that we need something new to solve them? What is the equivalent of "memory safety" for Kubernetes, in other words? I can think of a few candidates:
How do we run stateful systems (like a database) in a Kubernetes-like way?
How will we safely deploy new AI-based applications in a resource-constrained environment?
For the love of god can we please stop writing all this YAML?
I also think it's interesting to imagine how these new things will be built. Some solutions may actually just run on top of Kubernetes8. You could imagine a "distributed compiler", for example, which is able to analyze a giant monolithic codebase, identify where to break apart the API boundaries into service boundaries, and then produce all of the Kubernetes primitives to run that monolith in a distributed way. Other solutions may require building something new, something that is a bit more scoped to the problem domain: handling stateful services, for example, seems to fall into this bucket for me9.
Anyways, I don't think we have answers to any of this stuff yet, but this honestly is why I started Applied Computing in the first place. I don't know what we're going to build yet and I don’t know how we’re going to build it, but I do know that I want to be there when it happens.
That's all for this week! Hopefully this post was as inspiring for you to read as it has been for me to think about :)
Thanks for reading,
Also, to all my new orange site subscribers and/or visitors—welcome! I'm glad you're here!
I did my first "real" coding interview as a software engineer in C++, which I think impressed the interviewer a little bit #humblebrag
Yes I know that's not true but people like to say it anyways, and it's "true enough" in most cases, until it isn't.
And continues to be, in some cases coughUbercough.
This is obviously a subjective opinion, but it's my blog, so I can say what I want. I'm not gonna preface every potential opinion in this post with a disclaimer.
I unfortunately haven't read any of his proposals, but ThePhD is one person who has been extremely active and vocal about fixing some of the problems in both C and C++. If you're interested to know more you should absolutely follow them.
Whether or not these primitives actually solve the problems they need to solve is maybe a rant for a different post.
In the same way that Rust and C++ can be compiled down to LLVM IR, for example.
I used to ask this as an interview question. "Build me an orchestration platform that is capable of handling stateful services with the same ease that Kubernetes can deploy web services." It was fascinating to see the range of responses I would get to that question.