 Welcome to the Ruby Wasm Kubernetes talk. I'm Kingden Barrett, and let's get started. So this is a lightning talk, so I'm gonna try not to talk too fast, but I don't want to lose anyone. There are many twists and turns here. I've got these guys at the bottom that are gonna try to help keep me honest, and it seems we were already a minute behind, so I'm Kingden. You can find me on these social media platforms now. YouTube and Mastodon, I'm a developer experience member of the WeWorks developer experience team, OSS engineer since 2021, and the S is for open source support. I work on Flux, you can find me on Slack as well, Community Maintainer, and I was a Flux V1 maintainer. You can also find me at the Flux Bug Scrub, which is my weekly event. We do support things there, and I try to use all of our open source as deeply as possible and lean into open source solutions. This is an open source support engineer, so that's what the job does. Also, you can find more Flux Talks. Today is almost over, but we have OSS Summit things happening for the rest of the week, so check out this QR code, leave it up for a second, okay? And also this is a little bit more about me. On YouTube these are the things I do. One of the things is live coding, Ruby and Kubernetes things, so that will become relevant later. So what are we here for today? What is untrusted code, and why do we want to run untrusted code? I do not trust my own code. So that is part of the answer to the question. So can WASM run Ruby? Is the first question I'm going to ask, and yes it can. But after I explored the topic pretty thoroughly, I came to the conclusion I'm not sure there is a good reason to do that, at least for the purposes that I intended. So do you know why you want WASM? Do you know why you want to run Ruby in WASM, if that is what you want at all? I'm not sure. So I think these are the reasons to use WASM. It is a secure foundation that you can build on and you can build portable artifacts, and you can have a degree of language independence. I will see a little bit about how that's limited, especially from a Rubyist perspective. So I cannot sell you on WASM. So if you don't know why you want WASM, you're gonna have to go to another talk, but please stick around. But know that if you take the WASM, I will get nothing. There's no commission for me. I am not paid by WASM. I don't know how they get their money. But let's find out. So why Kubernetes? Well, for Flux and GitOps, those are the reasons for me. If you chose Kubernetes, you already know why you did it. It is not a simple choice. But there are declarative and versioned and immutable artifacts that describe a desired state. If you're new to Kubernetes, self-healing infrastructure, that's the reason why. About compiled languages. So these are some compiled languages that you can use with WebAssembly. And if you're interested in using compiled languages, I promise you there's value for here as well, even if you're not a Rubyist. So, my history as a Rubyist, I have used Ruby since 2002. Thank you, Ivan, my friend at IRC who built a Ruby chat bot with me. Got my first permanent job at a company called Metrics Matrix in Rochester, New York, and my second, both of these were Ruby jobs. University of Notre Dame, Office of Information Technology. That's where I live now in South Bend. So why Ruby? Well, for me, I know Ruby really well now. And I can use it for most of the problems that I come across. Has great debugging experience. Bundler, I don't know other languages that have great tools like bundler for dependency management. Ruby fibers are pretty new at this point. If you think that Ruby is a single-threaded language, well, you're right, but fibers make concurrency pretty easy even with a single thread. And for minimum viable products, I think you can't beat Ruby to get your product out the market faster. So what are the types of things that we will typically use Ruby for? I think the number one answer is to run a website. And probably the number two answer, subsumed by the first answer, is to connect to a database. Maybe scrape content from the internet, build an IRC bot. There's no compiler needed. You can do all these cool things. One thing, though, all these things are much harder in WebAssembly. So what did I think would be a good idea for this project? Let's build a Kubernetes operator and try to run it in WebAssembly. Well, why not? So here's where I started looking. I realized that Ruby is an interpreted language after some of the things that I went through and that makes performance in WebAssembly a little bit difficult because you never actually compile the Ruby. So you have to bundle it with a full Ruby interpreter. So if you thought you were gonna build a small WebAssembly and, well, you have to pack your Ruby code in with it because the VFS, the way the VFS works, this is not for the web. You're gonna send a 35 megabyte file so they can run a 600-byte Ruby script. That's silly. But these are some gems that you can check out that will help you get started in WebAssembly and Ruby. Wasmar, Ruby, and WasmTime. These are the gems that I use to produce the examples here. And you will run WebAssembly in Ruby. That's what I think you will do. So what is a WebAssembly is a runtime format and you can build applications with it and you can build libraries with it and you can include them in other programs. So this is what I really thought would be a cool thing to try. Why not run Ruby in WebAssembly in Ruby just to see if it will work? I could not make it work. So let's try something else. So WebAssembly is, I didn't think that I did not know WebAssembly going into this talk. I had to learn how does it work and those examples are great. Wasmar, I found, had the best set of examples, I think. So these are the types of things that you'll do with WebAssembly. If you're not familiar with WebAssembly, you can call functions that are in your WebAssembly library. You can export a function to the WebAssembly library so you can call it from there. You can ship memory around. You can use a compiler. I was looking for hello world. This is really a lot. But there's a thing called the system interface, wazzy. That is very helpful and I found that helped me solve a lot of the problems that I encountered when I was trying to use WebAssembly with Ruby. So what is the system interface? Well, systems are file systems or standard IO. Those are pieces that are not part of WebAssembly natively or remote connections. So these are things that you can get through a runtime environment for WebAssembly. So waggy is an extension off of wazzy that basically you use it as a web server, but you offload the responsibility of handling connections to another process. So these are things that you cannot do in WebAssembly in my experience. And I hope that someone corrects me if I'm wrong, but there's no string type. And that is a tough limitation if you're trying to work with WebAssemblies and Ruby. You have to use numbers and well-defined data structures only. That's very hard. You have to allocate memory, you have to make pointers, you have to pass pointers with string size if you really want strings. I don't wanna do any of that. So I decided to use, not WebAssembly as a library, from Ruby, I decided to use wazzy instead. So I needed strings, I reverted to wazzy and we can parse the output of our WebAssembly. We can pass in a file, in a file system directory. Those are examples that you'll find in the wasmer and wasm time examples. So let's try to solve a real problem with WebAssembly and Ruby. What is spin? This was my first entry point to wasm. And it is basically, the marketing material all says it's a serverless thing. You all know serverless is not a thing. It runs somewhere, but what does serverless mean in the wasm context? It means that you will shut down when you're done. I think that is where you get most of your performance gains from wasm, by not running it when you're not using it. You also, in spin, you can test locally. There's no Kubernetes needed. You don't need to link your wasms together. It works sort of like if you're a Rubyist, a controller or a router, if you're not. So you can map WebAssemblies to particular paths and you can call them from each other. You can call them from the website that you serve up. So we're gonna serve up a website, right? So where are we gonna run it? Well, we're not gonna run it on Fermion Cloud because this is open source summit. Actually, this is not open source summit. This is GitOpsCon, but we're not gonna run it on HippoFactory either because we already have Kubernetes. And if you try to sell me a HippoFactory after, are you serious? Come on. HippoFactory is the open source version of Fermion Cloud. Excuse me. Okay. So we're gonna run it on Kubernetes. This is GitOpsCon after all. And these are the things that we hope to gain by using WebAssemblies. We want testability, reusability, type safety between our languages. Maybe that one doesn't apply so much in Ruby, but we have the capacity for polyglot teams to work together with WebAssembly. That's what this buys us. So if there are specializations, if there are things you can do especially well or especially easily in a different language, you can access those things. If there's another team that uses that language, they don't know your language, you can work with that team. This is great. So I built some things. And I did this to help me break my misconceptions and understand what I was doing. And I tried to follow some good examples. Like I said, Spin is a great example. They have tons of examples for Ruby and they will help you understand the limitations. If you read every document from Spin, I think you will not regret a second of that. So how are we gonna use it to solve a real problem now? Well, this is a problem that we have in my organization. We need to know how many downloads. We use OCI packages to publish our software. And GitHub has a number on a page that tells you exactly how many downloads at that moment in time, but it doesn't seem to be exposed on any API. So if we clicked on this link, we would see that number. I need that number. We're gonna parse it from the HTML. Easy. So I built an EKS cluster. You can find the definition for that here. I built a blog service. It does not run Ruby, but this is one of the Spin examples. It's called taking Bartholomew for the Spin. Bartholomew, if you haven't read the Spin docs, is Spin's blog example. It's really nice. It's like Comparable to Jekyll or Hugo. And I wrote a Helm chart. And I began to understand why there is pain. Fermion, if you don't know the history of Fermion, Fermion was founded by a guy who was at Azure. And before that, he was at Deus. And they are Kubernetes people. It was my impression, at least for a long time. But they're not using Kubernetes and they're not using Helm. They actually invented Helm. Matt Budger is what I'm talking about. So I said, all right, we're gonna build an operator. And I followed the examples until I thought I knew everything I needed to know. And here's what I wound up building. So in Ruby, we're going to fetch from the URL. We're gonna write it to a file. We're gonna pass in that file system context to a web assembly. That web assembly is written in Rust. And that is an HTML parser. And then we're gonna return a number, but we're gonna do it as a string because I want to parse a string. And that's web assembly, WASI, right there. That's what we're using for that. So once we parse the number, since this is Kubernetes operator, we're gonna store the number we parsed in status in the CRD. So there's a CRD. If you go through this example, you'll find out about that. And we'll come back and retrieve that data later from the status of the CRD. So writing an operator in Ruby, actually super easy. This is the gem. It has a wonderful example. It's about one page long. If you've ever tried to learn controller runtime, it's a bit longer, the controller runtime book than one page. This was so easy. And it works. And it's based on a library called kube-client, which also works and it works in a delightful way. And it is well maintained. If you look at the Kubernetes operator, that's not maintained. It hasn't been updated since 2021. But kube-client is maintained. It has server-side apply only, which is great. And flux uses server-side apply too. If you don't know what that is, you can apply a Kubernetes YAML and then wait for the things in it to become ready before you close your connection, get a response. It's not asynchronous anymore. This is great. So that is all, almost, except that there is so much more. And if you are here for tomorrow, there will be a longer version of this talk with actual code that we can see. You can click on all those links or follow the links one way or another. And there will be a third demo on Thursday, where we won't be using Ruby at all. It will be Go and TypeScript. I have a co-presenter for that. By the way, the operator that I talk about is about 98% finished. We're going to finish it tonight. We'll find out how it went tomorrow. And the progress I have is about 98%. So I did it live on YouTube. I'm gonna do the rest live on YouTube as well. If you have any feedback to provide or if you're interested, you can make the demo tomorrow with me. This was my first Rust app. So Spin and Wesum inspired me to learn a little bit of Rust. I think that was pretty cool. So thanks for coming. And please visit us for the rest of the week if you're here for OSS Summit. And here are the slides. And there's a QR code you can follow if you wanna find the slides. And that's it. Thank you.