Blog Post

FastTrack for Azure
6 MIN READ

Custom Software Updating with Azure Update Management Center

MikeBazMSFT's avatar
MikeBazMSFT
Icon for Microsoft rankMicrosoft
Nov 01, 2022

I had a customer recently ask about how to leverage the Azure Update Management Center (UMC) preview offering to update their own in-house software deployments on running Linux VMs.  There’s a few different discussions that can come out of that question, including questions around whether or not they actually should be doing that long-term vs. using a CD pipeline in a modern DevOps fashion, but I thought it was an interesting to show a bit of what’s happening with the UMC under the covers a bit.  This article shows an end-to-end demo of using UMC with a custom software package.

 

Basic Infrastructure Setup

This post is focusing on the details of the update side, so I’m not going to deep dive on the basic VM creation process.  For the purposes of this demo, I’m using a Linux Generation 1 VM running Canonical Ubuntu Server version 18.04-LTS, which (as of August, 2022) is on the supported OS list

 

Sample Package Setup

I wanted a custom package that I could reference, but I didn’t want to be caught up in the details of that.  Ultimately, it’s on the customer to manage the packaging of their solution for basic OS update integration, of course, but to demonstrate the functionality, I needed something.  I followed a lightly modified version of the instructions at https://linuxconfig.org/easy-way-to-create-a-debian-package-and-local-package-repository to create a simple file structure:

 

localadmin@UbuntuUpdateDemo:~/helloworld_1.0-1_amd64$ ls -lR
.:
total 8
drwxrwxr-x 2 localadmin localadmin 4096 Aug 17 15:57 DEBIAN
drwxrwxr-x 3 localadmin localadmin 4096 Aug 17 15:45 usr

./DEBIAN:
total 4
-rw-rw-r-- 1 localadmin localadmin 255 Aug 17 15:57 control

./usr:
total 4
drwxrwxr-x 3 localadmin localadmin 4096 Aug 17 15:45 local

./usr/local:
total 4
drwxrwxr-x 2 localadmin localadmin 4096 Aug 17 15:47 bin

./usr/local/bin:
total 4
-rwx------ 1 localadmin localadmin 42 Aug 17 15:47 hello

 

The file “hello” is just a simple Bourne Again Shell script:

 

localadmin@UbuntuUpdateDemo:~/helloworld_1.0-1_amd64/usr/local/bin$ cat hello
#!/bin/bash
echo this is my package 1.0.1

 

And the DEBIAN/control file is just a text file with basic package metadata:

 

localadmin@UbuntuUpdateDemo:~/helloworld_1.0-1_amd64/DEBIAN$ cat control
Package: helloworld
Version: 1.0.1
Architecture: amd64
Maintainer: Michael C. Bazarewsky <michael.bazarewsky@microsoft.com>
Description: A program that greets you.
 You can add a longer description here. Mind the space at the beginning of this paragraph.

 

I then built the package:

 

localadmin@UbuntuUpdateDemo:~$ dpkg-deb --build helloworld_1.0-1_amd64
dpkg-deb: building package 'helloworld' in 'helloworld_1.0-1_amd64.deb'.

 

I then followed the steps in that blog post to create the local repository and move the file in (I won’t repeat those steps here), and then added the repository to /etc/apt/sources.list, although I did it a little differently in that I used http://127.0.0.1/debian as the source instead of the machine’s IP address, just because I was being lazy and didn’t want to have to worry about the IP.

I then updated apt’s local copy of the package information and installed the package – notice the local repository is listed:

 

localadmin@UbuntuUpdateDemo:/var/www/html/debian$ sudo apt update
Ign:1 http://127.0.0.1/debian ./ InRelease
Ign:2 http://127.0.0.1/debian ./ Release  
Ign:3 http://127.0.0.1/debian ./ Packages 
Ign:4 http://127.0.0.1/debian ./ Translation-en
Ign:3 http://127.0.0.1/debian ./ Packages 
Ign:4 http://127.0.0.1/debian ./ Translation-en
Ign:3 http://127.0.0.1/debian ./ Packages 
Ign:4 http://127.0.0.1/debian ./ Translation-en
Hit:3 http://127.0.0.1/debian ./ Packages 
Hit:5 http://azure.archive.ubuntu.com/ubuntu bionic InRelease
Get:6 http://azure.archive.ubuntu.com/ubuntu bionic-updates InRelease [88.7 kB]
Get:7 http://azure.archive.ubuntu.com/ubuntu bionic-backports InRelease [83.3 kB]
Get:8 http://azure.archive.ubuntu.com/ubuntu bionic-security InRelease [88.7 kB]
Ign:4 http://127.0.0.1/debian ./ Translation-en
Ign:4 http://127.0.0.1/debian ./ Translation-en
Ign:4 http://127.0.0.1/debian ./ Translation-en
Ign:4 http://127.0.0.1/debian ./ Translation-en
Fetched 261 kB in 0s (811 kB/s)
Reading package lists... Done
Building dependency tree      
Reading state information... Done
8 packages can be upgraded. Run 'apt list --upgradable' to see them.

 

I then installed the app and made sure it runs:

 

localadmin@UbuntuUpdateDemo:/var/www/html/debian$ sudo apt install helloworld
Reading package lists... Done
Building dependency tree      
Reading state information... Done
The following NEW packages will be installed:
  helloworld
0 upgraded, 1 newly installed, 0 to remove and 8 not upgraded.
Need to get 868 B of archives.
After this operation, 0 B of additional disk space will be used.
Get:1 http://127.0.0.1/debian ./ helloworld 1.0.1 [868 B]
Fetched 868 B in 0s (0 B/s)       
Selecting previously unselected package helloworld.
(Reading database ... 98054 files and directories currently installed.)
Preparing to unpack .../helloworld_1.0.1_amd64.deb ...
Unpacking helloworld (1.0.1) ...
Setting up helloworld (1.0.1) ...
localadmin@UbuntuUpdateDemo:/var/www/html/debian$ hello
this is my package 1.0.1

 

I then copied the 1.0.1 folder to a 2.0.1 folder, updated the script to have the new version number, and built a new package – this was following the same basic pattern as above.  I then copied the helloworld_2.0-1_amd64.deb file into the /var/www/html/debian folder, and rebuilt the Packages.gz file.  Critically though, I made sure to include the --multiversion option, so that both versions would be in the Packages.gz file, otherwise only the newest one would be in the file.  That’s not important for this demo, but you’d want this to be able to demo again on this machine in the future, so that you can install the 1.0.1 version again if desired... 

I then asked for my upgradable package list, and my 2.0.1 package was now there:

 

dpkg-scanpackages --multiversion . | gzip -c9  > Packages.gz
root@UbuntuUpdateDemo:/var/www/html/debian# apt list --upgradable
Listing... Done
cloud-init/bionic-updates 22.3.4-0ubuntu1~18.04.1 all [upgradable from: 22.2-0ubuntu1~18.04.3]
grub-efi-amd64-bin/bionic-updates 2.04-1ubuntu47.4 amd64 [upgradable from: 2.04-1ubuntu44.1.2]
grub-efi-amd64-signed/bionic-updates 1.173.2~18.04.1+2.04-1ubuntu47.4 amd64 [upgradable from: 1.167~18.04.5+2.04-1ubuntu44.1.2]
helloworld/unknown 2.0.1 amd64 [upgradable from: 1.0.1]
lxcfs/bionic-updates 3.0.3-0ubuntu1~18.04.3 amd64 [upgradable from: 3.0.3-0ubuntu1~18.04.2]
snapd/bionic-updates 2.57.5+18.04 amd64 [upgradable from: 2.55.5+18.04]
sosreport/bionic-updates 4.4-1ubuntu0.18.04.1 amd64 [upgradable from: 4.3-1ubuntu0.18.04.2]
tzdata/bionic-updates 2022e-0ubuntu0.18.04.0 all [upgradable from: 2022c-0ubuntu0.18.04.0]
ubuntu-advantage-tools/bionic-updates 27.11.2~18.04.1 amd64 [upgradable from: 27.9~18.04.1]

 

Notice that the helloworld/unknown package shows as upgradable from 1.0.1

 

Updating in the Update Management Center

Cool, so now that I had that out there, it was time to go look at the Updates view in the Portal.  The original view looks like this:

The “Update Management Center” is the next generation interface for dealing with this kind of thing.  The whole goal of this post is now coming up.  Going to the “Update Management Center” through either of the two buttons (one at the top of the right-hand pane, one in the middle of that pane), there was no data out there:

The “Check for updates” button at the top allows running the assessment on the VM.  If the assessment was doing something unusual relative to the OS, or working off of some kind of Microsoft-maintained “master update list”, or anything along those lines, the custom “helloworld” package wouldn’t appear.  But, after a couple of minutes or so, a notification appeared, and the list of updates available on the machine showed up – and that included the custom package:

 

The “One-time update” button allowed for applying updates on the VM:

 

 

 

 

 

After a little while, the update completed, and I was able to see my new updated version was on the machine:

 

localadmin@UbuntuUpdateDemo:~$ hello
this is my package 2.0.1

 

And there it is!

 

Conclusion

So, to summarize, the point of this was to show that the Azure Update Management Center is just leveraging the standard update system on the OS to track and deploy updates.  There's no special magic or secret sauce.  This means that if you’re a software developer, if you leverage the facilities of the OS that you’re developing on, you’ll be integrated with the Azure Update Center with no extra effort on your part, and that’s a pretty great outcome.  If you're an OS administrator, and your vendors play nice with the OS, you get this integration, too!

 

Updated Nov 01, 2022
Version 2.0