Automating environments with Azure
CC Attribution - NonCommercial - ShareAlike 3.0 Unported:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this
Lindblad, David
Most Cloud-related talks focus on greenfield development using PaaS offerings. In the meantime, the majority of us are struggling to survive in a world where the field is browner than ever. This talk covers how we can transform traditional environments and infrastructure to become flexible, repeatable and deterministic – using Azure. We explore topics such as Infrastructure as code, treating virtual machines as disposable resources and how to ensure consistency between environments. The talk mixes DevOps ideas with Cloud best practices, lessons learned and technical deep dives through demos.We will see how PowerShell, Azure RM (assuming it is released at Build as planned), Azure IaaS/PaaS and Desired State Configuration can be used to develop a modern, robust and scalable infrastructure. Combined, these technologies are used to reliably provision, configure, deploy and dispose virtual machines, resource groups and complete environments.
 All right. Hey everyone. I hope you had a good lunch and welcome to this session on automating environments with Azure. Just a bit of background regarding this talk. I work as a consultant and I talked to a lot of companies. I'm mainly focusing on public cloud in Azure. But I talked to a lot of companies that have seen the Azure parts of platform as a service and all the fantastic things you can do with it. But a lot of them say, yeah, we're not quite there. We're still on the legacy part. We're still running our VMs and that kind of things. So this talk is really for you guys or those people. What I will be going through today is some basic concepts in terms of DevOps and infrastructure as code. I'm also going to show some demos on Azure resource manager. Some of the parts that were released at build now and just a quick overview of how we can use this second generation provisioning system in Azure to provision machines and have them automatically set up entire environments. And for configuration of those machines, we will be using desired state configuration. So there's going to be some small demos there as well. But let's first start with the basic things. Why would we want to automate these kinds of things anyway? In the development industry, I mean, we as developers have worked pretty hard on becoming more efficient. We're using, you know, methodologies that sort of tries to get us to a better return of investment. And we've brought that pretty far up until we come to operations usually. It's still pretty common that it takes, you know, weeks to get a machine provisioned or something like that. So I think this is, you know, we need this to actually sort of take the continuous delivery, the whole continuous delivery thing, run it home basically. It's also one of those things that is very risk reducing. A lot of businesses today consider IT their main, sort of their main competitive advantage. I'm not talking about like Microsoft or Google. It's, you know, companies like Goldman Sachs or Nestle or, you know, these companies that we see as ordinary companies, they are so depending on their IT infrastructure today that it's like, it's not an option for them to be down or it's not an option to have, you know, human errors. It's also, we needed to respond to threats and respond to problems more instantly. It was pretty obvious when Heartbleed started starting going viral, the news about Heartbleed. There were sites up in within a couple of hours reporting on, you know, the average, how, which companies were most likely affected, what kinds of effect there were, how long it took for them to patch their servers. And I mean, Google managed to patch pretty much all of their 1.5 million affected servers in a couple of hours, which is pretty impressive if you think about it. And if they didn't have this kind of automation, there is just no way they could have done that. Another aspect that is more from a management point of view is scalability. If we can have, if we can have fewer people managing more infrastructure and managing more hardware, it will be cheaper. And we can also scale better as an organization. So let's have a look at a couple of the most core DevOps concepts. The first one is probably infrastructure's code. To be able to do this, to be able to automate our environments and our infrastructure, we needed to treat that code as any other. It's as important or even more important than basically our application code. The holy grail, of course, is something like what Netflix have achieved, where you can basically not go down anymore because you will fall, fail over automatically. But it's imperative that this code is really reliable and reproducible and that it can scale dynamically. So, of course, item potency here is absolutely key. And with that, I mean, we need to be able to run these scripts over and over again without being afraid that it will affect our production environments or cause any problems. Another important aspect of this is really that we need to start treating our environments and our machines as immutable and disposable resources. And coming from a sort of traditional IT perspective, this may sound very weird. I mean, what I'm saying is basically that we should probably delete everything, you know, at least once a week. Just, you know, everything from your virtual machines to your network configurations, basically your IT route tables and recreate it. And the reason for this, why this would be a good idea is really that we can eliminate configuration drift. I am pretty sure that a lot of you have at least, you know, one or two servers that have always just been there in the office. No one has really touched them or no one is really sure how they're configured and what is installed on them. If we automatically delete our infrastructure and recreate it automatically, periodically, or every time we want to change something, this never happens. We will have a perfect script that it says exactly what our machines are consists of, how they're configured and so on. Also, it makes us very sure that our provisioning and configuration scripts are actually working. If we run it often enough, we will, you know, we will get tired of fixing stuff manually and we will probably fix the root cause eventually. So it's a really good way of making sure that it's really working. And last but not least, if we do something like this, it's the first couple of times is probably pretty scary. If you want to, let's say if you came into work tomorrow and all the production environments, all the test environments were wiped, there was nothing. It would probably take some time to get back, you know, back up and running. And doing this often makes it a lot less scary. There is a little asterisk there and that is basically, because I always get that question is that can we really wipe everything? And the answer is probably no, you don't want to, you know, don't want to delete your Active Directory and you probably don't want to delete your production database. But to be honest, those two sort of, those two services in an infrastructure is usually anyway the best guarded. You probably have a DBA that is not letting you do whatever you want on that database server. Or you have some ops guy sitting and treating the Active Directory as his own child. So I don't really find this to be a huge problem. It's okay that we cannot do it for absolutely everything, but for test environments, for example, or for application services and so on. This shouldn't really be a big thing. It shouldn't be that difficult to achieve. And this opens up for a few new possibilities. Basically, just the idea that a developer or tester can sort of provision and configure and deploy a new version of your system in a matter of minutes. It's something that I think at least in most places where I've been has taken a few days at least, sometimes even months. Another thing in relation to this is if your management comes to and ask you how well prepared are we for, for example, disaster recovery scenario, or your external auditors have some demand that you need to be able to have a disaster recovery scenario and training every so often. It would be pretty cool to say, you know, the disaster recovery takes about 10 minutes and we practice it 12 times a day. And this is certainly achievable. A lot of companies are starting to do this. Another thing that is becomes very, very easy with this is upgrading software and operating systems. It's basically completely effortless. You would have to change the script somewhere and that's basically it. Then it will automatically at some point in a week or two, it will automatically be upgraded. And last but not least, I want to bring up the scenario of have a zero downtime deployments, for example, with blue-green deployments. I'm not sure if you're not familiar with blue-green deployments is basically where you have your production system and you provision a completely new system that will be your new production system. You deploy all your software on that. You test it. And once you think it's okay, this should be the new production, you switch over with something like traffic manager or a DNS redirect or something like that. All right. So enough of me standing here and trying to convince you why we should do this. I think we should jump over to some demos and going through the resource manager. I won't go into very deep detail on this. I'll show you the basics and how to get started. And it's not very complex, so you can probably, it shouldn't take that long. So I mentioned this was the second generation. So what was the first, you know, what was the wrong with the first one? And there wasn't necessarily anything wrong with it, but some of the things were pretty hard to get right. Most system contains of, you know, more than one resource. And with the old resource manager, we more or less ended up with scripts like this. We had some PowerShell script or similar, which created the first website, the second website, created some virtual network, some storage and so on. And that went, you know, that works fine until the, you know, first VM provisioning fails and you end up with some, you know, database and a couple of websites that doesn't really work anymore. So this is a very imperative way of declaring your provisioned script. And it worked fine, but it ended up, you know, we ended up having to do a lot of checks and to make them item-potent and so on. Also, it was pretty hard to manage them because we couldn't really manage the system as a whole in terms of, you know, cost tracking and access management. And for example, if I wanted to delete this whole system, I would have to go in and delete website one, website two, and VM one, two, three and so on individually. So the whole idea with the resource manager is really to treat the system as a whole as a resource group. And this opens up a few new possibilities. It allows us to actually manage the group as a whole. So we can actually, we can delete a resource group, which will imply that we're deleting all the internal resources as well. Or we can, you know, give someone access to the whole group instead of giving access to individual resource or tracking cost and stuff like that. So there is one rule to this, though, and it's a resource can only exist in one group. And if you think about it, it kind of makes sense. You don't want to mix and match between these. You want to keep them very isolated so you can actually manage them together. So it looks a bit different now because instead of having these declarative script, imperative scripts that we wrote, we now have a more declarative is a JSON file actually that we will look into it a little bit more in the demo. But it's basically a JSON file describing exactly what your system looks like, everything, all the, you know, the monitoring alerts that you want, or the network, or the virtual machines, databases, and so on. Pretty much everything that should be provisioned is within this single resource template. So let's jump over to a short demo of this. Here we go. Here is PowerShell. The first thing I need to do to be able to use resource manager at all is, well, first I need to install PowerShell for Asher, which I have already. The second thing I need to do is I need to switch the Asher mode to Asher resource manager. And if you can see, I can toggle through here. There are two of them. One is the resource manager and one is service management. The service management is the old stuff. The resource manager is the new. The reason that they have decided to keep these two separate is so that you can't write scripts which utilize both of them at the same time. And it kind of makes sense because you could probably do some pretty weird things if you did. So it's sort of an either or approach. You need to choose. Either you do it with the old stuff or you use the resource manager. So that means that I can no longer do things like Asher service. There is no Asher service anymore in this module. So instead, I have a bunch of quite a few new commands that I can use instead. And it's not, you know, full featured yet. I don't think it's complete really, but it's getting very close. And at build, they release the last bits for provisioning VMs. So that's good because that's what I wanted to show here today. All right, so also one thing that should be mentioned is in the new portal. I'm guessing you've seen this. Everything that we can provision here in this portal is already a resource group template. So this machine, for example, is a template. Basically everything in here is a template, which means that we can actually use PowerShell to do this. And PowerShell to find these templates. This is the longest, probably the longest command ever. So basically what this command does, it's listing all the resource group templates that are available in Asher. And it's the same ones that are shown on the website, on the new portal. This is only for the new portal. There are hundreds of them basically. And so we can use this to provision something. If I do the same thing, but I filter for something like... I just want to find the ones that contain something like Windows Server 2012 R2. I will most likely find a few less. Come on. So for example here we have... This is the very standard Core One, the Windows Server 2012 R2. If I want to deploy this just as a completely standard thing, I can do this with the command Asher Resource Group. So I want to create a new Asher Resource Group. And I want to use the gallery template identity of this. What this gives me now, if I show you all the available parameters, you can see that the available parameters that show up now are the exact same available parameters as if I choose to create a new VM. For example, I need to specify hosts, a username and a password. And I have the same thing here. Somewhere I have a username, host, name and password. So it's not really the portal site that decides which fields you have to fill in anymore. It's the underlying template. And it's the same template if you provision it from wherever, really. I'm going to spare you some typing because it's a few things to fill in here. Let me see here. Demo ghost. I'm going to do Asher Resource Group. And then we choose gallery template. Okay. So basically this is what I have to fill in for this template to work at all. I need to specify resource group, which is in this case, I just named it my resource group. I need to specify location and storage and domain name. There is also, by default, there is also creating a new network. So now if I run this, it's basically the same thing as running it from the portal. And this in itself is fairly neat. If you've worked with the old way of provisioning servers in Asher, in PowerShell or some script language, this is quite a clean way of doing it. So if I look now at resources, I see that my new resource group has been created. So far it's created the cloud service. It's going to continue to create the virtual network and then the virtual machine and so on. I'm not going to wait for that. I'm just going to keep moving on. Also, if you have any questions, feel free to ask. All right. So, but this is just the tip of the iceberg really, because if we really want to define our own resource groups, we really need to be able to define our own templates because very few systems, to be honest, consist of only a database or only a website. So what we need to do is basically we need to create our own templates. And luckily we can actually do this. So the gallery template that I showed previously that I used just now to provision this system, what I can actually do, I switch here, I can actually download that. I can download this template as is the JSON file that is. So I just downloaded it. There's a command called save Azure resource group gallery template that may actually be longer than the previous one. But let's have a look at it. So this is what it's consisting of. It's a fair amount of JSON, but it's pretty well structured and pretty easy to understand. First and foremost, we have a bunch of parameters. These are the parameters that we have to fill in either on the website or using the PowerShell. Next, we have the set of resources, basically just a list of resources that we actually want to provision using this script. This means that you can very easily just download a bunch of scripts and mix and match them together. And so if you want multiple virtual networks to be created, you can very easily just copy the virtual network and reuse it. There's also some templates for Visual Studio that is coming out in 2015 that will let you do this more easily. Still, it's fairly easy to get it right now as well. So if we look at this, we have a storage account, we have some domain name, virtual network, and a virtual machine. And the virtual machine in itself consists of endpoints. So we can pretty much configure most of the things that we want to configure from a provisioning point of view. So this can be really useful. And what you do is basically just you create a new JSON file based on what you want to provision. And then you use the same command that I just used here for provisioning this. But instead of using gallery template identity, you can use template file, basically. Other than that, it works identically. All right. So that's more or less what I had to say about Azure Resource Groups. Because this only takes us so far in terms of for websites and for most of the platform as a service components, you can take this pretty far. But for a VM, you usually need to install something on that VM or configure it in some way at least. So this works very well with what I'm going to cover next, which is desired state configuration. And by the way, desired state configuration is not necessarily an Azure thing. It's actually a PowerShell thing or a Windows thing even. Let me see if this worked. No, it didn't. This worked. Okay. So this desired state configuration. Race of hands. Have you heard about it before? Yeah, cool. Okay. There is a bunch of stuff on the market coming out now or you know, I've been here for many years, but that is sort of in this same space. I would say if you've never heard of desired state, it's closer to Chef and Puppet than it is to Vagrant and Docker. It's basically a set, you know, a way that we can have a machine configured to a specific state, thereby the name. So then you may ask, you know, why, why wouldn't we use Chef or Puppet? You would. If you're familiar with Ruby or if you like Ruby, then Chef is certainly the way to go. Puppet also, I mean, has a huge community. It's very well known. But to me personally, this is just my personal opinion. Don't hang me, but I feel like it's sort of Linux first, even though it works for Windows. So Chef, by the way, is starting to use desired state configuration under the hood for the Chef stuff. So that would work as well. All right. So this is not something that Microsoft just, you know, created all on their own. They've actually used some, it's not something proprietary. It's a completely open standard. I think it's called the common information models standard and the managed object format. So you can, if you want, I mean, you can use desired state configuration and you can use it to configure Linux boxes or, you know, your Amiga if you want to, if you write your own provider. So in Windows, desired state configuration was introduced in PowerShell 4. That means that pretty much all modern versions of Windows actually has it already. So it's very little investment to actually get this up and running. And, you know, one of the biggest differences in, I used to be a huge, you know, Linux person when I was young. And the biggest difference between Windows and Linux to me is that Linux is fantastic because it's file based. It's every, you know, it doesn't matter how you change that file, but if you can get it changed, then the system will be configured in that state. Windows on the other hand is API based, which is not always so nice. Desired state configuration really fixes this though. It actually, it lets us have basically one script, one file where we can control all those APIs, which is really, really nice. And it should be said that, you know, going forward, this is the primary management system for Windows. So I would say it's fairly safe to adopt this today. You know, Azure is doing a lot of investments in this. And as far as I know, SCCM and so on is also looking into it, starting using it for everything. And so this is how it really works. We start out with a, you know, completely plain old PowerShell file. We can then compile this to a managed object format, which is, it's compiled, quote unquote. It's not really a compilation. It's more of like transformation. It's still very much readable, but just harder to write it, basically. And then we have to make a decision. Either we have servers pull this configuration from some central place, or we push this configuration to all our servers. So the target nodes in this sense is the servers that we want to configure. And in the end, the desired state resource execution is happening within PowerShell. I think this is much better suited for a demo. Okay. Let me try to switch back again here. Okay. So my previous deployment of the virtual machine is ready. And I think you trust me enough to say that it actually deployed a machine. I hope so, at least. Yes. So we see all the resources that were actually, that was in that file was actually deployed. Okay. Desired state configuration. I actually need to switch back my Azure mode now, because I'm going to use a couple of the old, old examples. So first and foremost, I need a configuration. In my case, I have named this demo config. I don't know if it's large enough. I can probably make it a bit bigger. And the first thing I need to do to create a desired state configuration is have a ps1 file. And then say configuration, give it some kind of name. Okay. This is basically just to tell PowerShell that this is a desired state config. That's more or less all it says. Next, we basically need to tell it which nodes should this configuration apply to. And to make this easy for me, I'm going to say local host, which means that any node that this is actually running on would be fine. What you could do here is that you could use PowerShell filters or something like that to say, to specify that some of your machines are from different roles and stuff like that. Local host, of course, works for everything. And this is the easiest configuration that you can make. It is perfectly valid. You could run this. It would do absolutely nothing. But it's technically valid to run. To actually get this to do something useful, we would have to specify some resources to use within this configuration. So by default, I think PowerShell comes with 12 different resources, things like manipulating files, adding people to a group, to a security group. But there are packs and packs of these desired state resources that you can download. And we can actually get a list of the ones installed on the machine by running getDSC resource. This will take a couple of seconds. And I have installed a couple of these packs that works for most things. Just to give you a very brief example of what it's in there. So setting environment variables, for example, just doing logging. Package is used for installing things or uninstalling if you want. So there are all these kinds of different resources. And I feel that most of the ones that you're going to use more or less every day, there is already some open source version of them. But you can write them yourself as well. We'll go into that a little bit later. So if I want to, let's say now that I, for my configuration, I want to enable a Windows feature, MSMQ, basically. So I happen to know that there is a desired state resource called Windows feature. I will give it a name. And let's just have a look at this. I'm going to save the result here because this query takes some time to actually run. So now I can do, let's do this. If we show just the Windows feature and just showing everything. We can see that this feature has a, where it's stored and so on, it tends to be pretty helpful to be able to write, to be able to list at least all the different properties. So running this, we can see that this resources has a name that is mandatory. There is also some, you know, credential if we want to have a specific credential, an administrator doing this, or we can have this feature depend on, or this resource depend on another resource. So what I need to do, I need to specify the name. And I happen to know that that name is MSMQ server for the MSMQ feature. I'm also going to be very explicit and specify that I want this server to be present. Basically what would happen if I would say here instead absent, then it would ensure that MSMQ is not installed on the server. So if it is already installed, then it's going to be uninstalled, which makes it very convenient if you want to, you know, block people from doing something. But let's make it present. So I also want to do something like downloading Chrome and installing Chrome. And I'm not going to force you to sit here and watch that because the URLs for downloading Chrome is fairly horrible. I need to reopen it. So we still have the Windows feature here that I wrote. As you can see, we now also have a declaration here called import dsc resource and module name. Yeah, something. The reason that we need this is basically because this X remote file resource, which is used to download a file, is not a default, is not a standard resource. So then I need to explicitly say that this is the resource that I want to use and so on. What this does is basically it is downloading from this URL, saving it to this path, and later this package, which is used to install, will ensure that Google Chrome is installed on the machine. It will do a look up in the registry on the same as, you know, installed programs. You can either use a product ID for MSI or just the name. And we also see that this actually depends on the Chrome to be downloaded. So that means that if Chrome cannot be downloaded, we will not try to install Chrome, which kind of makes sense. So this is also sort of by default, all the resources are ran in sequentially, but you can ensure that, you know, some things, if they fail, other things won't happen. All right. So if I'm satisfied with this resource, I want to apply it to a server. There are a couple of things I need to do. If you're running this on premise, or then you would either have to specify that you want to pull this configuration from a central place, and there is tools for that, or you can push it and run it on the local machine. In my case, I'm going to use Azure. I have a machine in Azure. And so we're going to look at how we can actually do this in Azure instead. The first thing that I need to do to be able to use this configuration is I need to upload it to some storage in Azure. And I'm going to shake that I'm actually logged on. So Azure has the notion of extensions on their version machines. So we can actually, and desired state configuration is one kind of extension. So first, I will upload this file. And let's do it verbose. So actually see what happens. What happens here is basically that this command publish Azure VM DC configuration is going to take my configuration. It is also going to take all the resources that my configuration depends on. And it's going to package this together to a zip file and upload it to Azure. And that is done. And we can actually, we can go see this in the portal. We just go to my storage and check the containers. There is a container called Windows PowerShell DSC. This is the default name for these containers. And there's a bug in this version of the portal. So I have to do this twice or three times. Yeah. Okay. It doesn't want to load. But what you would see there is you would see our demo config dot PS one dot sip, which is basically the sipped version of our whole configuration. There you go. So I have it in Azure. I also have a VM that I've already provisioned. And now basically what I want to do is I want to have this configuration applied to this VM. And let's continue using partial. I named my config. Desire stage configuration and DC demo. Yeah. I'm going to store that to a variable called VM. Okay. And then I'm going to say tell this VM. To set the VM desired state extension for the. This. I also need to specify the configuration name, which we need named. Demo config, right? And I need to specify the archive, which was the sip file, basically. So demo config dot PS one dot sip. And I will tell this machine just pipe fit to update Azure VM. So this is going to take a couple of minutes to run. What is happening now is basically that Azure is going to install this extension on the VM. The extension will then go out and fetch the configuration. And it would then run the configuration download, you know, enable MSM Q and download Chrome and so on. While we're doing this. I'm thinking we can have a look at, you know, what it what a very simple configuration would look like. So in my PowerShell module. I have it under users David documents. I have all my modules here. We can look at some very simple one setting the time zone for a for machine. And as you can see, there is the module X time zone contains one resource also called X time zone. So if I wanted to specify time zone on this machine, I would specify. I would declare, you know, X time zone and give it a name and so on. But if we actually let me open it up in Adam instead. But if we look at this. It's actually just PowerShell, which means that for us, it's pretty easy to just create our own PowerShell resources. And in this case, all resources have three functions that you need to implement. It's a get target resource, a set target resource and a test target resource. These are used to see if, for example, if the time zone is already the correct one, the test would the test resource would return true and then nothing more would happen. And the set would would happen only if the test is false and so on. So once you start using this writing your own resources is actually very, very simple. Okay, the. It's succeeded. Now, if I go to my virtual machine. And it was this machine. I should be able to see that this extension is now being installed or has been installed already under all settings. Extensions. Now you see we have a DSC here. It's still loading some information. The configuration has actually been has been applied. So this means that if I log into the machine. We should be able to see that Chrome has been installed and should also be able to see that we have msm q installed. Yeah, so you see message screens also available. So that using this you can you can more or less automate your old legacy environments or your infrastructure for Azure having it configured just like it is configured today. Hopefully giving you the the ability to be a lot more robust and a lot more, you know, be able to act better in case of disaster and so on. So, yeah, this this is pretty much what I had in 10 to show you today. And if you have any questions, please feel free to to ask or come up to me afterwards. All right. Thank you very much. Thank you.
 All right. Hey everyone. I hope you had a good lunch and welcome to this session on automating environments with Azure.  Just a bit of background regarding this talk. I work as a consultant and I talked to a lot of companies. I'm mainly focusing on public cloud in Azure.  But I talked to a lot of companies that have seen the Azure parts of platform as a service and all the fantastic things you can do with it.  But a lot of them say, yeah, we're not quite there. We're still on the legacy part. We're still running our VMs and that kind of things.  So this talk is really for you guys or those people. What I will be going through today is some basic concepts in terms of DevOps and infrastructure as code.  I'm also going to show some demos on Azure resource manager. Some of the parts that were released at build now and just a quick overview of how we can use this second generation provisioning system in Azure to provision machines and have them automatically set up entire environments.  And for configuration of those machines, we will be using desired state configuration. So there's going to be some small demos there as well.  But let's first start with the basic things. Why would we want to automate these kinds of things anyway?  In the development industry, I mean, we as developers have worked pretty hard on becoming more efficient. We're using, you know, methodologies that sort of tries to get us to a better return of investment.  And we've brought that pretty far up until we come to operations usually. It's still pretty common that it takes, you know, weeks to get a machine provisioned or something like that.  So I think this is, you know, we need this to actually sort of take the continuous delivery, the whole continuous delivery thing, run it home basically.  It's also one of those things that is very risk reducing. A lot of businesses today consider IT their main, sort of their main competitive advantage.  I'm not talking about like Microsoft or Google. It's, you know, companies like Goldman Sachs or Nestle or, you know, these companies that we see as ordinary companies,  they are so depending on their IT infrastructure today that it's like, it's not an option for them to be down or it's not an option to have, you know, human errors.  It's also, we needed to respond to threats and respond to problems more instantly. It was pretty obvious when Heartbleed started starting going viral, the news about Heartbleed.  There were sites up in within a couple of hours reporting on, you know, the average, how, which companies were most likely affected, what kinds of effect there were, how long it took for them to patch their servers.  And I mean, Google managed to patch pretty much all of their 1.5 million affected servers in a couple of hours, which is pretty impressive if you think about it.  And if they didn't have this kind of automation, there is just no way they could have done that.  Another aspect that is more from a management point of view is scalability.  If we can have, if we can have fewer people managing more infrastructure and managing more hardware, it will be cheaper.  And we can also scale better as an organization.  So let's have a look at a couple of the most core DevOps concepts.  The first one is probably infrastructure's code.  To be able to do this, to be able to automate our environments and our infrastructure, we needed to treat that code as any other.  It's as important or even more important than basically our application code.  The holy grail, of course, is something like what Netflix have achieved, where you can basically not go down anymore because you will fall, fail over automatically.  But it's imperative that this code is really reliable and reproducible and that it can scale dynamically.  So, of course, item potency here is absolutely key.  And with that, I mean, we need to be able to run these scripts over and over again without being afraid that it will affect our production environments or cause any problems.  Another important aspect of this is really that we need to start treating our environments and our machines as immutable and disposable resources.  And coming from a sort of traditional IT perspective, this may sound very weird.  I mean, what I'm saying is basically that we should probably delete everything, you know, at least once a week.  Just, you know, everything from your virtual machines to your network configurations, basically your IT route tables and recreate it.  And the reason for this, why this would be a good idea is really that we can eliminate configuration drift.  I am pretty sure that a lot of you have at least, you know, one or two servers that have always just been there in the office.  No one has really touched them or no one is really sure how they're configured and what is installed on them.  If we automatically delete our infrastructure and recreate it automatically, periodically, or every time we want to change something, this never happens.  We will have a perfect script that it says exactly what our machines are consists of, how they're configured and so on.  Also, it makes us very sure that our provisioning and configuration scripts are actually working.  If we run it often enough, we will, you know, we will get tired of fixing stuff manually and we will probably fix the root cause eventually.  So it's a really good way of making sure that it's really working.  And last but not least, if we do something like this, it's the first couple of times is probably pretty scary.  If you want to, let's say if you came into work tomorrow and all the production environments, all the test environments were wiped, there was nothing.  It would probably take some time to get back, you know, back up and running.  And doing this often makes it a lot less scary.  There is a little asterisk there and that is basically, because I always get that question is that can we really wipe everything?  And the answer is probably no, you don't want to, you know, don't want to delete your Active Directory and you probably don't want to delete your production database.  But to be honest, those two sort of, those two services in an infrastructure is usually anyway the best guarded.  You probably have a DBA that is not letting you do whatever you want on that database server.  Or you have some ops guy sitting and treating the Active Directory as his own child.  So I don't really find this to be a huge problem.  It's okay that we cannot do it for absolutely everything, but for test environments, for example, or for application services and so on.  This shouldn't really be a big thing.  It shouldn't be that difficult to achieve.  And this opens up for a few new possibilities.  Basically, just the idea that a developer or tester can sort of provision and configure and deploy a new version of your system in a matter of minutes.  It's something that I think at least in most places where I've been has taken a few days at least, sometimes even months.  Another thing in relation to this is if your management comes to and ask you how well prepared are we for, for example, disaster recovery scenario,  or your external auditors have some demand that you need to be able to have a disaster recovery scenario and training every so often.  It would be pretty cool to say, you know, the disaster recovery takes about 10 minutes and we practice it 12 times a day.  And this is certainly achievable.  A lot of companies are starting to do this.  Another thing that is becomes very, very easy with this is upgrading software and operating systems.  It's basically completely effortless.  You would have to change the script somewhere and that's basically it.  Then it will automatically at some point in a week or two, it will automatically be upgraded.  And last but not least, I want to bring up the scenario of have a zero downtime deployments, for example, with blue-green deployments.  I'm not sure if you're not familiar with blue-green deployments is basically where you have your production system and you provision a completely new system  that will be your new production system.  You deploy all your software on that.  You test it.  And once you think it's okay, this should be the new production, you switch over with something like traffic manager or a DNS redirect or something like that.  All right.  So enough of me standing here and trying to convince you why we should do this.  I think we should jump over to some demos and going through the resource manager.  I won't go into very deep detail on this.  I'll show you the basics and how to get started.  And it's not very complex, so you can probably, it shouldn't take that long.  So I mentioned this was the second generation.  So what was the first, you know, what was the wrong with the first one?  And there wasn't necessarily anything wrong with it, but some of the things were pretty hard to get right.  Most system contains of, you know, more than one resource.  And with the old resource manager, we more or less ended up with scripts like this.  We had some PowerShell script or similar, which created the first website, the second website, created some virtual network,  some storage and so on.  And that went, you know, that works fine until the, you know, first VM provisioning fails  and you end up with some, you know, database and a couple of websites that doesn't really work anymore.  So this is a very imperative way of declaring your provisioned script.  And it worked fine, but it ended up, you know, we ended up having to do a lot of checks and to make them item-potent and so on.  Also, it was pretty hard to manage them because we couldn't really manage the system as a whole in terms of, you know,  cost tracking and access management.  And for example, if I wanted to delete this whole system, I would have to go in and delete website one, website two,  and VM one, two, three and so on individually.  So the whole idea with the resource manager is really to treat the system as a whole as a resource group.  And this opens up a few new possibilities.  It allows us to actually manage the group as a whole.  So we can actually, we can delete a resource group, which will imply that we're deleting all the internal resources as well.  Or we can, you know, give someone access to the whole group instead of giving access to individual resource or tracking cost and stuff like that.  So there is one rule to this, though, and it's a resource can only exist in one group.  And if you think about it, it kind of makes sense.  You don't want to mix and match between these.  You want to keep them very isolated so you can actually manage them together.  So it looks a bit different now because instead of having these declarative script, imperative scripts that we wrote,  we now have a more declarative is a JSON file actually that we will look into it a little bit more in the demo.  But it's basically a JSON file describing exactly what your system looks like, everything, all the, you know, the monitoring alerts that you want,  or the network, or the virtual machines, databases, and so on.  Pretty much everything that should be provisioned is within this single resource template.  So let's jump over to a short demo of this.  Here we go. Here is PowerShell.  The first thing I need to do to be able to use resource manager at all is, well, first I need to install PowerShell for Asher,  which I have already.  The second thing I need to do is I need to switch the Asher mode to Asher resource manager.  And if you can see, I can toggle through here.  There are two of them.  One is the resource manager and one is service management.  The service management is the old stuff.  The resource manager is the new.  The reason that they have decided to keep these two separate is so that you can't write scripts which utilize both of them at the same time.  And it kind of makes sense because you could probably do some pretty weird things if you did.  So it's sort of an either or approach.  You need to choose.  Either you do it with the old stuff or you use the resource manager.  So that means that I can no longer do things like Asher service.  There is no Asher service anymore in this module.  So instead, I have a bunch of quite a few new commands that I can use instead.  And it's not, you know, full featured yet.  I don't think it's complete really, but it's getting very close.  And at build, they release the last bits for provisioning VMs.  So that's good because that's what I wanted to show here today.  All right, so also one thing that should be mentioned is in the new portal.  I'm guessing you've seen this.  Everything that we can provision here in this portal is already a resource group template.  So this machine, for example, is a template.  Basically everything in here is a template, which means that we can actually use PowerShell to do this.  And PowerShell to find these templates.  This is the longest, probably the longest command ever.  So basically what this command does, it's listing all the resource group templates that are available in Asher.  And it's the same ones that are shown on the website, on the new portal.  This is only for the new portal.  There are hundreds of them basically.  And so we can use this to provision something.  If I do the same thing, but I filter for something like...  I just want to find the ones that contain something like Windows Server 2012 R2.  I will most likely find a few less.  Come on.  So for example here we have...  This is the very standard Core One, the Windows Server 2012 R2.  If I want to deploy this just as a completely standard thing,  I can do this with the command Asher Resource Group.  So I want to create a new Asher Resource Group.  And I want to use the gallery template identity of this.  What this gives me now, if I show you all the available parameters,  you can see that the available parameters that show up now are the exact same available parameters as if I choose to create a new VM.  For example, I need to specify hosts, a username and a password.  And I have the same thing here.  Somewhere I have a username, host, name and password.  So it's not really the portal site that decides which fields you have to fill in anymore.  It's the underlying template.  And it's the same template if you provision it from wherever, really.  I'm going to spare you some typing because it's a few things to fill in here.  Let me see here.  Demo ghost.  I'm going to do Asher Resource Group.  And then we choose gallery template.  Okay.  So basically this is what I have to fill in for this template to work at all.  I need to specify resource group, which is in this case, I just named it my resource group.  I need to specify location and storage and domain name.  There is also, by default, there is also creating a new network.  So now if I run this, it's basically the same thing as running it from the portal.  And this in itself is fairly neat.  If you've worked with the old way of provisioning servers in Asher, in PowerShell or some script language,  this is quite a clean way of doing it.  So if I look now at resources, I see that my new resource group has been created.  So far it's created the cloud service.  It's going to continue to create the virtual network and then the virtual machine and so on.  I'm not going to wait for that.  I'm just going to keep moving on.  Also, if you have any questions, feel free to ask.  All right.  So, but this is just the tip of the iceberg really, because if we really want to define our own resource groups,  we really need to be able to define our own templates because very few systems, to be honest,  consist of only a database or only a website.  So what we need to do is basically we need to create our own templates.  And luckily we can actually do this.  So the gallery template that I showed previously that I used just now to provision this system,  what I can actually do, I switch here, I can actually download that.  I can download this template as is the JSON file that is.  So I just downloaded it.  There's a command called save Azure resource group gallery template that may actually be longer than the previous one.  But let's have a look at it.  So this is what it's consisting of.  It's a fair amount of JSON, but it's pretty well structured and pretty easy to understand.  First and foremost, we have a bunch of parameters.  These are the parameters that we have to fill in either on the website or using the PowerShell.  Next, we have the set of resources, basically just a list of resources that we actually want to provision using this script.  This means that you can very easily just download a bunch of scripts and mix and match them together.  And so if you want multiple virtual networks to be created, you can very easily just copy the virtual network and reuse it.  There's also some templates for Visual Studio that is coming out in 2015 that will let you do this more easily.  Still, it's fairly easy to get it right now as well.  So if we look at this, we have a storage account, we have some domain name, virtual network, and a virtual machine.  And the virtual machine in itself consists of endpoints.  So we can pretty much configure most of the things that we want to configure from a provisioning point of view.  So this can be really useful.  And what you do is basically just you create a new JSON file based on what you want to provision.  And then you use the same command that I just used here for provisioning this.  But instead of using gallery template identity, you can use template file, basically.  Other than that, it works identically.  All right.  So that's more or less what I had to say about Azure Resource Groups.  Because this only takes us so far in terms of for websites and for most of the platform as a service components, you can take this pretty far.  But for a VM, you usually need to install something on that VM or configure it in some way at least.  So this works very well with what I'm going to cover next, which is desired state configuration.  And by the way, desired state configuration is not necessarily an Azure thing.  It's actually a PowerShell thing or a Windows thing even.  Let me see if this worked. No, it didn't.  This worked. Okay.  So this desired state configuration.  Race of hands. Have you heard about it before?  Yeah, cool. Okay.  There is a bunch of stuff on the market coming out now or you know, I've been here for many years, but that is sort of in this same space.  I would say if you've never heard of desired state, it's closer to Chef and Puppet than it is to Vagrant and Docker.  It's basically a set, you know, a way that we can have a machine configured to a specific state, thereby the name.  So then you may ask, you know, why, why wouldn't we use Chef or Puppet?  You would. If you're familiar with Ruby or if you like Ruby, then Chef is certainly the way to go.  Puppet also, I mean, has a huge community. It's very well known.  But to me personally, this is just my personal opinion.  Don't hang me, but I feel like it's sort of Linux first, even though it works for Windows.  So Chef, by the way, is starting to use desired state configuration under the hood for the Chef stuff.  So that would work as well.  All right.  So this is not something that Microsoft just, you know, created all on their own.  They've actually used some, it's not something proprietary.  It's a completely open standard. I think it's called the common information models standard and the managed object format.  So you can, if you want, I mean, you can use desired state configuration and you can use it to configure Linux boxes or, you know, your Amiga if you want to, if you write your own provider.  So in Windows, desired state configuration was introduced in PowerShell 4.  That means that pretty much all modern versions of Windows actually has it already.  So it's very little investment to actually get this up and running.  And, you know, one of the biggest differences in, I used to be a huge, you know, Linux person when I was young.  And the biggest difference between Windows and Linux to me is that Linux is fantastic because it's file based.  It's every, you know, it doesn't matter how you change that file, but if you can get it changed, then the system will be configured in that state.  Windows on the other hand is API based, which is not always so nice.  Desired state configuration really fixes this though. It actually, it lets us have basically one script, one file where we can control all those APIs, which is really, really nice.  And it should be said that, you know, going forward, this is the primary management system for Windows.  So I would say it's fairly safe to adopt this today. You know, Azure is doing a lot of investments in this.  And as far as I know, SCCM and so on is also looking into it, starting using it for everything.  And so this is how it really works.  We start out with a, you know, completely plain old PowerShell file.  We can then compile this to a managed object format, which is, it's compiled, quote unquote.  It's not really a compilation. It's more of like transformation.  It's still very much readable, but just harder to write it, basically.  And then we have to make a decision. Either we have servers pull this configuration from some central place, or we push this configuration to all our servers.  So the target nodes in this sense is the servers that we want to configure.  And in the end, the desired state resource execution is happening within PowerShell.  I think this is much better suited for a demo.  Okay. Let me try to switch back again here.  Okay. So my previous deployment of the virtual machine is ready.  And I think you trust me enough to say that it actually deployed a machine.  I hope so, at least.  Yes. So we see all the resources that were actually, that was in that file was actually deployed.  Okay. Desired state configuration.  I actually need to switch back my Azure mode now, because I'm going to use a couple of the old, old examples.  So first and foremost, I need a configuration.  In my case, I have named this demo config. I don't know if it's large enough.  I can probably make it a bit bigger.  And the first thing I need to do to create a desired state configuration is have a ps1 file.  And then say configuration, give it some kind of name.  Okay. This is basically just to tell PowerShell that this is a desired state config.  That's more or less all it says.  Next, we basically need to tell it which nodes should this configuration apply to.  And to make this easy for me, I'm going to say local host, which means that any node that this is actually running on would be fine.  What you could do here is that you could use PowerShell filters or something like that to say, to specify that some of your machines are from different roles and stuff like that.  Local host, of course, works for everything.  And this is the easiest configuration that you can make.  It is perfectly valid.  You could run this. It would do absolutely nothing.  But it's technically valid to run.  To actually get this to do something useful, we would have to specify some resources to use within this configuration.  So by default, I think PowerShell comes with 12 different resources, things like manipulating files, adding people to a group, to a security group.  But there are packs and packs of these desired state resources that you can download.  And we can actually get a list of the ones installed on the machine by running getDSC resource.  This will take a couple of seconds.  And I have installed a couple of these packs that works for most things.  Just to give you a very brief example of what it's in there.  So setting environment variables, for example, just doing logging.  Package is used for installing things or uninstalling if you want.  So there are all these kinds of different resources.  And I feel that most of the ones that you're going to use more or less every day, there is already some open source version of them.  But you can write them yourself as well. We'll go into that a little bit later.  So if I want to, let's say now that I, for my configuration, I want to enable a Windows feature, MSMQ, basically.  So I happen to know that there is a desired state resource called Windows feature.  I will give it a name.  And let's just have a look at this.  I'm going to save the result here because this query takes some time to actually run.  So now I can do, let's do this.  If we show just the Windows feature and just showing everything.  We can see that this feature has a, where it's stored and so on, it tends to be pretty helpful to be able to write, to be able to list at least all the different properties.  So running this, we can see that this resources has a name that is mandatory.  There is also some, you know, credential if we want to have a specific credential, an administrator doing this, or we can have this feature depend on, or this resource depend on another resource.  So what I need to do, I need to specify the name.  And I happen to know that that name is MSMQ server for the MSMQ feature.  I'm also going to be very explicit and specify that I want this server to be present.  Basically what would happen if I would say here instead absent, then it would ensure that MSMQ is not installed on the server.  So if it is already installed, then it's going to be uninstalled, which makes it very convenient if you want to, you know, block people from doing something.  But let's make it present.  So I also want to do something like downloading Chrome and installing Chrome.  And I'm not going to force you to sit here and watch that because the URLs for downloading Chrome is fairly horrible.  I need to reopen it.  So we still have the Windows feature here that I wrote.  As you can see, we now also have a declaration here called import dsc resource and module name.  Yeah, something. The reason that we need this is basically because this X remote file resource, which is used to download a file, is not a default, is not a standard resource.  So then I need to explicitly say that this is the resource that I want to use and so on.  What this does is basically it is downloading from this URL, saving it to this path, and later this package, which is used to install, will ensure that Google Chrome is installed on the machine.  It will do a look up in the registry on the same as, you know, installed programs.  You can either use a product ID for MSI or just the name.  And we also see that this actually depends on the Chrome to be downloaded.  So that means that if Chrome cannot be downloaded, we will not try to install Chrome, which kind of makes sense.  So this is also sort of by default, all the resources are ran in sequentially, but you can ensure that, you know, some things, if they fail, other things won't happen.  All right. So if I'm satisfied with this resource, I want to apply it to a server.  There are a couple of things I need to do.  If you're running this on premise, or then you would either have to specify that you want to pull this configuration from a central place, and there is tools for that, or you can push it and run it on the local machine.  In my case, I'm going to use Azure. I have a machine in Azure. And so we're going to look at how we can actually do this in Azure instead.  The first thing that I need to do to be able to use this configuration is I need to upload it to some storage in Azure.  And I'm going to shake that I'm actually logged on.  So Azure has the notion of extensions on their version machines.  So we can actually, and desired state configuration is one kind of extension.  So first, I will upload this file.  And let's do it verbose.  So actually see what happens.  What happens here is basically that this command publish Azure VM DC configuration is going to take my configuration.  It is also going to take all the resources that my configuration depends on.  And it's going to package this together to a zip file and upload it to Azure.  And that is done.  And we can actually, we can go see this in the portal.  We just go to my storage and check the containers.  There is a container called Windows PowerShell DSC.  This is the default name for these containers.  And there's a bug in this version of the portal. So I have to do this twice or three times.  Yeah. Okay.  It doesn't want to load.  But what you would see there is you would see our demo config dot PS one dot sip, which is basically the sipped version of our whole configuration.  There you go.  So I have it in Azure. I also have a VM that I've already provisioned.  And now basically what I want to do is I want to have this configuration applied to this VM.  And let's continue using partial.  I named my config.  Desire stage configuration and DC demo.  Yeah.  I'm going to store that to a variable called VM.  Okay. And then I'm going to say tell this VM.  To set the VM desired state extension for the.  This.  I also need to specify the configuration name, which we need named.  Demo config, right?  And I need to specify the archive, which was the sip file, basically.  So demo config dot PS one dot sip.  And I will tell this machine just pipe fit to update Azure VM.  So this is going to take a couple of minutes to run.  What is happening now is basically that Azure is going to install this extension on the VM.  The extension will then go out and fetch the configuration.  And it would then run the configuration download, you know, enable MSM Q and download Chrome and so on.  While we're doing this.  I'm thinking we can have a look at, you know, what it what a very simple configuration would look like.  So in my PowerShell module.  I have it under users David documents.  I have all my modules here.  We can look at some very simple one setting the time zone for a for machine.  And as you can see, there is the module X time zone contains one resource also called X time zone.  So if I wanted to specify time zone on this machine, I would specify.  I would declare, you know, X time zone and give it a name and so on.  But if we actually let me open it up in Adam instead.  But if we look at this.  It's actually just PowerShell, which means that for us, it's pretty easy to just create our own PowerShell resources.  And in this case, all resources have three functions that you need to implement.  It's a get target resource, a set target resource and a test target resource.  These are used to see if, for example, if the time zone is already the correct one, the test would the test resource would return true and then nothing more would happen.  And the set would would happen only if the test is false and so on.  So once you start using this writing your own resources is actually very, very simple.  Okay, the.  It's succeeded.  Now, if I go to my virtual machine.  And it was this machine.  I should be able to see that this extension is now being installed or has been installed already under all settings.  Extensions.  Now you see we have a DSC here.  It's still loading some information.  The configuration has actually been has been applied.  So this means that if I log into the machine.  We should be able to see that Chrome has been installed and should also be able to see that we have msm q installed.  Yeah, so you see message screens also available.  So that using this you can you can more or less automate your old legacy environments or your infrastructure for Azure having it configured just like it is configured today.  Hopefully giving you the the ability to be a lot more robust and a lot more, you know, be able to act better in case of disaster and so on.  So, yeah, this this is pretty much what I had in 10 to show you today.  And if you have any questions, please feel free to to ask or come up to me afterwards.  All right.  Thank you very much.  Thank you.
Automating_environments_with_Azure_-_David_Lindblad_0_1319.png Automating_environments_with_Azure_-_David_Lindblad_1320_2507.png Automating_environments_with_Azure_-_David_Lindblad_2508_2555.png Automating_environments_with_Azure_-_David_Lindblad_2556_6539.png Automating_environments_with_Azure_-_David_Lindblad_6540_8039.png Automating_environments_with_Azure_-_David_Lindblad_8040_12755.png Automating_environments_with_Azure_-_David_Lindblad_12756_16199.png Automating_environments_with_Azure_-_David_Lindblad_16200_16607.png Automating_environments_with_Azure_-_David_Lindblad_16608_17183.png Automating_environments_with_Azure_-_David_Lindblad_17184_17315.png Automating_environments_with_Azure_-_David_Lindblad_17316_19007.png Automating_environments_with_Azure_-_David_Lindblad_19008_20363.png Automating_environments_with_Azure_-_David_Lindblad_20364_21479.png Automating_environments_with_Azure_-_David_Lindblad_21480_21635.png Automating_environments_with_Azure_-_David_Lindblad_21636_21695.png Automating_environments_with_Azure_-_David_Lindblad_21696_21791.png Automating_environments_with_Azure_-_David_Lindblad_21792_24695.png Automating_environments_with_Azure_-_David_Lindblad_24696_24755.png Automating_environments_with_Azure_-_David_Lindblad_24756_25295.png Automating_environments_with_Azure_-_David_Lindblad_25296_28259.png Automating_environments_with_Azure_-_David_Lindblad_28260_28499.png Automating_environments_with_Azure_-_David_Lindblad_28500_28703.png Automating_environments_with_Azure_-_David_Lindblad_28704_29075.png Automating_environments_with_Azure_-_David_Lindblad_29076_29183.png Automating_environments_with_Azure_-_David_Lindblad_29184_29735.png Automating_environments_with_Azure_-_David_Lindblad_29736_29783.png Automating_environments_with_Azure_-_David_Lindblad_29784_29867.png Automating_environments_with_Azure_-_David_Lindblad_29868_31091.png Automating_environments_with_Azure_-_David_Lindblad_31092_31187.png Automating_environments_with_Azure_-_David_Lindblad_31188_32279.png Automating_environments_with_Azure_-_David_Lindblad_32280_32891.png Automating_environments_with_Azure_-_David_Lindblad_32892_38135.png Automating_environments_with_Azure_-_David_Lindblad_38136_38255.png Automating_environments_with_Azure_-_David_Lindblad_38256_38327.png Automating_environments_with_Azure_-_David_Lindblad_38328_38567.png Automating_environments_with_Azure_-_David_Lindblad_38568_38615.png Automating_environments_with_Azure_-_David_Lindblad_38616_38867.png Automating_environments_with_Azure_-_David_Lindblad_38868_40643.png Automating_environments_with_Azure_-_David_Lindblad_40644_43835.png Automating_environments_with_Azure_-_David_Lindblad_43836_45539.png Automating_environments_with_Azure_-_David_Lindblad_45540_45599.png Automating_environments_with_Azure_-_David_Lindblad_45600_45647.png Automating_environments_with_Azure_-_David_Lindblad_45648_45779.png Automating_environments_with_Azure_-_David_Lindblad_45780_45851.png Automating_environments_with_Azure_-_David_Lindblad_45852_46523.png Automating_environments_with_Azure_-_David_Lindblad_46524_52487.png Automating_environments_with_Azure_-_David_Lindblad_52488_56207.png Automating_environments_with_Azure_-_David_Lindblad_56208_59951.png Automating_environments_with_Azure_-_David_Lindblad_59952_63083.png Automating_environments_with_Azure_-_David_Lindblad_63084_63131.png Automating_environments_with_Azure_-_David_Lindblad_63132_63395.png Automating_environments_with_Azure_-_David_Lindblad_63396_66191.png Automating_environments_with_Azure_-_David_Lindblad_66192_66311.png Automating_environments_with_Azure_-_David_Lindblad_66312_66359.png Automating_environments_with_Azure_-_David_Lindblad_66360_66407.png Automating_environments_with_Azure_-_David_Lindblad_66408_67619.png Automating_environments_with_Azure_-_David_Lindblad_67620_67667.png Automating_environments_with_Azure_-_David_Lindblad_67668_67859.png Automating_environments_with_Azure_-_David_Lindblad_67860_69899.png Automating_environments_with_Azure_-_David_Lindblad_69900_70415.png Automating_environments_with_Azure_-_David_Lindblad_70416_70619.png Automating_environments_with_Azure_-_David_Lindblad_70620_70679.png Automating_environments_with_Azure_-_David_Lindblad_70680_70727.png Automating_environments_with_Azure_-_David_Lindblad_70728_70943.png Automating_environments_with_Azure_-_David_Lindblad_70944_71063.png Automating_environments_with_Azure_-_David_Lindblad_71064_71111.png Automating_environments_with_Azure_-_David_Lindblad_71112_71159.png Automating_environments_with_Azure_-_David_Lindblad_71160_71327.png Automating_environments_with_Azure_-_David_Lindblad_71328_71411.png Automating_environments_with_Azure_-_David_Lindblad_71412_72143.png Automating_environments_with_Azure_-_David_Lindblad_72144_72623.png Automating_environments_with_Azure_-_David_Lindblad_72624_73381.png