Slide 1

Slide 1 text

0000001111101000011111000100000111100101011110010110100001110100011110100001000111110 0111001100000100010000011111000001101110100100001111000000101101000100101010110111010 0010111000111011111101110011010101010101001101101100011101101010011110000101000000000 0011111010000111110001000001111001010111100101101000011101000111101000010001111100111 0011000001000100000111110000011011101001000011110000001011010001001010101101110100010 1110001110111111011100110101010101010011011011000111011010100111100001010000000000011 1110100001111100010000011110010101111001011010000111010001111010000100011111001110011 0000010001000001111100000110111010010000111100000010110100010010101011011101000101110 0011101111110111001101010101010100110110110001110110101001111000010100000000000111110 1000011111000100000111100101011110010110100001110100011110100001000111110011100110000 0100010000011111000001101110100100001111000000101101000100101010110111010001011100011 1011111101110011010101010101001101101100011101101010011110000101000000000001111101000 0111110001000001111001010111100101101000011101000111101000010001111100111001100000100 0100000111110000011011101001000011110000001011010001001010101101110100010111000111011 1111011100110101010101010011011011000111011010100111100001010000000000011111010000111 1100010000011110010101111001011010000111010001111010000100011111001110011000001000100 0001111100000110111010010000111100000010110100010010101011011101000101110001110111111 0111001101010101010100110110110001110110101001111000010100000000000111110100001111100 0100000111100101011110010110100001110100011110100001000111110011100110000010001000001 1111000001101110100100001111000000101101000100101010110111010001011100011101111110111 0011010101010101001101101100011101101010011110000101000000000001111101000011111000100 0001111001010111100101101000011101000111101000010001111100111001100000100010000011111 0000011011101001000011110000001011010001001010101101110100010111000111011111101110011 0101010101010011011011000111011010100111100001010000001011010000111010110100010111000 When to rebuild things that already exist Jacob Tomlinson

Slide 2

Slide 2 text

Dask Kubernetes A tool for deploying Dask clusters on Kubernetes

Slide 3

Slide 3 text

The Problem Dask Kubernetes had grown to use many different Kubernetes libraries because none of them individually had all the features we needed. Some libraries are also much more verbose than others and most have poor documentation. Using many Kubernetes libraries made things hard to maintain.

Slide 4

Slide 4 text

Proliferation of libraries kubernetes kubernetes_asyncio pykube-ng kubectl (via subprocess) kubectl (via pytest-kind) kopf

Slide 5

Slide 5 text

Library pros/cons Pros Official, lots of examples Semi-official, asyncio Pleasant API Pleasant API Familiar to k8s users Familiar, nice Python API kubernetes kubernetes_asyncio pykube-ng kopf kubectl (via subprocess) kubectl (via pytest-kind) Cons Autogenerated, no asyncio Autogenerated, poor docs No asyncio, no port-forward Only useful for controller Adds binary dependency Can only be used in tests

Slide 6

Slide 6 text

Can I bridge the gap by contributing? kubernetes and kubernetes_asyncio are both auto-generated libraries using the OpenAPI specification. They are generally not open to Pull Requests that fundamentally change the design as it would conflict with the auto-generation. pykube-ng is built with requests and has no asyncio support. Adding async support would mean rebuilding the entire internals of the library. kopf is designed for building operators in an event driven manner. It’s components would be hard to factor out into an imperative Kubernetes client. kubectl (via subprocess) is a widely-adopted Go application that would be hard to modify if needed and unpleasant to expose in Python via subprocess. kubectl (via pytest-kind) adds some syntactic sugar around subprocess in pytest-kind fixtures but would need to be extracted and released separately for use in our code.

Slide 7

Slide 7 text

What about a wrapper? If I can’t add what I need upstream can I wrap or shim my dependencies to fill in gaps and expose a consistent internal API?

Slide 8

Slide 8 text

I Enhanced pykube-ng with a wrapper called aiopykube

Slide 9

Slide 9 text

Blocker aiopykube was a wrapper around pykube-ng that made HTTP requests to the Kubernetes API using requests, but to work with asyncio it ran each call via a threadpool executor. When it came to implementing a pure-Python port forward using websockets it was clear this would need low-level access to requests and would be a huge challenge with this design. aiopykube as a wrapper was a dead end.

Slide 10

Slide 10 text

“I wish I had something that feels like kubectl, but in pure Python.” Me, 6 months ago

Slide 11

Slide 11 text

Should I build a new library? Fortunately, the charging one has been solved now that we've all standardized on mini-USB. Or is it micro-USB? Shit. https://xkcd.com/927/

Slide 12

Slide 12 text

Wishlist for a new library ● The existing libraries all expose the user experience of the Kubernetes API in Python. I want to expose the user experience of kubectl. ● I want a library that supports both sync and async usage. ● I want to stop using auto-generated code and make strict client-side schema validation optional. ● I want authentication and client creation to be implicit. ● I want pure Python implementations of quality-of-life features like port forwarding but with APIs as human as kubectl.

Slide 13

Slide 13 text

Goals ● Make Dask Kubernetes more maintainable and reduce contributor friction. ● Build the library that I want to use. ● Learn more about how the Kubernetes API works, but shield others from it’s complexity. Non-Goals ● Create a new standard. ● Solve everyone’s problems. ● Get everyone to adopt it.

Slide 14

Slide 14 text

https://github.com/kr8s-org/kr8s A simple, batteries-included, Python client library for Kubernetes that feels familiar for folks who already know how to use kubectl.

Slide 15

Slide 15 text

Comparison of libraries kubernetes_asyncio kr8s

Slide 16

Slide 16 text

We adopted kr8s and simplified Dask Kubernetes

Slide 17

Slide 17 text

Helpful person: “Have you heard of lightkube?” *Ominous music plays

Slide 18

Slide 18 text

Helpful person: “Have you heard of lightkube?”

Slide 19

Slide 19 text

They had some striking similarities lightkube kr8s

Slide 20

Slide 20 text

Should I stop and adopt lightkube instead? I’ve already achieved my goal of learning more about the Kubernetes API, and it meets some of my requirements. Maybe this is the library I want to use?

Slide 21

Slide 21 text

Digging deeper highlighted key differences lightkube kr8s

Slide 22

Slide 22 text

Goals from lightkube ● Extensive type hints to avoid common mistakes and to support autocompletion. ● Models and resources generated from the swagger specifications using standard dataclasses. ● Support for installing a specific version of the kubernetes models (1.15 to 1.27). ● Lazy instantiation of inner models.

Slide 23

Slide 23 text

I felt kr8s satisfied a different niche, so I continued. But felt uncertain…

Slide 24

Slide 24 text

until…

Slide 25

Slide 25 text

The Hacker News Effect kr8s

Slide 26

Slide 26 text

When should you build from scratch? ● When you can’t contribute to or wrap an existing project. ● When your needs are met by something fundamentally different. ● When you find a niche, don’t just rebuild everything that exists. ● When you’ve done your research and exhausted your options. ● When you want to learn how something works.

Slide 27

Slide 27 text

Just don’t be scared to throw it away again.

Slide 28

Slide 28 text

Final thoughts Come and see me for a sticker ● Building something from scratch will take longer than you think. It’s a commitment. ● Don’t hesitate to rebuild things simply to learn! ● Consider adding interoperability with existing solutions. ● There are many valid reasons to start from scratch. ● Check out the companion blog post to this talk for a deeper dive into everything that wouldn’t fit into this talk. http://jacobtomlinson.dev/posts/2023/when-to-rebuild-things-that-already-exist/

Slide 29

Slide 29 text

0000001111101000011111000100000111100101011110010110100001110100011110100001000111110 0111001100000100010000011111000001101110100100001111000000101101000100101010110111010 0010111000111011111101110011010101010101001101101100011101101010011110000101000000000 0011111010000111110001000001111001010111100101101000011101000111101000010001111100111 0011000001000100000111110000011011101001000011110000001011010001001010101101110100010 1110001110111111011100110101010101010011011011000111011010100111100001010000000000011 1110100001111100010000011110010101111001011010000111010001111010000100011111001110011 0000010001000001111100000110111010010000111100000010110100010010101011011101000101110 0011101111110111001101010101010100110110110001110110101001111000010100000000000111110 1000011111000100000111100101011110010110100001110100011110100001000111110011100110000 0100010000011111000001101110100100001111000000101101000100101010110111010001011100011 1011111101110011010101010101001101101100011101101010011110000101000000000001111101000 0111110001000001111001010111100101101000011101000111101000010001111100111001100000100 0100000111110000011011101001000011110000001011010001001010101101110100010111000111011 1111011100110101010101010011011011000111011010100111100001010000000000011111010000111 1100010000011110010101111001011010000111010001111010000100011111001110011000001000100 0001111100000110111010010000111100000010110100010010101011011101000101110001110111111 0111001101010101010100110110110001110110101001111000010100000000000111110100001111100 0100000111100101011110010110100001110100011110100001000111110011100110000010001000001 1111000001101110100100001111000000101101000100101010110111010001011100011101111110111 0011010101010101001101101100011101101010011110000101000000000001111101000011111000100 0001111001010111100101101000011101000111101000010001111100111001100000100010000011111 0000011011101001000011110000001011010001001010101101110100010111000111011111101110011 0101010101010011011011000111011010100111100001010000001011010000111010110100010111000 Thank you @_jacobtomlinson https://jacobtomlinson.dev