 Hello there, I'm Justin Fluger and I'm a senior solutions engineer at Fermion and at Fermion We build a serverless functions platform that's powered by WebAssembly You may have heard of WebAssembly before it's a bytecode format and executes in a secured sandbox runtime at you when you're using spin Which is made by Fermion That is built on top of wasm time wasm time was built by the bytecode alliance Who's also been driving the WASI specification and that's what enables the kind of server side WebAssembly Execution and We'll also be kind of marrying that with the Kubernetes ecosystem today So Kubernetes if you're familiar with it is a pretty strong orchestrator A lot of people have used it before a lot of Customers that we've talked to and folks that we've talked to at cube cons in the past Are all kind of interested in you know, taking advantage of Running server side WebAssembly Because it does allow you to be a little bit more resource efficient with your Kubernetes environments because it's Executes in a similar manner to a Docker container But it doesn't have the kind of base layer of the operating system. So It starts up a lot faster because it just gets straight to your application code And Yeah, so that also means that that it does scale pretty pretty quickly Which is which is also pretty nice if you have you know some bursty workloads and Kubernetes That you're trying to orchestrate So let's kind of dig in here Those sort of things that they you'll need if you're following along You'll need a Kubernetes cluster. I have one that's set up on on SIBO and you'll also need keep CTL home and Fermion spin and then for our programming languages today, we'll take a look at Rust go and Fata script So how does how we enable WebAssembly workloads in in Kubernetes is that it's built on top of a container de shim And that container de shim that we'll be using today is built by the deus labs team at Microsoft and The way that it works is that when Kubernetes gets a request to schedule a pod it sees that that pod has a runtime class for our container de shim and Then it finds the container de shim that's on the node and hands off that WebAssembly module to the shim which gets executed and So the next thing we'll we'll have to get going is We'll have to get those shims on to our Kubernetes nodes And we'll do that using the kwasm operator and makes it really simple to get those container de shims installed on your Kubernetes nodes It'll just be a quick helm install and then we'll be off off the running And for our development tool we'll be using spin to kind of create our application and build it test it locally And then push it up to a container registry and then we'll jump into a cube CTL to kind of deploy that Cool, so let's get into some of the code here So the first thing that we'll need to do, you know, there's nothing in this repository I've got some terraform in here for sevo if you wanted to deploy there You know, it can also be Azure, Kubernetes, EKS, you know, wherever as long as there's a it's a container de-based Kubernetes distribution, it should just work Yeah, so there's nothing else in here, so we'll go ahead and create our spin application And we'll just create it in this in this directory. So we'll initialize a new application. I like to use the our HTTP empty template it makes it easy to kind of add more functions as you go And we'll give it a name here CNCF wasm webinar Yep, we're gonna overwrite our gitignore. I think in a quick description And we'll see, you know in source control There's only one file to get created and that's our spin tunnel. So that is for spin applications This is kind of our application manifest and this is the way that we wire up different web assembly modules to different routes So if you're using just kind of the HTTP empty template There's really nothing in here to get started with so let's Go ahead and add our first our first web assembly module To spin add because we already have the existing spin manifest here We'll start off with rust Rust has pretty good support for web assembly. So it's it's kind of a tier one language for us. It's what spin is built on It's also what Wasm time is built on as well. I'll just give this a description And then the next thing that it's asking for here HTTP path with the three dots. That's a wild card route so if we wanted this function to handle every request that Hits our application. We could leave it like that, but I'm going to use a couple different programming languages today So I'm gonna give it a sub route. We'll just call it RS for rust and There we go, we can see that a couple of things got added here to our spin tumble So the first thing is our HTTP is an HTTP trigger And it's called rust funk because that's the name that I gave spin And it picked up our route So that's the slash RS slash wild card. So anything after RS will get routed to our Rust module here And then, you know looking deeper in into this component rust bunk You know, this source is just a web assembly module. It's just a path So this is where when you run a cargo build. This is the output path for it And if you do have rust installed, you'll need to Install the wasm 32 wazzy target. So Make sure we've got that installed. I'm pretty sure I do already up to date. So we're good there And then, you know under this build portion here for this component We just give it a command. So spin itself doesn't actually build your application We're just using cargo to kind of build our application And then the working directory for us is rust funk. So let's go take a look at that So this is pretty standard rust Project, this is our cargo tumble, which has our dependencies in here right now. It's just anyhow Which helps you kind of handle errors Pretty nicely and then spin SDK I'm using spin 2.2, which is the latest And then let's take a look at the source code So this is all of our source code here. Just one function with this HTTP component attribute And all it's doing here is it's logging out the request header when it gets a request in and it's writing. Hello fermion Let's update that Let's call it. Hello cncf webinar cool And then let's uh go ahead and build our application. So instead of typing, you know cargo build With target and everything um, you can just use a spin build And that's going to compile our app for rust into a web assembly module Eventually Great, so that's built. Um, and then let's just make sure everything's working So we'll do spin up and so you kind of start the global development server and Um, cool. So it's listening on this route We'll open up another terminal here And we'll do a curl write port And give it that rs path Great, it says hello cncf webinar um Perfect, so that one is done Let's add that To our k repository Great back to no changes here So just for funsies, let's add a couple more Uh, we'll go with the javascript one next And we'll just call it js bunk Give it a quick description following the same Pattern we'll get it a javascript path our application And since it's um Javascript and we are using npm to kind of manage our packages um We will go into that directory and install our dependencies and it looks like I need to Set up It's a little it's a little early over here, so Still still drinking my coffee. We've got npm on our path It seems like I need to update my um lrc Cool So we've got all of our dependencies installed Let's go back up to our spin directory where our toml file is Rerun that build and then while we're doing that, we'll take a look at What changed in our application manifest so similar to the rust function here Um, we just added the javascript function Um, and we're just pointing it at the uh output from that. Um, that's a web assembly module and When we rerun spin build here, it did go through the npm or the node build and it also ran through the rust build again. So everything should be up to date And great. So we've got a rust function. We've got a javascript function That says hello from jssdk and let's go take a look at the source code I'll change it again We'll make sure we know which um Which endpoint we're hitting when we call it Let's do that Rust Well, I'm going to run shell again So with this command, um, I ran spin build but since I know I want to run up right right afterwards I just gave it the dash dash up argument and then we'll Double check Yep, our message got updated. That's good And then one more We'll use go this time Call it a gofunk And this is actually built using tiny go. So tiny go has a target for Wasm 3D wazi Go lang will eventually have full support for it. Um, and they're currently working on imports and exports right now One of those may already be done. I don't follow The go lang issue is religiously as some of our other engineers Tango serverless One bit of path I'll rerun that build Test it out again. So many sanity checks I don't know what's going to go wrong. Okay, so we took a look at our go or our JavaScript function already. Let's take a look at our go function So pretty basic, um, go application I think the only difference here is that in the it handler is where we kind of wire up our go handlers Um, and let's change update this message to be similar to the other ones Rerun the build and get that updated message And our other functions are all still working. So I think we're I think we're ready to deploy this So the next thing we'll do is we're going to take this application and we're going to First I'm going to commit my changes push them up. So they're public Here's the github url If you're following along and want to take a look at the code It's under my github handle slash the ncf wasm webinar Find all the code there Cool. So in order for kubernetes to kind of execute this, we'll need to get it into an oci repository. Um, so One one easy way to do that Is there's a command in spin to do a spin registry push And then I've been using ttl.sh lately to Just have kind of an anonymous OCI registry reasonable tag So everything's pushed up to our registry um, so As far as I know, I think we're we're good to start working on some kubernetes manifests. Oh the fun Lots of yaml coming at you. We'll create a directory for it And so the first thing we'll do is create our deployment file um And this will be a pretty basic deployment. So I love snippets Fill out all my stuff for me Okay, so let's take our name here and go through and update it We won't need actually the ports and Just gonna remove the resource here right now. Um You can't put resource requests and limits on there All that all that works and it gets passed through to the container dshim Which does respect to hold those all of those limits. So Um, right, we've got all of our names labels that let's set our image name And it will also have to give a command Uh, this can really be anything. Um, the container dshim doesn't actually use this because it looks up the spin tunnel file Um, and then it will find the subsequent uh, wasm Modules that are in there, uh using that spin manifest So I think let's go to an integral policy Okay, so this is a basic deployment. Um, and this would work if uh, we were just running a regular docker container Um, but since we're going to be using the container dshim We're going to give it the name of a runtime class and this is kind of how we'll wire up The container dshim to be able to execute this specific image So we'll call our runtime class one times nv2 We actually haven't created our runtime class. Let's go ahead and do that now Uh, runtime class And I've got a template here for this one. It's really simple Um, if you've used other, uh, runtimes before like gvisor or anything you've had to do this or Helm has done it for you. Um, so we'll just match up this name to our deployment file You can decide by side here So we've got a runtime class name that'll match up with this runtime class name And uh, the handler here, uh, this does have to be spin. Um, just because the name of the container dshim is follows a pattern Where it's container d dash m dash spin and then v2, uh, corresponds to the container or the, uh The container d, uh, spec heavily something like that Great. So we've got a runtime class. Let's Go ahead and apply our runtime class Looks like I had one left over in in this cluster. Let's make sure I don't have anything else left over Nope, I'm good Uh, cool. So those are the two basic things we need to get this running. Um, Or to wired wired up to the container dshim So the next thing we need to do is get our container dshims actually installed onto our, um, kubernetes nodes. So If we just take a look at our cluster, this is a basic three node cluster Uh, it says k3s, but it's actually running on cvo cloud right now, which uses k3s. Um, so Yeah, well, it's the next the next thing we'll do is use kwasm to install the container dshim Um, and for that we'll use helm. So if we do a helm repo add kwasm Copy paste this one in here. So I don't mess it up. Um, so this is the kwasm operator You can also find that at github.com slash kwasm slash kwasm operator. So there's the helm repo Already exists because I've installed this before And then we'll do a helm install Let it create the namespace Give it a name of space. What's called kwasm And um, I'm gonna set a helm value here that I know and it's called auto provision Um, and so there's two modes that kwasm works in One mode is auto provision, which we'll use here Um, where it will listen for every node that gets added to your Kubernetes cluster And then it will add the container dshim To those nodes as they kind of get added The other way if you have like a node pool that you want to Install specifically on you can annotate those nodes And kwasm will filter based on those annotations I'm gonna be a little lazy here and just auto provision the whole cluster So I'll get a helm release name and point it at our repository and then Here I'm just using an alias that I have to change the Kubernetes context to use the kwasm namespace that was just created We can see that the kwasm operator is running Let's get the logs for that. Cool. So it looks like it started We usually have to place some jobs here. So Um, maybe it already sees that I have run this demo before And uh, these nodes are already provisioned. So let's take a look at one of the nodes Just to make sure And what we're going to be looking for here is a label Um, I can see These are our annotations and labels. Maybe I have that figured the helm to install I'm going to uninstall and Reinstall because I I Typed in that helm value wrong. So sure. It's not in there anymore. Cool to the kwasm namespace I'd say that auto provision nodes is enabled That's saying the kwasm labels in here It's probably because I've run through the demo a couple of times just to make sure that everything's working um So let's take a step further and let's uh, since we have kwasm installed. We've got the deploy installed For the deployment file written. So let's go ahead and apply this and see if it throws an error I am in the wrong namespace Create that deployment in the default namespace. So we don't pollute that kwasm namespace cool So it says it's running, you know, I think um, I just had the shim already installed Usually what you would see in there is some messages, um from kwasm that says that it has added the shim in there But since it probably found that shim already It Didn't log anything out for us. So Let's just make sure that our application is running And we'll port forward from our local port 3000 to 480 We'll create another terminal here So that should be running in our kubernetes cluster You can see that our port forward handled that um, so Let's take it a step further and uh add in some Replicas a couple more replicas and then we'll add in a service I've been running And next thing we got to do is create our service definition This cncf wasm webinar We use port 80 here by default the container dshim will always use port 80 But you can always give it your service a different port. We can make this 3000 if we wanted to but for simplicity, we'll just pass through that That 80 port the Protocol I think that's all we need Make sure that is also up and running Great I got our service deployed. Um, it should be load balancing to our three replicas And the next thing we want to do is be able to access our application from Outside of our cluster. So we'll add an ingress This would be a pretty basic ingress We'll just give it the same name Host um, we don't have a host here. So we're actually going to use a different version of this spec. So Um instead of doing a bunch of rules, uh, which we don't really need for this sample We'll get it to default back end And we'll just point it at our service That should be enough to get an ingress going Great. Now, usually you'd wait until you get an address for this ingress. Um, and in my testing with sevo's K3S distribution, um, this doesn't get populated. But what we can do is look at our Load balancer that got provisioned. Um, so I have some Terraform over here under in Procevo One of the outputs over here is going to be our load balancer domain. So That gets mapped through their mth to the Endpoint So let's go to endpoint And we'll do a curl Endpoint and we'll give it the rust cool, and that's working Great. So we have our Externally available service now So I'll just type on type this all out Great. Um, so that's Um That should be all publicly available. So that's that's it That's all we had to do to get get everything kind of up and running here. Let's um, Add all this to the get repository Now let's do a quick load test um, so I've just been using this a tool to run a quick test It's a pretty simple tool. Um And it'll give us a couple of numbers here. So on 200 responses um Latency distribution On a basic hello world app coming in um, right under Um 280 milliseconds. So that's that's pretty good. Um, you can see a decent amount of that time was spent um, you know doing dns lookups um And the actual response uh writing and reading and waiting for that is actually um, you know 68 68 additional seconds. Um I'm reading that right And a good a good portion of them were in that 75 millisecond range. Um, you know, that's it's not bad for just an unoptimized kubernetes cluster um We have definitely gotten this a lot higher before for the request per second. Um in some of our more optimized environments um But yeah, that's that's the uh, that's the demo. That's kind of everything up and running We've got a kubernetes cluster running web assembly workloads. Um, so That's all we've got today. Uh, thanks for thanks for tuning in. Um, If you have any questions or want to chat about web assembly on kubernetes, uh, I am on the cncf slack So feel free to reach out. It's um jfluder and yeah Thanks for tuning in and we'll see you later