Bootstrapping Linux VMs with DSC in Azure

Part 1: Getting Started

This is part one of a three part series on using DSC and Azure Automation to configure Linux.

You can find part two: “Doing it in Azure” here.

Part three: “Automating it all together” is located here.

Lately I’ve been doing a lot of Azure work — both professionally, and for my personal education. Microsoft and I have never been what you would call close, but over the years I’ve grudgingly started to recognize their new “open-source friendly” stance as an attempt at a new start.

So, Azure: there’s a lot of decent things going on there, and in fact, some of their management tools seem to be pretty awesome compared to the other two cloud providers I work with the most: Amazon Web Services (AWS) and Google Cloud Provider (GCP). One thing that caught my eye was the suite of tools called Azure Automation, and in particular the Desired State Configuration (DSC) capabilities of that platform.

But I don’t use Windows based operating systems for much (beyond playing games) — and so I decided to delve into the DSC on Azure Automation and see if you could use it to successfully configure Linux boxes too. And, as it turns out, you can!

Overview of Desired State Configuration (DSC)

DSC is Microsoft’s version of a configuration management solution. If you’ve ever used Chef, Puppet, Ansible, Salt, etc., then you’ve seen what a config management tool can do. Basically it allows you to apply configuration to a machine in a predictable and repeatable manner — things like installing software, adding files, or making registry settings.

It works by writing Powershell scripts that are then compiled into the “MOF” or Management Object Format. These files are then used by the DSC Local Configuration Manager on the target host (or “node” in DSC terminology) to run the configuration specifications.

This can happen in one of two modes: Push or Pull.

In Push mode, you manually copy the MOF files to the computers you want to configure. Then by running the Start-DSCConfiguration command (either locally on the nodes themselves or from a central workstation) you tell the Local Configuration Manager on each node to use those files to configure the machine. If you want to make a change, you have to stage new MOF files to the nodes and rerun the command.

In Pull mode, you have a centralized pull server that stores all the MOF files. You set up each node to connect to this pull server to get their specific MOF configuration files. And even better, you can configure this pull to happen at regularly scheduled intervals — so for example, every 30 minutes the managed nodes will poll the pull server for updated MOF files. If they get one, they run the configuration specified.

Azure Automation DSC

In 2017 Microsoft announced that the option to run your own pull server was being deprecated in favor of using Azure Automation DSC for both cloud and on-premises usage.

Azure Automation DSC contains a built-in pull server, but also management features for configurations, nodes and node-to-configuration mappings. You can see and do a lot with Azure Automation DSC right from the Azure Portal, including viewing your node compliance status and job statistics.

The Azure Automation Portal (there’s not much happening yet).

In addition, Azure Automation DSC is tied in with other Azure services such as Log Analytics. You can search the logs generated by your nodes, as well as correlate events across multiple Automation accounts. You can even set up alerts off of DSC events, such as node compliance failures.

Linux and DSC — Installing DSC locally

So writing DSC modules requires Powershell. And if you’re going to use Linux to author your modules, you will need to install Powershell. Otherwise you can do it on your favorite gaming machine.

But the Linux Local Configuration Manager doesn’t use Powershell to run the MOF files…it is written in C. And the DSC for Linux toolset includes Python versions of all the Powershell DSC cmdlets that are used to do DSC operations, such as StartDscConfiguration.py .

But what you do need as a prerequisite that might not be in your favorite Linux’s basic install is Microsoft’s OMI or Open Management Infrastructure daemon.

Basically you can fetch both OMI and the Linux DSC packages from their respective GitHub release pages and install them. For Ubuntu/Debian for example:

wget https://github.com/Microsoft/omi/releases/download/v1.1.0-0/omi-1.1.0.ssl_100.x64.deb

wget https://github.com/Microsoft/PowerShell-DSC-for-Linux/releases/download/v1.1.1-294/dsc-1.1.1-294.ssl_100.x64.deb



sudo dpkg -i omi-1.1.0.ssl_100.x64.deb dsc-1.1.1-294.ssl_100.x64.deb

At this point, you could write some DSC configurations, compile them into MOF files, upload them to the Linux node, and run the Python version of the DSC cmdlets to configure a single machine.

Linux and DSC — The “nx” module

You are going to have to get a little something extra first though.

All Linux configuration abilities require the usage of the “nx” module, which exposes the Linux specific DSC built-in resources.

So in Powershell, you can do this via:

Install-Module nx

That will go out and fetch the module for you if you have a new enough version of Powershell installed (≥version 5.0). If that fails, you’ll have to go get the Microsoft PackageManagement preview for your older version, or upgrade your Powershell.

Testing it Locally

Ok so I’ve installed Powershell on a test Ubuntu box, and I’ve also installed OMI and DSC via the method above. Let’s do a local test run of how it all works, using the test server to both author the configuration and act as a target node.

First, I’ll install the nx module. Then I’ll put in some DSC configuration commands to create a test file in /tmp.

root@ubuntuservtest:~# pwsh

PS /root> Install-Module nx PS /root> Configuration dsctestlinux{ >> >> Import-DscResource -Module PSDesiredStateConfiguration,nx >> >> Node "TestDSCLinuxfile"{ >> nxFile ExampleFile { >> >> DestinationPath = "/tmp/example" >> Contents = "hello world `n" >> Ensure = "Present" >> Type = "File" >> } >> >> } >> }

(Yes I’m rocking it as root. Save your complaints until the end.)

Then, still in the Powershell session, I’ll run the Configuration. This will compile it into a MOF file named after the Node , and drop it in a directory named for the Configuration .

PS /root> dsctestlinux Directory: /root/dsctestlinux Mode LastWriteTime Length Name ---- ------------- ------ ---- ------ 5/10/18 5:43 PM 992 TestDSCLinuxfile.mof PS /root> exit

root@ubuntuservtest:~#

If I look in the directory listed, I’ll see the MOF file.

root@ubuntuservtest:~# cd dsctestlinux/

root@ubuntuservtest:~/dsctestlinux# ls

TestDSCLinuxfile.mof

Then I’ll run the python version of the StartDscConfiguration cmdlet. First though, I can tell you that if you have python 2 as your default system python, you’re going to get this error:

Traceback (most recent call last):

File "/opt/microsoft/dsc/Scripts/StartDscConfiguration.py", line 21, in <module>

filedata = open(sys.argv[2], "r", encoding="utf-16").read()

TypeError: 'encoding' is an invalid keyword argument for this function

The simplest way to fix this for the short term is to edit the StartDscConfiguration.py script and change #!/usr/bin/python to #!/usr/bin/python3 first.

OK…so back to running the command:

/opt/microsoft/dsc/Scripts/StartDscConfiguration.py -configurationmof /root/dsctestlinux/TestDSCLinuxfile.mof instance of SendConfigurationApply

{

ReturnValue=0

}

This gives all indication of a successful run. And we can check /tmp for the file and contents…

# more /tmp/example

hello world

And there we have it…Microsoft DSC has been used to configure our Linux node without ever touching a Windows machine.

In Our Next Episode

So that’s the end of part 1 of this series. Next time we’ll actually get into Azure, create a Linux VM and start using Azure Automation to run DSC on it.

Or, if you’re the type of person that skips to the end of a book, then by all means go to the last section and see all the best stuff!