Oxidizing the Kubernetes Operator

Some applications are hard to manage in Kubernetes, requiring lots of manual labor and time invested to operate them. Some applications might be hard to set up, some need special care for restarts, some both. It’s individual. What if the knowledge of how to operate an application could be extracted into a dedicated software, relieving human operators? That is exactly what Kubernetes operators are about. An operator, a.k.a., custom controller automates what a human operator would do with the application to make it run successfully. First, Kubernetes is taught about the application to be operated by the custom controller. This is simply done by creating a custom resource. Custom resources end up extending the Kubernetes API, making Kubernetes recognize the resource. The operator then watches events of such custom resource and acts upon them, hence the name custom controller — a controller for custom resources.

Rust is an extraordinary language for operators to be implemented in. A typical Kubernetes operator ends up making lots of calls to the Kubernetes API. Watching resources states, creating new ones, updating/deleting old ones. Also, an operator should be able to manage multiple resources at a time, ideally in parallel. Rust’s asynchronous programming model is a perfect match for building high-performance/throughput operators. If a threaded runtime, such as Tokio is used, a vast amount of custom resources can be managed in parallel by the operator. Rust is an ahead-of-time compiled language with no runtime, no garbage collection pauses, and C-level performance. An operator typically resides inside a Pod in Kubernetes. Such a pod can be restarted at any time. Near-instant startup time minimizes delay before the state of managed resources is handled by the operator again. Rust also guarantees memory safety and eliminates data races. This is especially helpful for heavily concurrent/parallel applications, like Kubernetes operators.

Using TLS in Rust: Getting Async I/O With tokio (Part 2)

On my last post, I got really frustrated with tokio’s complexity and wanted to move to using mio directly. The advantages are that the programming model is pretty simple, even if actually working with it is hard. Event loops can cause your logic to spread over many different locations and make it hard to follow. I started to go that path until I figured out just how much work it would take. I decided to give tokio a second change, and at this point, I looked into attempts to provide async/await functionality to Rust.

It seems that at least some work is already available for this, using futures + some Rust macros. That let me write code that is much more natural looking, and I actually managed to make it work.

Using TLS in Rust: Going to async I/O With tokio (Part 1)

Now that we have a secured and authentication connection, the next stage in making a proper library is to make it run more than a single connection at a time. I could have used a thread per connection, of course, or even use a thread pool, but neither of those options is valid for the kind of work that I want to see, so I’m going to jump directly into async I/O in Rust and see how that goes.

The sad thing about this is that I expect that this will make me lose some/ all of the nice APIs that I get for OpenSSL in the sync mode.