Pragmatic CS #5 Rust Love and Kubernetes Challenges
Reasons for Rust love, challenges with container orchestration platforms and Async Python
A significant part of my mission with this Pragmatic CS newsletter, is in figuring out how Computer Science knowledge helps us as programmers choose the right tool for the right job, and using the tools in the right way. The articles featured in today’s newsletter seek to do that.
Why The Developers Who Use Rust Love It So Much
In the recently-released Stack Overflow 2020 Developer Survey results , Rust is the number one most loved language among the 65,000 programmers who participated. It has taken the number one spot since 2016. 86.1% of respondents who currently use Rust want to continue using it next year.
Jay Oster, Architect at PubNub, on how Rust is the only language that ticks all the boxes:
Memory safe
Type safe
Data race-free
Ahead-of-time compiled
Built on and encourages zero-cost abstractions
Minimal runtime (no stop-the-world garbage collection, no JIT compiler, no VM)
Low memory footprint (programs run in resource constrained-environments like small microcontrollers)
Targets bare-metal (e.g. write an OS kernel or device driver; use Rust as a ‘high level assembler’)
David Ross on compile time guarantees:
When I think of a “statically typed language”, I think of Java, or C#, or something like TypeScript. They give compile-time assurances that your code has the correct types, and move a set of errors from runtime to compile time. Rust goes one magnitude further in this! Compile time checking extends to thread safety, to ownership semantics, to validation.
Peter Varo on Rust finding the sweet spot:
it is just as low-level as C or C++ with all the advantages of these (e.g. control, size, speed, etc.) At the same time, it is as high-level as Haskell with an amazing amount of functional heritage. It is still imperative, so quite accessible to most people, and it is just as flexible as Python. For example, concepts like “duck-typing” are happening at compile time (i.e. trait bounds), yet it does not have the dated, object-oriented programming model and all of its well known problems.
I normally try to be more balanced in how I present such evaluations, but apart from the steep initial learning curve and relatively less mature ecosystem of libraries, I didn’t find many other substantial downsides to the use of Rust as a language. Sure, you might feel like you are fighting the compiler sometimes, but that’s better than having those errors pop-up in run-time.
Should you containerize, and what container orchestration platform should you use? Coinbase put out a blogpost this week about their decision not to use Kubernetes as part of Coinbase's container technologies stack:
The basics of securing a Kubernetes cluster are well known/understood but once you dig into each of them the complexities start to unravel. Securing all of the system components (etcd, kubelet), the API server, and any abstracts/overlays (Istio) opens up a lot of surface to understand, test, and secure. Going deep into namespaces, seccomp, SELinux, cgroups, etc. is all required given the increased attack surface.
On containers being resource boundaries, not security boundaries:
In order to define security boundaries around containers, you need to delve into custom kernel namespaces, syscall filtering, mandatory access control frameworks, and/or vm-based isolation technologies designed for containers like gVisor.
Benchmark To Show Async Python Is Not Faster
Under realistic conditions, asynchronous web frameworks have slightly worse throughput and much worse latency variance.
In async Python, the multi-threading is co-operative, which simply means that threads are not interrupted by a central governor (such as the kernel) but instead have to voluntarily yield their execution time to others. In asyncio, the execution is yielded upon three language keywords:
await
,async for
andasync with
. This means that execution time is not distributed "fairly" and one thread can inadvertently starve another of CPU time while it is working. This is why latency is more erratic.In contrast, traditional sync Python webservers like UWSGI use the pre-emptive multi-processing of the kernel scheduler, which works to ensure fairness by periodically swapping processes out from execution. This means that time is divided more fairly and that latency variance is lower.