 Thanks everyone for coming. This is overwhelming with all these people showing up at this workshop. I'm sure all of you have high expectations on getting to learn about WebAssembly, getting hands on WebAssembly. So we will do our best to live up to those expectations. We're going to be at least four people presenting as we go along. We have Kate, David, Joe. My name is Mikkel. And we will try to help you the best to get you through this workshop content that we created. We also have a few more colleagues around. Three of them over there, one of them over there, waving his hand. If you have any questions or anything, get stuck along the way. Just make signs, and we'll try to get to you and help you. We also have microphones in the room. There's one over here. There's one there. Feel free to go up to those if you have questions and we can try to answer them here from stage. OK, so let's get going. We're going to do hands-on with WebAssembly, microservices, and Kubernetes. And the objective of this for you is to get hands-on experience. Services at WebAssembly, we're going to talk about the spin framework. We're going to talk about Ron Wasi. And we're going to talk about Kubernetes. So we've set up a GitHub repository that has all the content you need to go through the workshop. There's a QR code here that will take you there. There's also the repo address. And basically, we try to figure out a way where we can do this at your pace. So there are two options you will get. You can come up with more options yourself if you want. One is, head over to the repo. Start doing the stuff. All the instructions that you need to get through the workshop are in the repository. If at any time you get stuck, as I said, raise your hand or anything, we'll have people that will come around and try and help you move forward. So if that's what you want to do, go ahead and do that. You also have this option to listen to me if you think that might be interesting for at least 10 minutes doing a little bit of introduction of WebAssembly. If you're not familiar with WebAssembly or if WebAssembly is fairly new to you, I will walk through that. And then you can either go back to one and do stuff on your own. Or we will also follow along in doing the workshop from stage, so going through the individual exercises so you actually have a chance to experience that as well. So choose your own path through this adventure. As I said, we have an hour and a half together here. Lots of people to help. And we hope we get some good content and some good experiences with you along the way. OK, so I'm going to talk a little bit about what WebAssembly is. It is a specification. It is a specification of a binary instruction format. It's signed as a portable compilation target. That sounds complex, to be said. But I'll try to unfold that a little bit what we mean by that and how that works in practice. Another thing just to be aware of as we go through this, if I at any point in time say, Wassum, it's just another name for WebAssembly. It's the same thing that we do. So let's get back to that compilation target thing. What does it mean to compile and run a WebAssembly and what is it? So WebAssembly being this common compilation target for a lot of different programming languages, you always start with some code in some language that has some level of degree of support for WebAssembly. And I'll get back to that in a little bit what that means. Now, once you have built your code or written your code, you compile that into a WebAssembly. And depending on the language and the tool chain, there are something you can and cannot do. And that will create that binary format, the WebAssembly or the Wassum file. Now, in order for you to run the Wassum file, you need a runtime or virtual machine. So when you run that, your Wassum binary is going to be run by that virtual machine. And there are various ways you can do this in. There are various options for runtimes and virtual machines. And there's also options of whether WebAssemblies are going to be or the WebAssembly is going to run inside of a browser, or the WebAssembly is going to run outside of the browser. So a little bit around that language support, like across a lot of different programming languages, and in particular, the top 20 languages from RedMonk Surveys at Fermion, which is the company that I work for, we have created this WebAssembly language guide that sort of gives you a good indication of the level of support that you have for your preferred programming language. There's a link up here to how to get to that language guide, and you can sort of start diving into what level of support you would have for the language that you're interested in. By the way, the GitHub repo QR code is at any point in time. You get tired hearing what I'm saying. Head over to the GitHub repo and do the workshop. All the instructions are there. You can do that as you go along. So I also talked about the runtimes, not only the language and what type of support you have for the individual languages. And there are basically two different types of runtime that exist for WebAssembly. One of them is the JavaScript-based runtime, and then you have the WASI-based runtimes. Now, the JavaScript runtimes are where WebAssembly originates from. So it's about being able to extend the number of programming languages you can use with inside the browser. And because those WebAssembly interact with browser APIs and through JavaScript, there is a tie-in to having JavaScript sort of being the glue code between the WebAssembly and the actual browser APIs. So this is the type of WebAssembly support you find in JavaScript engines like V8 and SpiderMonkey, which are being used across the browsers that I'm showing up here and some of the frameworks like Node.js and Dino as well. Now, we also have these WASI runtimes. And the WASI runtimes were designed to also take all the power and all the potential of WebAssembly and sort of not be tied into that JavaScript dependency that you have when you run inside of the browser. And as the WASI specification has been built out and emerging, a set of runtimes that are WASI-compatible runtimes have also emerged. Amongst those are WASIN time, WASMA and WASMETCH as some of these examples. So you can see how when I think part of the introduction, I use the word server-side WebAssembly. Basically, those are the WebAssemblies that are compatible with WASI and will run outside of the browser. So we sort of have those two types of WebAssembly, the things that can run inside the browser and the things we can run outside of the browser. So use those for servers and those types of scenarios. So the WebAssembly system interface, which is what WASI is an abbreviation for, is really giving those WebAssembly a POSIG-like interface, your conceptual operating system, whatever you wanna call it, but it gives the WebAssembly the ability to have access to things like file systems, sockets, random numbers, and other things that you need if you wanna run, like things that don't exist inside the browser, right? Those are the things that have been built into these WASI runtimes. And why is this a good idea? So if you think about what's the design principles that you need behind any type of code you need to run inside of the browser, there are four very specific things that needs to be true for any code to work well inside the browser environment. First of all, you need that code to be portable, right? Like you don't know if the browser runs on a Linux operating system, if it runs on a Windows operating system, Mago is whatever operating system. You don't know that, but you wanna have that binary being able to run regardless of what operating system the browser is on. You also wanna have it be independent of the processing architecture, the processor architecture that is underneath that operating system. The second thing is you need things to be really secure. You need those things to execute in a secure, isolated environment because any code that run inside of the browser is basically untrusted, right? You download it directly from internet and you don't wanna have that be able to escape the browser and the sandbox it runs in. You want them to be small because everything is downloaded over the internet or other types of network before you can start executing them and you wanna have them to be really quick in startup times so that the experience of running that application that actually comes remotely is like running something locally. Now, if you think about WebAssembly being designed for those four things to be true when running inside of the browser and start thinking about those will actually be really good as capabilities and properties to have on the server side as well. If you think about being able to write microservices that are portable across operating systems and processing architecture once you build it that runs in these isolated sandboxes where you have a capability-based security model meaning not until you actually run the process or the program do you exactly describe what type of resources that program can access. So for instance, access to files. You also wanna have them small so you can quickly move them around in your distributed systems or your distributed architectures and you wanna have them being able to quickly start up as they move around. So those are really some of these core benefits that we get from WebAssembly and that makes them really, really interesting as a technology to run outside of the browser. So what type of options do I have for running these WebAssembly or the Wasi-based WebAssembly outside of the browser? Well, you can just use a runtime. And what I'm trying to illustrate here is that if I build or wrote some code in Rust, I would use cargo as the command to build my Rust WebAssembly and I will tell cargo to give me an output of a Wasm32 Wasi compatible build. And then I can use a WebAssembly runtime like WasmTime to run that WebAssembly. That is pretty straightforward, right? We build some code into a binary, we use a runtime to run the WebAssembly. And it, but it doesn't give us, you know, a lot of benefits in terms of, you know, we hook into the thing of things being portable, being small in size, being quick to start up and the security and all of that. But it's, we were sort of on our own there, right? But you can definitely do that by using the runtime. You can also choose to use a framework and spin is an open source framework that we build at Fermion that helps you easily build microservices functions as a serverless types of applications. So if you move into a world of a framework like spin, you'll start using spin and interact with spin. In this case, there's a Toml file that describes your application. You can build your application using spin. You can run your application using spin upright. It's just a framework to build applications that happens to use WebAssembly because of all of the benefits we get from WebAssembly. But there's also this option of getting your WebAssembly into Kubernetes. And there's a project called Run Wasi that in particular, some of my co-presenters from Microsoft have been help bootstrapping. And what that enables is it enables you to package these WebAssembly in OCI-compatible containers and deploy them into your Kubernetes cluster. So now you start looking into the tool chain of using tools like Docker to build container images, push them into registries, and then use tools like QCTL to go and create these deployments and get them into your Kubernetes cluster to run. So all of these are just various options of working with WebAssembly and using WebAssembly. And to prove a little bit of a point, I know this is just slides, but trying to prove the point about some of those benefits you get from WebAssembly on the server side, particularly related to size and why you wanna do these compared to doing what you would do with a lot of applications today that you build inside containers and run inside your Kubernetes cluster. I have two Docker files up here, and we actually just tested this an hour ago or something to get some of the numbers. What the Docker file you see on the right-hand side is sort of what you normally would expect from a Docker file, right? You have a base image that contains, in this case, a Python framework. You copy some requirements stuff in there for what you need for your Python application to run. This is a Flask application, by the way. And we go and install those requirements and we copy the app in and we set an entry point and now we have a container that can run a Flask application. What you have on the left-hand side is a WebAssembly Docker file. And all we actually need in that Docker file is we start from scratch, which means it's an empty container. We copy that spinTumble file in which sort of an application manifests and then we copy in the WebAssembly binary that we need to run our application. And if you compare the output of these two containers, the red purplish thing on the right is sort of meant to be the scale of the size of that container. That purple thing over there on the left-hand side is the size of the WebAssembly container. And to be more specifically, the Flask application is a 32-megabyte file, Docker container, sorry. The spin WebAssembly here is 550 kilobytes. So I hope that gave you a little bit of that interest in terms of how the sizes and these things might be interesting for you to look at in terms of how you wanna compile your server-side services into WebAssembly format and give you some of those benefits. Okay, so that was the introduction that I wanted to you. So if you wanna break out and go through the workshop yourself where you will be getting the tools installed on your laptop, you get to try and use spin as a framework to build WebAssemblies. You get to deploy spin applications into Kubernetes cluster. In this case, we're using key K3D. And also go back in part three, we're gonna go back and build our own spin applications from scratch, get them into Kubernetes clusters. And finally, part four, Kate will do her magic with the magic K8s ball and Azure Kubernetes service and everything coming together with real applications and stuff like that. So feel free and go ahead with the workshop. I will now go through part zero and part one on getting machine set up and getting started with spin. And again, make sure if you are stuck at any point in time or anything, raise your hands, stand up, and we have people in the room who will come and help get you moving forward. Okay, so I've opened up the repo here. Do I need to zoom additionally? Is it okay? More soon? Yes, no? Okay, let's try this. Okay, and basically I'm gonna look at this first setup file. And what we wanna do with this setup file is we wanna install spin and we wanna install a set of templates and some requirements to be able to work with JavaScript in this case. Throughout the workshop, I think we have instructions for JavaScript, TypeScript, and we have instructions for Rust as well. So you can sort of choose your own path and if you wanna be very explorative, try using things like Python, C sharp or Go are also options. You should be able to complete the workshop as well using any of those languages. So what I'm gonna do here is I'm gonna pull up my terminal and I'm gonna put my terminal on top and then we have the instructions down here and then hopefully we can follow along. The way we're gonna install spin is basically by running this fast script. If you wanna go and find the install instructions for spin for other programming languages, if you go to developerferment.com, you'll find all the documentations for spin on that side. So what I'm gonna do now is I'm gonna run this fast script to install. You can see I'm gonna get spin version 1.1 for my operating system and architecture. And I've downloaded this now in my local directory and I'm just gonna move it into my bin directory which I know is in my path. So now if I can get the password right, I should be able to run spin and check the version and I can see I have spin 1.1 installed. So there's a few templates here that would be good for you to get. Like the first command is not necessary if this is the first install you do of spin but if you've had older versions of spin installed at this point, you can basically go and update the default set of templates. So you can see I now have various templates for various programming languages. And what I also wanna do in this case because I'm gonna go through this using the JavaScript SDK is to get JavaScript templates installed. And you can see I now have a JavaScript HTTP handler. I got back to the HTTP handler a little bit and a TypeScript version as well. And we're gonna install yet another template which we will be using as we go along in this workshop. I think you get the idea by now that spin has a concept of templates. I can unfold that a little bit later but basically those are a lot of the boilerplate code that we would need to write microservices where we use framework like spin. And the last thing I need is specifically in order to be able to compile my JavaScript into WebAssembly, I need a plugin for spin that will help us do the compilation from JavaScript into WebAssembly. So now that I have all of that installed, I need to make sure that I have obviously the tool chain that I need for the programming language I want to use. In this case as I'm using JavaScript, the only thing I need to make sure that I have installed is NPM. So if you want to do JavaScript as TypeScript, you need NPM. If you want to do Rust, make sure obviously you have Rust but also that you have the Wasm32 was a target installed. Again, in the repo, if you follow these links, you should be able to get to the instructions that will actually give you those two chains. Okay, that was getting set up, that was easy I think. So now we can move on and we'll start working a little bit with spin. But before going into spin, it's gonna spend a few minutes talking about what spin is. So as I said earlier, spin is a framework and it is a developer tool. If you wanna build WebAssembly microservices and web applications, it's an open source project that we bootstrapped at Firmian and have contributions from various parties at this point. Spin very recently released in a 1.0 version less than a month ago, where we believe that the core pieces of spin, which is the runtime, the application model and those things you get, are at a stable enough state for us to declare that 1.0. And we actually released the 1.1 version just a week ago. The idea behind spin is to take some of those benefits we get from server-side WebAssembly that I talked about earlier, for the ability to speed, size and security. And really just create a very nice developer experience and create a nice operations experience around how you deal with these WebAssembly and how you can operate things in a much better way than what we do today. So what does spin contain? Spin is a whole lot of things. First of all, it's a runtime that has an application model, right? So there's a specific, you can call it more with the prescriptive way of writing applications, which is based on what you serverless functions that you would probably know from services like AWS Lambda or Azure functions. So on the spin news side where you bring in your code, we create these templates for you that makes it really easy for you to write just the code that's needed for you to handle the business logic. So spin has this triggering model where every application has a particular type of trigger that it responds to. Typically that would be HTTP requests, but it could also be monitoring a Redis message queue or other type of queues. Spin triggers is an extension point so you can build your own type of triggers depending on what type of events you wanna monitor. And the idea is that the code that you write inside of spin is basically just the code that is needed to handle the information that comes in with the trigger. So in the case of an HTTP request, spin hands over an HTTP request to your code and expect you to return a response. So the only thing that you have to write in terms of the code is what's actually handling that HTTP request. Everything else is taken care of in spin. And because we have WebAssembly being these small binaries that can start very fast, the model of spin is that you can start thinking of the URL structure of an application where various paths are being handled by various independent WebAssembly binaries. So if I go to slash API, something that will be one component and slash API something else will be another component. And those components because of the WebAssembly, the way the WebAssembly's work could be written in any programming language because they all compile down to the same format which means when we run them, it's all just WebAssembly. Whether it came from Python or came from Rust or came from JavaScript, we don't care the time it's WebAssembly. And because these things start up so fast that they do, those modules are not being loaded until the actual event that needs to be handled by a certain module is happening. So imagining I had those two different components listening to different paths of the URL structure. If a request come in that matched my structure A, we would load that component, hand over the request, request is being handled, components being unloaded, and nothing is happening until a new request comes along. And we can do that because WebAssembly starts so quickly as they do. And we're gonna show you that and you're gonna experience that as well if you start building out these applications. So SPIN has those kinds of concepts of how you build applications and using SPIN new, you saw all the templates that are installed. It's easy to do HTTP based in all these different programming languages using any of those templates. Now, as a CLI tool, there are sort of these convenient command of using SPIN build that basically enables you to easily sort of hook into the tool chains of the languages that you use. So if you use Rust, it'll help you run your cargo builds. If you use JavaScript, it'll help you run your NPN commands, and so on and so forth. And finally, there's a SPIN up command that you can just use locally. And this is where the SPIN runtime comes in, which is using wasm time. That is the wasm compatible runtime that's built inside SPIN. And basically SPIN up is the command to run your application, right? So if you wanna run the application locally, you would run SPIN up. As part of that whole, making things simple, being able to distribute these applications as OCI images through things like docker hop or the GitHub container registry, being able to integrate with storage technologies such as Redis or the building key value store that we have in SPIN is made really, really easy and also to help with the whole supply chain security you can go and sign your SPIN builds and making sure that once you start running them, they're actually the right binary that you wanna run. And finally, the output of these SPIN applications, you can then run in various places. I mentioned Kubernetes earlier through one WASI, you can run them locally. And we're also running a managed service and managed cloud called Fermion Cloud where you can push these applications and run them there. So that was the introduction, the quick introduction for SPIN. And I'm gonna go ahead with that next part of the workshop now, which was basically just building a SPIN application. So we got set up and got SPIN installed. We got our templates installed. I have NPM installed so I can do JavaScript in here. So I'm just gonna scroll down to the JavaScript section of this first. Part of the repository also describes a little bit of the background here. You can see that I'm mentioning of how JavaScript and TypeScript works with, or uses QuickJS as part of the runtime. So if you wanna dive further into these, there are some good references in here. Okay, but the thing we wanna do is we wanna run a SPIN new command. And SPIN new is creating a new application for us. And so in this case, well, we're gonna do a TypeScript and already have the command in here. So we're gonna create a new SPIN command. We're gonna use the template called http dash ts. So this means this is an application that is set up to be listening to HTTP requests. We're using TypeScript. We're gonna give this application a name and we're just gonna accept the defaults for that template. Otherwise, we would have been asked for a few prompts about what you wanna call this component and other things. Now, this is now gonna be created for us in a directory that is equal to the name of the applications. I already changed directory and went into that. And I could go ahead and as you see below, I can do a tree command. And these are the files that the template has put into this directive for me. So a few things to point out here is that there are the files that are all part of building the TypeScript application. So I have a package JSON file, which are my TypeScript dependencies and libraries that I use. And then I have my index TypeScript file. I have some TypeScript config file. And we're also using webpack as part of how we compile TypeScript down to web assembly. The other thing we have in here is a spin.toml file. And the spin.toml file is what describes a spin command. So I'm just gonna show you this, my editor here. And the spin.toml file basically have two sections. There's a section which is like one to six that you see. That is a set of metadata around this application. So I put myself in as an author. I can add that description for the application. It has a name. You can see I have a trigger type defined here being HTTP. And I can also version this application. The other section of spin.toml is a list of components. So I can have as many components as I want inside an application. To begin with, when you use these templates, you always get one. And the one is the one that aligns with the template that I was using. So a few things to call out down here. First of all, line 10, you can see the source. So the source really means this is the WebAssembly module, the WebAssembly binary that will serve this component. So the implementation of this component in my application is gonna be the WebAssembly binary that will be in the target directory with this particular name. Now that's the one that the JavaScript, or the TypeScript, sorry, is gonna compile into. And the way that it's gonna compile into that is by using the command that you can specify here in component build. So basically, this sort of bridges out and uses NPM to go through the JavaScript to WebAssembly compilation. Had this been in Rust, this is where I would have been around my cargo command. Had it been another programming language, it would have been the tool chain that sort of fits in with those programming languages. And then there's some other things in here that are related to the trigger type. In this case, because it's HTTP, I need to define the route of the URL that this component is serving. And in this case, it serves root and is a wildcard with the three dots, which means that any request coming into this application will be served by this component. So that's all I have in here. And if I just go and look at the instructions, the next thing we're gonna do is we're gonna run that spin build command. As you can see, this is calling out to my NPM and thus I'm pretty sure I actually need to go and run NPM installed to begin with. So let me just do that. I don't know if we have that in the instructions, but if you run into this issue with TypeScript, the JavaScript, you need to run NPM installed. And then I can do my spin build at this point. So what we do behind the scenes, not behind the scenes, but what we do to get JavaScript into WebAssembly is that first of all, we use WebPack to actually create a single JavaScript module out of the JavaScript files that we may have created, or the TypeScript files. I use, sorry, I know this might be a little bit ignorant, but I tend to use TypeScript and JavaScript interchangeably. So sorry for anyone. Just barrel with me there. But we use WebPack to create a single module as an output. And then we use this spin plugin called JS2Wasn that will help take the output of that module, which is in distspin.js, and actually create the WebAssembly file. So if I go in and check the target directory, we should be able to see that we now have that WebAssembly file here. So we now have our WebAssembly binary created. And then the next thing that I can go do is I can run the spinup command, which will start my application. Actually, before we do this, let's take a look at what's even in this file. So this is what the TypeScript template gives you by default. So we're imparting some functions and classes from our Fermion SDK. So the spin SDK, sorry, not the Fermion SDK, the spin SDK. And then what we expect for you to implement is this handle request function where we hand over an HTTP request to you and we expect you to give us an HTTP response back. That is all that's been asked for you. So basically in this code, we're just straight away returning 200 with a foobar header and hello from TypeScript. We could go ahead and say hello from KubeCon. Let's write that file. So this is basically all I have to do. I had all the boilerplate set up. I only have to figure out what do I want to do with that request once it comes in and how do I want to return that. So now I need to go back and do my spin build again. And once that's built, we can do spin up. And the next thing we can do is we can call in and see local host. There you have it. Hello from KubeCon. We have our headers being set. And basically we now have a spin application running where we can start doing HTTP request two and we'll see how the request comes back. I'm just quickly gonna check. I don't think there's a lot more in here. So that is what we're gonna do in this exercise one or what you can do in this exercise one. So we have the spin C line stalls. We have the templates in there. We're able to build and able to spin up our applications. And now you're using WebAssembly. It's as easy as that. So before moving into part two, if there's any questions at this point in time, feel free to go to the microphones. We can take some questions, try to answer them here from stage or if anything, just raise your hand and we'll be able to stage question or just help. Would you mind going to the microphone? Thanks. Can you hear me? Okay. So my question is a little bit generic. It's regarding WebAssembly. So for runtimes that have, let's say, RLIs like Go or Rust or things like this, does the WebAssembly runtime, do they allow running on multi-core and do they preserve the concurrency primitives that these runtimes support? I'm gonna, yeah, we're gonna point to Till over here. He's gonna help answer that question. This is why we have more people in the room, by the way. Good question. WebAssembly does have multi-threading support and in browsers you can use that today. No, sorry, I was trying to get to the technician by hand, you just go ahead. In browsers you can use multi-threading today, but that is kind of deeply integrated with how browsers do multi-threading using the web workers concept. Outside the browser in environments like Spin, there is a proposal for an interface called WASI Threads and the wasm time runtime supports that but that is very much emergent right now and it is not compatible for the time being with some other techniques we're using for this WebAssembly component model and that means there is still some work to be done but obviously that is a very important aspect. We do need multi-threading and we are working on making that possible in environments like Spin. So just to continue with my question, does that mean that, for example, a Go application that has multiple routines, does it mean that it will just preserve its semantics but it will run in a single process? Yes. That's it, okay, thank you. That's a pretty similar question. So it's also about threading but also about blocking calls. So what happens if I block in my Hello World application right now? If I have another blocking call or just sleep one second or something. The question was how do we handle blocking operations and since we don't actually support multi-threading inside your Spin application itself right now, you can do a busy loop. You can do a while loop that just does something for a second but that's, I mean, if you do have a computation then it'll just run for that time. If you're waiting for IO to happen in that time then you do a blocking call to IO but we actually suspend your application. We stack switch away from it on the host side and it doesn't use any, there's no Spin loop going on despite the name Spin and instead it's actually completely dormant at the time and we can process other requests while the IO wait time is happening. And there's one more short follow up to the threading conversation which is in Spin we handle the multi-threading, a handling of requests outside of the WebAssembly module so that you have a listener that listens for HTTP requests and for each of those we spawn a green thread so that each you can have like as many parallel computations happening as your computer can handle. So it's all happening outside of WebAssembly. Just testing, okay, works. Hey everyone, I'm Joe, I'm a stuff engineer from Microsoft and I'm a maintainer for Ron Wazzy. Ron Wazzy is a CNCF project part of the Container D organization and it's a project that helps you to run Wazzy workloads on Container D and Kubernetes. So now we learned how to write your first Wazzy service that can handle HTTP requests with Spin and now let's learn how to run Wazzy application on Kubernetes. Well, obviously there is an easy way, right? You can just bundle the Spin runtime into a container, bundle the Wazzy module and the Spin config into that same container and you can deploy that to Kubernetes but in order to achieve the 40 times difference of the size that Miko just showed, you have to get rid of the runtime in the Container image and in order to do that, I will first explain how this whole architecture works. So when you first apply a POS back, the API server is going to schedule the workloads into a register node or multiple nodes and those nodes have KubeLat running on them as an agent but KubeLat is not the one that will put images. You will actually delegate the POS back into Container D which is a Container runtime. The Container D runtime will put image down but it's not the one that actually executes the containers. It delegates the test of execution into even a lower level process or runtime, also known as the SHIM. By default, there is a SHIM run C that can execute normal Linux containers but there can be multiple SHIMs because there are in fact just binaries on the node. So there is a run-wise project that is a SHIM implementation that facilitates running Wwise and workloads and then we build on top of it a SPING-SHIM or a slide-SHIM that can run different Wwise and runtime. Then the question is, how does Container D know which SHIM to run for a POS? Well, in a POS back, you can define a runtime class name and that runtime class name is going to tell Kubernetes this is a runtime class which binds to a specific SHIM that runs in Container D. So now we have a very typical POS back. This is a deployment and it's called Wwise and SPING. This deployment just fetches the SPING Rust Hello container image. In that stack, there is a runtime class name called Wwise and time SPING. So before we deploy this POS back, you have to deploy a runtime class to tell Kubernetes I have this handle for Wwise and time SPING and this handle is pointing to the SPING SHIM. All right, so that's basically the high-level idea. Now I want to work through the workshop. There are some prerequisites. Unfortunately, you have to install Docker and K3D and coop control. I have all of them installed so I'm not going to show how to install all of those, but you can click the link, go to their website and install Docker K3D as well as coop control. If you don't know K3D is K3S on Docker containers. So that gives you the local experience of running K3S. And K3S is a Kubernetes distribution for Edge and IoT devices. So to start a K3D container cluster, we have already baked an image that will give you the SPING SHIM. So I'm going to run this command and this is just starting a K3D cluster with the SPING SHIM installed. All right, it's created successfully and then we want to deploy the workloads. We have already provided you the YAMLs for runtime class for wasn't time SPING as well as the YAML for workload. If we take a look at this YAML, it defines two runtime classes, one for SLIDE and another one for SPING. And by the way, SLIDE is a runtime that we wrote for doing WISY clustering like key value and messaging. This is just to show you that the continuity can have different SHIMs installed on the local and they can choose what kind of SHIM you want to run. All right, so I'm going to apply this. All right, next step is to apply the workloads. And I will show you what does the workloads look like. So it creates a service and the deployment for both SLIDE and SPING and then the ingress for that. Apply this, ensure CRDs are in store first. Let me just apply this again. Sometimes you have to wait for a while or just wait for another five seconds. Okay, success. And then once you have the workloads, you can check the pods are running and both SPINGs like are running. And then if we wait for five seconds, we can test it out by doing curl. I need to wait a bit longer. Let's try this again. Hello world from SPING. And now we deployed a SPING application to Kubernetes. So the next workshop will use the same cluster so you don't have to delete this WISY cluster. If you have created one, you can keep it there. But if you are curious to know how to delete, this is the command. So in this workshop, we learned how to create a K3D cluster with WISON shims in store both SPING and SLIDE shims. And we have learned deploy a runtime class and workloads for WISON and we test it works. And now I want to turn this to Kate for the next workshop. All right, hi everyone. I'm curious. I'm kind of bringing everything together right now. So how many of you all have finished phase one of the workshop in the sense of you've successfully hit that happy path of a spin up? If you could raise your hand. Okay, that's awesome. Okay, great. And how many of you have just completed what Joe walked through of being able to deploy a SPIN application to Kubernetes? Okay, so what I'm now gonna walk through is how do we build our own SPIN application and now deploy it to Kubernetes? So bringing that together, instead of using a pre-built and pre-pushed and hosted SPIN app, we'll go through and do that ourselves. So I'm gonna walk through it, but if you still are working towards this point, that's fine, obviously we have the workshop online. So we've already created our cluster, so we don't need to worry about that. We've applied our runtime class as well. Also don't need to worry about that. Now we're gonna walk through the details of how we can use another SPIN plugin, like the ones that Mikkel mentioned, to package up a SPIN application that we built into a container and make it ready to deploy to our K3D cluster. So the first step we're gonna do is we're going to install that plugin. And we're gonna do this anywhere, but we'll see here that I already have my TypeScript application, so I'll be deploying that one to the cluster. So I'm just gonna navigate there. Great, and I already have it installed. Our next step will be just to do a SPIN build, and if you're doing TypeScript, remember our first step here is an NPM install if you haven't yet. And the one thing I wanna point out is if you have chosen to use Rust, what you're gonna need to do first, and I'm gonna show this right now first, is you're gonna need to modify your SPIN manifest or your SPIN.toml, because SPIN 1.1, we just brought out support for SPIN watch, which basically creates that experience where you can update your application and we will live rebuild it so that you get that automatic update of your application while it's being served. So if you did choose to do Rust in the first part, go ahead and delete this line because the SHIM is only supporting up to SPIN 1.0. Okay, back to TypeScript. All right, we're gonna do a SPIN build. We're familiar with that one so far. And now that we have built our application, it's now time to go ahead and scaffold a Dockerfile to be able to put this application inside of a container so we can transport it essentially and pull it down into our cluster. And then we're gonna go ahead and build that Dockerfile. So these are two separate commands. We'll do a SPIN kates, which is the plugin we just installed, scaffold. And here's where you're gonna point to your container registry. If you do not have one, that is fine. Just do this ghcr.io slash my registry, use a fake one. It's fine by default. It's going to do a, it's by default in your Kubernetes deployment. It's going to do an if not present on that pod. So it'll be present into your cluster, so you'll be fine. So we'll do a, for me, I'll do ghcr.io and then I have my registry. So now we can see that my Dockerfile was created and so is my deployment. Let's go ahead and look at both of those or at least the deployment. So you can see here that I have, I'm going to deploy three replicas of this TypeScript application to my cluster. I'm going to use that runtime class that we applied and we're gonna point to an image that I'm about to push to my registry. We're also gonna create a service so that we can point to it and the service is going, we're going to hit it on the path of hello TypeScript. Great. Now we're ready to go ahead and build that Dockerfile. So SPIN kates build. And this next step is the step that I was referring to a little bit earlier. So if you do not have a public registry, what you'll want to do is go ahead and import that image that you just built locally, the ghcr.io slash my registry into your K3D cluster. So you'll want to follow this command here and I'll make this a little bigger. You'll want to go ahead and follow this command if you do not have a public registry that you're pushing to making public and pulling from. I do and I've made this image public. You're also welcome to use this image if you don't want to go through the build process. So now we're ready to go ahead and deploy it to my cluster. Just want to confirm that it's running. Great. Runtime class set up, wonderful. All right. All right, these are being created and we're just gonna watch for these to get ready. Awesome, they're running. Okay, so now I'm just gonna go ahead and curl the application and hopefully we get a hello from TypeScript. Awesome. So now we have successfully built our SPIN application. We packaged it in a container, we pushed it up to our registry or kept it on our local registry and we've deployed it to our Kubernetes cluster all using the SPIN Kates plugin. I think that is all had to show this part. If you would like to see what you can do that is above and beyond with SPIN, the next thing we were going to show is how to do even more with a SPIN application and see something more real. We've seen all these different ways of saying hello world and all these different programming languages but it'd be great if we could see an example of a fun application. So this slide is not really necessary but okay, I did all of that to show you this one slide but it's exciting to me. So why don't we build a SPIN application that is a magic eight ball? And the part of this is of course it's great to ask questions and get answers to them and know exactly what to do with your life but beyond this, this is an extra magic eight ball if you're not familiar with magic eight balls what it is is it's basically an eight ball that you see in pool and then it has a dice inside it that has these random sides and you ask it a question and it gives you an answer but what I personally would do when I was younger is I would just reshake it until I got the answer I wanted. We're not gonna allow that. So we're going to use SPIN's key value store feature which will basically make it so that when you ask our SPIN magic eight ball a question we are going to store the answer that it gives you so that you may not try to reshake it to get a new answer. All answers are final in this magic eight ball. So we have a workshop that walks you through this it's a separate workshop and we link to it from the workshop we just showed and it has various steps that build up to this final application of a SPIN magic eight ball. So first you start off by making a JSON API that basically you can query for a random answer and it will return you a random answer. Then we move on to talking about how you can add files to a SPIN application and so we add a front end to our magic eight ball app that way. And then we move on to talking about how you can deploy this application to Fermion Cloud. So if you're interested in learning about the SPIN deploy command that Michael introduced you can do that next. And then we talk about how do we do this or we persist these answers that our magic eight ball gave us with the key value SDK and SPIN. And then finally we deploy to Kubernetes. So I'm going to zoom forward to this final version and just show you what it looks like. And then if this is tantalizing enough you can try it if there's more time. Okay, so you'll see that the prerequisites are all the same that we've seen. We should all have a lot of these locally already. And then the one other thing I wanna say is that I have also deployed this application to AKS which supports wazzy node pools. So then we'll see not only a magic eight ball running on a Kubernetes cluster but running on an AKS cluster. Okay, so here is our SPIN.toml. This is once again where you define your SPIN application and the components that are part of it. So far we've talked about only having one component. We had that hello world component. The exciting thing about SPIN is you can have multiple WebAssembly components or .wasm files a part of the same SPIN application and they can live at different endpoints or be triggered by different HTTP endpoints. So in this application, our magic eight ball application you can see that at the root of our path is our front end. It's where you see the magic eight ball. And then another path, the magic eight path that is where we'll have our random request and response. And one thing to mention is we've talked about WebAssembly's capabilities based security. So what that means is that a WebAssembly application will only have access to what it is explicitly granted access to. So if you see this files section here of the SPIN.toml that's where we're saying explicitly wasm time give access to the front end directory to this WebAssembly module. And you can play around with this when you're doing this and change it to something else and you'll get a runtime error because you were not allowed access to that explicit directory. The other thing to note in here is when you want to use key value stores with SPIN applications you'll need to explicitly grant access to a key value store. So by default, SPIN applications are given access to a store called default, very originally named. And so you'll want to add that to a component that you want access to the key value store. Then if we look into that component, so here is our TypeScript application that uses our key value store we'll see in it like we've been doing we're importing the SPIN SDK. The new part here is that we're opening our default store using the KV part of the SDK. And then here in our application you'll say, okay, does this question, will I have five dogs in five years? Does this exist in my key value store? If it doesn't, if it does, or if the response happens to be ask again later we'll go ahead and get an answer or if it doesn't exist yet we'll go ahead and get an answer and then we're gonna set that in our store before we return it to the requester. So this is where we're persisting our responses of our magic eight ball. The other thing we want to see is our front end here. If we look at our front end you'll see the JavaScript part of it where we're basically saying, hey, when someone spins the ball so presses the button we're going to call the magic eight endpoint. So that's where from one component in our spin application we're calling the other. So our front end, once you click the spin it then will call down to that component we just looked at, the TypeScript component that then is going to use the spin SDK to get a response or set a response. So now that we've taken a look at our application let's go ahead and spin it up. So we're used to this NPM install. Then we'll do a spin builds and a spin up. All right, now we can go ahead and navigate to it. Here's our magic eight ball. Okay, does anyone have a question? Okay. I tried to build the application by using the spin gates plugin. I got an error. Okay, that was not the question I was expecting, but. Okay. So when you tried to build the application with this. One thing to mention, I'm on an ARM based Mac. Wait, sorry? I'm on an ARM based Mac, so. Okay, I'm also on an ARM based Mac. So I do not think that will be the issue. Were other people able to build the application with the spin gates? Oh, okay. Did it work for you? Okay, are you on an M1 Mac? Okay, so we're having some successes. Maybe floaters can address the people who aren't having successes. Do you have a life or existential question that you would like to ask the magic eight ball? Does anybody else? Thank you, thank you. Okay, all right. Well, I'm gonna ask it a question then because the suspense is killing me. Will I get a dog? This is really not that exciting. I don't really want one, so. Okay, well, I'm getting a dog. Okay, and so the point here is that I can keep spinning this and it's not gonna change. Every time it is persisted, you'll see as you work up through the workshop, maybe if you try this out later. When you don't use KV, it's gonna change every time. But you could ask a different question and, okay, apparently I'm getting a lot of pets. Okay, great, we're not sure if I'm getting a hamster. I am also getting a hamster, so we're gonna ask about a fish. Okay, I'm getting a fish as well. This is starting to get a little strange. Camel. Okay, I'm not getting a camel. So I am getting every other animal but a camel. So what we saw there is persisting data in a spin app through a key value store. Now I wanna go ahead and show, oh, question. Sorry, go ahead. There's a party tonight. Should we go? Sorry. There's a party tonight. Should we go? Just ask the eight more, that's what I'm saying. I can't hear it. I missed it. I think I missed that. Oh, I would love to hear it. Okay. All right, there's a party tonight and we're trying to find out if he should go to the party. Okay. All right. No, you are not going to the party. I am sorry. Okay, so, out there in the ether, there is an AKS cluster that is running this application. So I'm gonna go ahead and point to its cube config and we'll go ahead and see and use that magic eight ball as well. All right, we've got a bunch of stuff running on this cluster. Some of it is not working, including my magic eight ball. Well, that's disappointing. And it's restarting a lot. All right. All right, we're gonna try and do this live. We'll see how this goes. Is David out there? We ran into the same issue earlier. So there's something I need to change for AKS. Oh, okay, I need to change the runtime class. So previously, when we're running on K3D, our runtime class that we applied was wasm time spin. The name of the runtime class, I believe on AKS is wasm time spin V1. So let's try this. And if you're interested on how to set up your own WASI node pool on AKS, we also have a section of the workshop on that. While this is loading, I'll just go ahead and point you all to that. So this will walk through how you can set up that WASI node pool and hopefully work up to what? Well, hopefully work. We're running and we have multiple instances of it. So we might not get persisted results. So one second, let me update at that again. Since we have a KV store created for every single instance of spin runtime, we want only one replica here if we want persisted results. All right, so now let's go ahead and try out our magic eight ball that's running on AKS. I really didn't think that was gonna work. Okay, so any other questions? Any final questions? Because this does kind of conclude our workshop or our guided portion of the workshop. Oh, yeah, go ahead, the microphone would be great. I'm a bit curious about the implementation of the KV. So I read online, I believe that's a skew light and you can also change it to Redis. How does that work if I wanna use something else and maybe I have my external database or something like that? Yeah, that's a great question. So this is actually pretty new that you can swap it out on the spin side and spin 1.1. We added support for being able to swap out what the underlying we call host implementation is for key values. So we started off with by default, your default store was always setting and getting values from a SQLite database. You can modify the runtime config file of a spin application to be able to point to a different store. So if we were to look at where this would happen, basically we have a spin.toml. We would create, I'm not gonna do this right now because I don't have Redis running, but you would create a runtime config and in here in this runtime config file, this is where you would specify what your default SQLite store is. So if we look at the documentation on this to get an example of that, I'm not sure exactly, here maybe. Okay, take a second, sorry about that. So in this runtime config file, by default, we've created one for you when you spin up an application. By default, the key values users, the key value store called default will be of type spin. So when it's of type spin, that means it's getting and setting values from a SQLite database that's embedded in the spin binary. You can change this to instead get and set values from an external database, namely right now we support Redis, so you could run Redis locally and then point to the URL for your Redis running locally and then get and set values there instead. And the whole idea here is that you never had to change your spin application, that looked the same. All you have to do is change this runtime config file and configure it differently. And the exciting thing about this is it shows how componentizable WebAssembly is so that you can have your guest code or your .wasm file and keep that consistent but you can change the host component. And host means it's not .wasm, oftentimes instead it's a native binary. In our case, the SQLite implementation is in spin itself. I also never asked a question on here. I'm not getting frog. Yes. Are there any limitations with the .js to .wasm transpiler like the, what we're using, you're using .js to .wasm to convert the, the TypeScript into .wasm. Is there like any, I don't know, I mean I can't think of it off top of my head but anything that would have trouble converting from JavaScript to WebAssembly. Okay, so the question is, what is the limitation of what I can convert from my JavaScript application to a WebAssembly component? I'm not sure if there are specific libraries that aren't supported. Does anyone know the answer to that, Til? Basically as far as the language is concerned, there aren't really any limitations but the .js ecosystem is obviously full of libraries that use special APIs that are available in browsers or in Node.js. And if a library is very specifically meant to run in Node then chances are it might not work but increasingly there are libraries are targeting this concept called isomorphic JavaScript where it's meant to run in the browser as well as in Node.js and in Deno and in Cloud for Worker's fastly computed edge and that really plays into our hands here because we are in some sense just another environment for isomorphic JavaScript to run and as much as the JavaScript ecosystem is developing in that direction that really helps us support more and more of it and that already is really, really working well for I think by and large we haven't really gotten much feedback from people not able to compile their JavaScript to Work and Spin. And we have about 14 minutes left but we don't have any more guided content so if people have other questions feel free to keep asking them and we'll leave this slide up here for a bit but if you have, if you want more resources obviously you all know where the link to the workshop is. This is where Spin is, Ruanwazi and then Slack and Discord where you can also be involved in the conversation. Also you can stop by our booths if you wanna talk in person but yeah, feel free to keep asking questions. Thank you. So I would like to ask how Spin actually compares with other Wasm runtimes like Wasmar or like Wasm time? So. Yeah. Or if this is discussed already. No, that's a great question. So the question was how does Spin compare to other runtimes? Like the ones Mikkel mentioned at the beginning like Wasmar, Wasm Edge, Wasm Time. So Spin is using Wasm Time. So we are, our runtime essentially is Wasm Time. We're using those crates. Itself Spin's implemented in REST and so is Wasm Time. How does it compare to Wasm Edge, Wasmar? They all have different levels of support of various Wasi features. Wasm Time is the, what is it called? The reference implementation for the Wasi specification which is why we chose to go with Wasm Time. So that means our support of features tend to be time-staged and in line with the Wasi specification. Okay, thank you. One quick addition to that is also that I am biased. I used to lead the team that built Wasm Time. So take what I say with a grain of salt, but we have done really pioneering work on securing the runtime to a point where I would challenge anybody to try to kind of measure up with that. For example, we were the first request project to run in OSS Fuzz and have done huge amounts of work to get fuzzing working. We're doing verification work on the compiler side to prove correctness of the sandboxing, for example. And that is all, I think, completely unpeckled out in the space which is a big factor of why Mission Critical Web Assembly is increasingly betting on that implementation. Okay, one more. So is it possible to use some other libraries that are built with M-scripten or something like that with spin? So for instance, if there is no Wasm library available for something that I would like to do. Yeah, so. Okay, so the question was, is it possible to use libraries such as ones from M-scripten to use them with spin, essentially? Roddy, did you wanna jump in? Oh, Til, there you go. For M-scripten, the answer is probably no, because M-scripten has, well, M-scripten actually supports WASI, but only WASI, not the system interfaces we are adding for spin. And it's also not meant for the kind of composability where a library that uses M-scripten would be usable for a spin application. And besides supporting WASI, M-scripten is really focused on the M-scripten ABI. It has its own kind of syscall interface that is very POSIX-like and is completely focused on the browser. There are implementations of the M-scripten ABI outside the browser, but, well, there are all kinds of reasons why we chose to go with WASI instead of M-scripten, I'm happy to expand on those offline, but basically it's not a good fit for the security properties we want to have. Implementing all of POSIX in a way that is very browser-focused is kind of not the approach we are pursuing for, I think, pretty compelling reasons. Hi, thanks for your talk, great content. I wonder what type of workloads are supported at the moment in WASI. Can I write an application that interacts with a SQL database, with a no-SQL database, with Kafka, with Pub-Sub, or are these things not available at the moment, but eventually they will be? Yeah, so the question is, or I guess you have a great mic, but what are all the types of applications that I can write and use with spin? Well, you mentioned SQL, so that's what we've been talking about, and you can certainly use SQL with spin right now. Right now you can, we support MySQL for spin locally, and for Infirmion Cloud, we don't yet have support for SQL, it's just key value, and with the runtime config, so the ability to swap out host implementations, in the future we hope to make it so that whatever type of SQL database that you use, you would be able to swap into that runtime config in an easy way while keeping the same application. WebAssembly application, as for other ones like Kafka, we don't yet have support in and spin, but all of this is growing and evolving and we could add more SDKs and more host implementations for those. Rada, did you wanna speak to that as well? Yeah, and there are essentially two approaches to interacting with things like databases and external services. One is, Wazzy's getting support for TCP sockets, so in a short while you'll be able to just import your favorite database RM or Kafka client or Mongo client or any of that, and then, so that should happen and should be available in a little while. In parallel to that, we're testing this approach of using the component model to essentially interact with those things so that you can compose components that interact with those services and then swap them and interact with them in interesting ways. Short answer, both of them are in the works. In the meantime, you can use PIN to connect to databases, you can use hosted databases like PlanetScale directly, you can use MySQL and Postgres and things like your value stores as well. All right, so in the example, the Hello World example, we're essentially writing a cloud function and interfacing with HTTP response and sending it an HTTP response. Is there a way to use a different interface? I don't know, maybe they're communicating with some other message protocol? Yeah, that's a great question. And Mikkel touched on this a little bit, but what we call the fact that that is started or kicked off by an HTTP request, we call that a trigger. So HTTP was what triggered us to run that WebAssembly module and that's also why the interface looks like that. It takes in an HTTP request and returns HTTP response and expects those types. We also have a Redis message queue can trigger it so you could run Redis locally and create a channel and have a spin subscribed to that channel essentially and when there are updates and messages, Redis will then spin up your WebAssembly application on those events, which will handle those types. As for other triggers, we now support being able to create spin plugins that are triggers. So we installed plugins throughout this workshop and you could actually create a new type of trigger as a plugin. So your workflow would be spin, plugin, install, maybe a new trigger and then you could also create those new types of applications, but we also anticipate supporting more triggers over time such as some of the ones you mentioned. I suggest you have a look at the DaySlab Spider Lightning project which defines some common interfaces for things like PubSub and Messaging that we're essentially trying to work together and implement that approach. Yeah, and that's spider lightning and slight is the run time for that and you might see that also reference in the workshop and Joe and David Justice have worked a lot on that and so they have, like Roddy mentioned, a lot of other cloud like interfaces and support for those kinds of functionalities that like Roddy said, we expect to support. Okay, I think we are at time, but if we'll be here for the next few minutes if you're still working through the workshop and want help and as you can see here, we have a Discord, we have a Slack, we have a booth, so feel free to keep throwing your questions our way. Thanks.