 All right, we are back. We've got Elton and Elton is going to talk to us about Putting the dot net into Kubernetes two of my favorite topics these days. Dot net and Kubernetes Right on can you hear me? I can hear you now. Yes. You can hear me now perfect I'm still trying to figure out these buttons I'm gonna have it all figured out when it's my turn to leave the studio and be replaced by somebody else And then I'm gonna keep it tribal knowledge Whenever you're ready Okay, just to share my screen ready to go. Yep. Okay, excellent. So let's do the right screen Okay, how's that looking? perfect Okay, so Let's get to my PowerPoint here So hey, thanks for joining everybody. My name is Elton. I work for Docker This session is all about dot net applications in Kubernetes. So I've been using before I joined Docker I was a I was a Yeah, a consultant working on big dot net projects. I've been an MVP for 10 years now I was working with dot net from the very first version back in 2002 One of the things I really like about the framework is that it's it's longevity You know, you can take those apps from 2002 and you can run them on all the newest platforms And this session is all about doing that with Kubernetes. So there's a couple things I'm gonna cover Start with a few slides. I'm gonna talk about I'm gonna give you some one-on-ones because I know this is this is a new topic for a lot of people I've been working with Docker since the earliest version So like and if you if you if you're with me on there, then the first few slides will be stuff You already know but I want to get get everyone on the same level talking about what Docker is how dot net fits in What Windows containers mean in in Docker and in Kubernetes and then most of the session is gonna be demos So I'm gonna do a bunch of demos running some brand new dot net core 3.0 apps Building them in Docker running them locally on my machine and then running that exact same app in Kubernetes With the Azure Kubernetes service So I'll do that with a brand new dot net core 3 app running in Linux containers And then I'll use the exact same process the same tools and the same frameworks to do it with a very old dot net app Running on Windows. So that's that. That's the session today Okay, so the very first thing so if you're not familiar with Docker like primarily it is a packaging Distribution and runtime for applications So what you do with Docker is you have your Windows server or your Linux server You install Docker on it and you don't install anything else because everything else that can that your application needs It's gonna come through the container the way you make that happen is you write this script Which which is basically an installation script that says all the bits and pieces that your app needs That's called a Docker file and what that might look like for an old Let's say a dot net web forms up. It's basically a list of all the components that you need So I'm a Windows app. So I need to start on a version of Windows Windows server core. I'm a web app So I need is I'm a dot net up. So I need dot net and I'm a speed on that So I need a speed on that installed and configured and then right at the top there I packaged my own web application, which would be the binaries or the content the HTML and JavaScript and Any configuration that I need? So I write this thing called a Docker file which describes all those steps I run this command Docker image build and that produces this thing called an image Which is just a static package that contains everything in my application and I can share that Now that Docker file that I talked about that does all those steps could be something as simple as this So this Docker file It actually is the previous the previous diagram So this requires is and dot net and ASP dot net but that first line that from line says use somebody else's Docker image This happens to be a Microsoft image and that's already got everything I need. So it's got IS It's got dot net got ASP dot net already configured. So everything my application needs is already there right in that first line So and then the next stage imagine. This is an old application I've already got a build process that gives me an installer a windows MSI I want to just see how that looks in Docker This is literally all I need to do a copy in my MSI and that run command this all happens within Docker It's going to run MSI exec to deploy my application from my MSI You're not necessarily going to do this with your new applications But it's a good way to see how they have your old applications your old windows apps are going to look in containers For a new app. It's going to look something more like this. So it's the same syntax It's the same few commands that you need to understand the words in blue there They're the they're the docker syntax most of what you're going to do though Is is just run script inside that inside this docker file. This is a bit more complicated This is my brand new dot net core application and this does a bit more than the previous example Firstly, there are two parts to this. So the first part is going to compile my application from source code So you see here the from line is saying use an image that microsoft own So there's a public images microsoft maintain them every time there's a windows update or a dot net update They push out new versions This is using a version this isn't using an image that's got dot net core installed and it's the SDK So it's got everything you need to build and package your applications The rest of the of the lines here copy in the source code from whichever machine that's running docker And then run dot net publish, which is exactly what you would do if you were building it in In the ci system or locally on your machine. This all happens within docker And then the second stage starts from the dot net runtime. So this has got ASP dot net This doesn't have the SDK so I can't build on out because When i'm running my container in production, there's no need for me to have the SDK I just need the runtime. So this starts from the ASP dot net runtime It specifies what to do when the application starts so that entry point line says run dot net with my dll And then it copies everything that was built in the previous stage So the the the previous the previous example that I showed you you need to have a bunch of stuff first So you need to have something a process and a machine that can build your msi But it's very quick to get up and running This version you don't need anything at all because all you need is docker and your source code And everything you need to build your app and compile your app and run your app is going to come from docker So it's a really nice way to to make everything super portable Okay, so when I've built my image and I've run through that that docker file So what docker will do is effectively execute each line in that docker file And it will build me this thing called a called a docker image That lives on the machine where I did the docker build and I can push it to a thing called a registry So that's docker hub or as your container registry or a local registry or whatever you're doing or github packages Which is just a store for all these images So I can share that now and then anyone who has access to that image because I could make it public or private Anyone who has access can do a docker run and that will bring that container image onto their machine Which brings everything with it so everything that you've packaged comes down with that container image And then the container will start so your application will start The actual process for your app is going to run on the server directly because that's the way containers work But everything the application needs comes packaged with that container image So my server doesn't need is or dot net and if i'm running several containers with different versions of dot net They're all completely isolated So that's the kind of basics of containers and of course it's the same with linux 2 The commands are the same the docker file syntax is the same When you run your container, it's a linux container. It needs to run on a linux server But the syntax is the same I bring that down. This may be based on debian or a lightweight linux Version is your dot net core installed an asp dot net core on my web app And the application that's running is the dot net runtime But it's exactly the same set of tools same set of artifacts to run your your old windows apps on dot net framework Or your new apps running on on linux okay, so That's your introduction to docker Now what you can then end up with is because your linux containers have to run on linux servers And your windows containers have to run on windows servers You end up needing to kind of join these things together. That's where kubernetes comes in So what kubernetes can do is that you can take a bunch of servers Like a bunch of linux machines a bunch of windows machines You install docker on all of them And then what you end up with is a bunch of isolated machines that can all run containers individually But then you deploy kubernetes and you turn the whole thing into a cluster you can treat it like one big One big platform where you're just going to throw your apps and it's going to decide what to do with them Now i haven't got time to go into kubernetes in any depth, but basically what it is is it's a container Orchestrator so it manages where the containers run. So you you manage your your kubernetes cluster remotely So I can use my laptop. I can connect to my kubernetes cluster When i want to deploy an application I send kubernetes a description of what the pieces that the app needs in a yaml file It's called your application manifest that says i need this content I need this this container and i want five of them I need this container. I want 10 of them. This one has to run on windows This one has to run on linux You throw that to kubernetes and it makes all the choices for you about what's going to run where So it might run for someone one server and someone another server And then it monitors the whole thing and guarantees you your the service levels that you specified So if I need 10 containers running my web app to get to get scale and failover If three of those are running on one of my linux servers and that server dies Then kubernetes will see that server's gone. It's taken three containers with it So I need to start up another three somewhere else on the cluster to maintain the service level So the reason why kubernetes is so exciting and why people are really interested in it Is if you if you build your app and package your app with docker to be to be self-healing Then you can get these kind of autonomous systems where you throw them the application manifest They work out what to do with it. They keep it up and running. They keep it healthy for you And so they're kind of self-operating Okay, and this is what that application manifest looks like in kubernetes This is a simplified version because the kubernetes the kubernetes manifest spec is quite involved But there's there's two parts to this. There's the top the top element here is a service Which is basically just um something that will let network traffic from the outside world Into your containers. So this is saying i'm listening on port 80 81 So any traffic that comes into kubernetes from the outside world on that port It's going to go into a container on port 80 and in this case the container is going to be this dot net conf to do list Which is my dot net core container So the second part is the deployment that says this is the container that I want to run That's going to deal with the traffic that comes into the service There's way more to kubernetes than that This is just to give you a bit of a a bit of a grounding So that the demos make sense and then all the rest of this session is going to be demos until we come back And recap at the end Okay, so i'm going to move on to my demos now Let's open vs code So first demo is i'm going to take a uh a dot net core 3.0 app And i'm going to run it locally and then i'm going to push it up to aks My azure kubernetes cluster and see how it looks in azure So, uh, all the code i've got is on github. Uh, the final slide i've got is a whole bunch of links that will show you Where all this stuff is you don't really need any pre-rex in order to do this yourself You just need docker desktop which runs on mac or windows You can get the source code you can try it all yourself and then there's actually in the uh in the read me for today's session There's instructions how to spin up an aks cluster so you can try it on aks too Okay, so this is the docker file for my dot net core app There are two parts to it like in the example i showed you it starts from the dot net core sdk Microsoft own and maintain that it's got all the tools i copy in my source code I do a restore to get my packages and then i'll do a dot net publish There's this thing here, which is about the runtime id and i'm using advantage of a new dot net core three feature Which is uh in here That i can publish a single file and i can publish it trimmed Um those two things together mean i don't need the dot net core framework deployed In my container at all i'm just going to get a single binary which has got my whole application This happens to be an asp.net core application But i don't need asp.net core uh deployed to my container because everything's in my application So this gives me a super super lightweight uh container on time Okay, so the way i do this is i'm gonna i'm connected to uh a linux machine So i'm running on windows here, but i'm connected to docker on linux Which means i can build this to run on linux if i clear this down and just do a build So that's going to run through all the steps in my docker file And you'll see it was it was like ridiculously suspiciously fast because i've already run it today And if nothing changes if none of the source code changes if none of the docker file changes Then all that stuff comes from the cache So you'll see all these lines here each of these lines from the docker file says using cache Now if i run this without the cache so i can say no cache you'll see a bit more familiar output So each of these steps are going to be executed now. This is running on my linux machine You'll see i've come into the dot net restore part So i copy in the cs proj file into my docker image That's all i copy to start with then i run the restore because that might be um a time consuming process And then i copy in the rest uh and then i go i go and do the build and you'll see now the The build engine starts it's doing the dot net publish Which is going to actually do the the single file packing and the trimming and all that stuff So that that takes a little while So you'll see this is just and the output here all these lines of output are just what you would normally see in Visual studio or vs code if you're doing this as part of your csd pipeline Then you will see all this in the output too. So it's nothing different It's just a different way of actually running these things Okay, i'm going to kill this because the compression of all the bits and pieces takes a little while And i already have a version that's built so i'm going to run that container From the version that i actually i'm going to show you i'm going to show you the difference between some of these These new options that you've got with dot net core 3 So i've built a few of these images already i've built them with different variations of those single file and trimmed stuff So uh, this is the the biggest version if i run that without the single file and without the trim Then it ends up being 200 or megabytes If i include the single file and the trimmed flags Then it comes down to 170 megabytes. What that means is that entire package which has got Debian it's got the linux operating system It's got my binary for my application It's got enough bits of of dot net core to be able to run the website It's got all my all my dependencies or my configuration the whole thing comes in at 170 megabytes Which is pretty much as small as you're going to get a full asp.net core app Okay, so that's the difference those new flags mean So if i run this So i'm going to do a docker container run So imagine i could put i could share this now with with a docker hub as you already have So if you want to try this yourself you can these flags here just mean it's a background container So detach it put it in the background It's going to keep running and this flag means i want to send traffic into my host on Port 80 98 and that's going to go into the container on port 80 So again, i'm zipping through this is going to get a feel for how this stuff works Okay, so i'm going to run this container And then i'm going to open firefox Browse to that app This is the machine that i'm connected to my Linux machine and this I'm afraid to say it's another to-do list application. They're really easy to write so they're good to they're good for demos I've got nothing in here right now and this is connected This is running on a local SQL lite database that's inside the container I've got a to-do list here. It's all empty. I could put some new items in I've got a diagnostics page, which is really handy for me to see what's going on This is the name of the container. This is the version of dot net that's running so I can see it's uh, it's running on preview nine Actually, uh, I've got the operating system architecture and the description. So I know it's linux. I know it's running on intel I know it's running on dot net core Okay, so that's looking pretty good If I wanted to deploy this to kubernetes Let's go back here Close this down Here's my application manifest So what this is saying is again, it's a slightly more elaborate version of the one I showed you in the slides, but it's the same principle. I've got a service here, which is the entry point to my app So kubernetes will listen on port 8081 It'll send traffic into my to-do list container on port 80 When I scroll down here, this is describing how kubernetes should run that container So this is the version of my container that I've already pushed to docker hub So I've done the docker image push. This is all ready to go. I've got my ports that I'm exposing There are a few other bits and pieces here. So I'm taking uh, I'm taking configuration from the cluster So I've created some configuration settings in kubernetes Now, this is one of the great things about these platforms is that you can separate your application from the runtime config So the app has enough logic inside it to look in this particular path And if it finds a bunch of config files, it'll use them and those config files aren't there in the docker image They are provided by the runtime. So kubernetes has this has this configuration deployed When the container runs that configuration gets injected from kubernetes into the application It sees the narrative configures itself So I've got one docker image that I can run in dev in test in uat in production And just apply the configuration from the platform. So this thing is really portable. So that's that's an important thing to have Okay, so I'm going to go over to as you're here. I'm see if my cloud shell is still running yet. Okay, cool So I've got a resource group here with a bunch of things for today's demos I've got a kubernetes service that has some windows and some linux nodes I've got a sql server database that I'm going to use later And I've also got a postgres database, which I'm using for my to-do list application So to do that that I'm running locally. I've just run it in a container using sql light It also has enough logic using ef core to go and talk to postgres and that's what I'm using in as you are So in my cloud shell here I'm going to kill this sleep I'm ready to Switch between linux and windows I'm ready to deploy this because I've already got everything set up So if I do a cube cuddle cube cuddle is the command line to deal with kubernetes Cube other people pronounce it different ways. It's officially pronounced cube cuddle Don't let anyone tell you different So cube cuddles get nodes will tell me what machines are running in my cluster Now I've got two linux machines two windows machines So I can run a variety of different applications But the way I deploy them and manage them is all exactly the same. So If I look at the secrets that I've got these are the configuration items that I've deployed So I've already got ones set up. I've got my in here in my to-do list config I've got a um all the information to connect to postgres. So if I describe That particular secret which is called to-do list config Inside here, there are two files json files and inside the secrets.json is the connection string to postgres So as a kubernetes administrator, I can go and look at that, but no one else can see that stuff Okay, so now I will go and deploy my app And I've already got that that same yaml file that I've just shown you is already on here Let's see where I am So let's do it.net.comp.app And let's have a look. Okay. So I can so the way I deploy my application I've got this yaml file and I do kubectl applied and what that does is it's a desired state system So kubernetes is going to take the description that I've got in this yaml file That's my desired state It'll look at what's currently running and anything that needs to change it will change So I can say I've already created the service because that service creates me and as your load balancer with a static IP address I want to keep that but my deployment is new so it's deploying my application now if I do a kubectl get all You will see I've already got a few things running So here's my my new thing which is my to-do list web application which has started 25 seconds ago All these bits and pieces are how kubernetes does the different layers of my application So that's all up and running that all looks good. And if I browse through this application now If I do kubectl just to be sure get service These are the these are the external entry points. So here's my to-do list web This is the load balancer so it gets created by aks integrates with the rest of as your creates a real as your load balancer Gets me an external IP address and it tells me what ports I can use. So if I switch back to my test browser This is now my hitting my aks version which is talking to postgres It's a brand new deployment. This is a brand new container using the same container image that I've run locally I've already pushed it to docker hub kubernetes is able to pull that down Because of the of the the secrets inside the configuration It's already set up to connect to postgres and postgres has some data already in there So I've already been putting stuff in here. The one good thing about this to-do list is it really Suits my workflow. You can put new items in but you can remove them So if you've got a workload like mine, this is this is perfect for you If I go to diagnostics here, you'll see actually this is a slightly different version because i'm running the release version of dot net core Three, uh, but i'm running x64. I'm running linux. So it's the same app It's connected to postgres because it's getting the config it needs from kubernetes So same same workflow, but a really nice way to do the deployment Okay, so that's a brand new app. So that's fairly straightforward. What about my old app? So as part of my my kind of taking the oldest apps I can find I've got a docker file here that's going to package up nerd dinner like the original nerd dinner from 2006 or whatever it was The docker file syntax is the same This there's a few more pieces in here because it's a more complicated app But actually the the structure is exactly the same. I'm starting from a dot net framework Image so again microsoft own this they keep it up to date This is based on windows server core and it's got the full dot net framework for me I'm copying in the package config and doing a new get restore. So Exactly the same patterns. Excuse me Same patterns to build my application copying the rest of the source code and run ms build. So all fairly straightforward The application image has already got um asp.net 4 7 installed and then i'm doing all this weird stuff Which is to do with setting up is so I can get the logs out of the container I then copy in my application down here. I run some power shell to set up my app I do that again. This is a weird thing that you have to do because it's a 10 year old application And sometimes there are weird steps And then the last thing I've got here is I've got a health check Which is which tells docker how to check the application inside the container is still healthy And then I copy in the app the application. So there's a few bits going on here, but it's still 48 lines half of them are white space lines compare this to a 30 page word document with lots of pictures that say now click here and now Install.net and now run the asp net rage command This is much neater and it's much more portable because all you need to build this is docker and the source code So I would do a docker image build to make to make this happen But you've already seen that process exactly the same process I would run it on a windows machine docker image build gets me the build package Docker image push to share it and then I'm then I'm ready to run it So again, I already have this deployed to my kubernetes cluster. So if I go and check this out Oh, that's I haven't shown you the yaml file So similar thing To deploy this to kubernetes. It's got its own service because in this case. I'm listening on a different port But of course I could have I would ordinarily use the standard http port And I would do things by domain name if I was running several apps on one cluster So this is listening on 8080. I've got my container image here that I want to use This is the one that I've built and pushed. I'm saying which ports to use I'm using exactly the same pattern to get the configuration Out of out of the kubernetes cluster and into my app now The first app that I showed you used the dotnet standard config system with json files This is using the old dotnet framework configuration system with the xml config files It's exactly the same as far as kubernetes is concerned I'm going to deploy those xml files as a secret in kubernetes and make them available to my app in this location And the app is configured to pull bits of the app bits of the config from there Okay, and then the last thing I've got here that I need to point out is this node selector So this is a docker image. It's pushed to docker hub kubernetes doesn't know at this point when I ask it to run the app whether it's for windows or linux So I've given this a hint to say this is a windows app. So make sure you run it on one of my windows nodes Okay, so let's have a look at this So I've already deployed this to make sure that the demos didn't take all afternoon Morning or evening depending on where you are. So that's what you can see here I've already got a deployment that I that I deployed an hour or so ago It's running my nerd dinner web application And I can see there's a service here. And that's my external ip. So exactly the same thing I've already got a if I do the kubectl describe secret And what was it called nerd dinner config Then you'll see the same thing. I've uploaded this secret with my SQL server connection string It's a connection strings.config file exactly the same principle that I would use for an ordinary dotnet app Got a web config file that's looking elsewhere for the connection strings. This is already deployed So this is now running up in up in kubernetes. So I can browse to this Go back to my test browser And if I look at this there we are there's nerd dinner. So this is my 10 year old application It was originally written with with mvc like many many moons ago I can log in. This is all connected to my SQL server database. I've already put some information in here So this is connected to SQL as your it's getting the data that I've already run if I run a new pod It'll connect to the same container and I'll get the same thing out So exactly the same kind of workflow for an old windows app or a brand new dotnet core app running on linux Okay, so Let's have a look here Let's go back to our slides Okay, so those are the demos all that stuff on github you can check it out So just to just to kind of recap what I did because it's not a very long session I've got my kubernetes clusters now the great thing about kubernetes is it's kind of the same everywhere There are different implementations for different parts of kubernetes But the yaml descriptions are always kind of the same so I can throw this on my local machine I can throw it on vms. I can run it up on a ks in azure. I've got my cluster I've deployed my application deployed my old windows application So inside the kubernetes cluster. There are the secrets that have my credentials for my database and my windows container And kubernetes is listening at the top on a particular port and it will send my my request into the container And the container will use the secret to get the connection string and go to sequel as your I also have my brand new dotnet core application Exactly the same principles totally different technology stack. So again kubernetes is listening on a public port Passes traffic to my dotnet core container, which is running on linux that uses a secret to find the connection string for postgres And it all works in the same way Now the beauty of this is you've got an awful lot of consistency across all your applications So all the artifacts are the same every app has a docker file and an application yaml file that describes it The docker if it's a more complicated app i've shown you sync apps with a single component If it's a more complicated Microservice type application You just have more docker files a docker file for each part and the application yaml file brings them all together The pipeline is always the same and it's really simple It's a bunch of command line instructions that you can plug into as your dev ops or jankins or github actions or whatever You're using docker image build docker image push cube cutler applied to deploy it to your cluster And then we've got a consistent platform. So for developers who are working Administrators who are who are managing the stuff in production We're using the same set of tools the same set of artifacts the same platform So it's docker everywhere kubernetes in my test and production environments and it's dotnet all the way through So it's a really nice way to get consistency across a whole range of different apps Okay, and then here is the big list of a big list of links. So today's demo is all on github If you're interested in how this stuff works and you want to go right back to the beginning If you follow that link that for dotnet that's a workshop that'll do at various conferences But all the contents online you can go to that website and follow along and you know take this whole thing much more slowly I'm in the process of writing a book learn docker in a month of lunches That's the link to the book the first five chapters are done If you want and the final thing is going to give you a discount to go and buy the whole book when it's when it's ready So, um, thank you very much for listening. We'll take some q and a if we've got any But yeah, that's that's what we've got I can see you pushing buttons, but I can't hear you. Yeah We're we're struggling with the on mute on skype Yes You can hear us. Okay, right? All right. I can hear you now. Yeah, all right. Perfect. Thank you. That was awesome Um in terms of questions and I know you're you've just put up some Links here, but I think there's a lot of confusion about kubernetes and not just how to pronounce it So, you know somebody who's maybe played around with docker understands the concept of containers What where would you point them to learn about kubernetes? So starting with what the heck is it because it gets pretty deep pretty quickly, right? Yeah, it's a that's a really good point So, I mean if you look at the learning curve for these things like the learning care for docker is is pretty straightforward Um, you can spend a couple of days looking at it and and find some good samples and you'll be up and running You know with your own applications running containers in in a few days Um kubernetes the learning curve is very much steeper Uh, because it is there are so many abstractions there. It's it's got a very pluggable framework There are different ways of doing the same thing Different relief it moves so quickly the each new release brings all these interesting features In terms of resources, so so the the docker docs are always are always great and it's really you know There's some good examples of how to get that stuff started Um, and again the the the the main kubernetes docs are pretty good If you're looking for something that's specific to dotnet, I don't think that's out there yet So that that link back for dotnet. Um, that's an evolving workshop and I'm adding more and more kubernetes content The trouble is is is this big gulf between I get the idea of containers I'm running them locally and then kubernetes, which is which is massively more complicated The bit in between which most people don't do is docker swarm So docker swarm is another container orchestrator It's much simpler than kubernetes because it doesn't have all the features that kubernetes has But it's way easier to get started with so actually is a really good learning learning Journey is to to learn how to dockerize your applications Using single containers then learn about docker compose, which tells you how to deal with multi application multi container applications Then learn docker swarm, which you may not use in production But it's it's much easier to learn kubernetes when you've got swarm when you've got swarm and understanding of swarm because the the main kind of clustering Concepts of the same and docker swarm uses docker compose as the format to describe all these these multi container apps So, um, yeah, it's a good good good learning path is docker then compose then swarm Then kubernetes and somewhere along that journey you may say I've got everything I need and then I can stop So you don't have to go to kubernetes the big advantage with kubernetes is um Because it has so many integration points all the clouds that are that are giving you a hosted kubernetes service Integrate really nicely with the rest of that platform, right? So, you know, as you all I get my low balance. Sorry. I get my public IP addresses I don't have to do anything else. I spin up my aks cluster And it will take care of the rest for me. So yeah, so that's why, you know That's why kubernetes is the kind of the poster child for cloud native stuff But yeah, there is a steep burning cove and and you're you're gonna have to decide whether you need to go all the way All right, perfect. Thanks so much for doing this Oh, you're welcome. Thanks for having me. Yeah, thanks so much. We're gonna get the next speaker up Who's the next speaker? That's mic What is he gonna be talking about? Mike is gonna be talking about modernizing dot net applications with dot net core. Sweet. All right. That's awesome Thank you so much everybody. We're gonna stay here. We we we shut off the videos because people were wanting that the Links because the way we do the video overlay they couldn't see it So I kind of shut it off halfway through it. So thank you so much. We'll be right back with more dot net com See you