Skip to main content

· 2 min read

Azure Backup Overview

Issue Description

Unable to start Windows Azure Guest Agent (it's in a disabled state). When trying and set the service to auto the following error occurs 'The specified service has been marked for deletion.'

VM Agent is unable to communicate with the Azure Backup service.

Root Cause

This may occur if Windows Communication Framework (WCF) profiling is enabled. WCF profiling should only be enabled while debugging a WCF issue. It should not be left enabled while running a production workload.

Resolution #1

1. Restart your workload, I would recommend to Stop (deallocate first) to make sure that the workload starts correctly on a new hypervisor, the Azure Backup agent starts and checks for agent updates during the boot process.

Resolution #2

Disable WCF profiling:

1. Launch an elevated CMD prompt. 2. Run the following commands to back up the existing: C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\machine.config file:

   cd C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config

copy machine.config machine.config.bak

3. Run notepad machine.config to edit the file in Notepad.

Remove this text, being careful not to also remove any additional text that may be on the same line:

<add name="Microsoft.VisualStudio.Diagnostics.ServiceModelSink.Behavior" type="Microsoft.VisualStudio.Diagnostics.ServiceModelSink.Behavior, Microsoft.VisualStudio.Diagnostics.ServiceModelSink, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>

Also remove this text, being careful not to also remove any additional text that may be on the same line:

<commonBehaviors><endpointBehaviors><Microsoft.VisualStudio.Diagnostics.ServiceModelSink.Behavior/></endpointBehaviors><serviceBehaviors><Microsoft.VisualStudio.Diagnostics.ServiceModelSink.Behavior/></serviceBehaviors></commonBehaviors>

4. Save and close the file. 5. Restart the guest agent services:

net stop Rdagent

net stop WindowsAzureGuestAgent

net stop WindowsAzureTelemetryService

net start Rdagent

6. In some cases the VM may need to be restarted for the WCF disablement to take effect.

Resolution #3

From time to time the Azure backup agent may fail. Sometimes this will self-resolve but on the odd occasion, additional steps may be needed.

1. Uninstall the agent via the Control Panel. 2. Open CMD as Admin. 3. Stop the following services:

net stop rdagent

net stop WindowsAzureGuestAgent

net stop WindowsAzureTelemetryService

4. Delete all the services of the agent:

sc delete rdagent

sc delete WindowsAzureGuestAgent

sc delete WindowsAzureTelemetryService

5. Create a folder called OLD in "C:\ WindowsAzure" and move the old version of the agent to it and the folders that say Packages. 6. Install the service again using the link: https://go.microsoft.com/fwlink/?LinkID=394789&clcid=0x409 or the latest agent available.
7. Restart the server.

Resolution #4

1. Migrate the Pagefile to a new disk 2. Set a limit on the pagefile

· 7 min read

There are many ways to do automation scheduling – whether its Jenkins or even Windows Task Scheduler. Each toolset has its place or specialization today we are looking at the son of Ironman Software’s PowerShell Universal Automation platform – the Desktop Edition!

The Desktop edition replicates some of the same functionality as the Universal Automation platform, however, aimed more at being able to drive automation scheduling from your Desktop! Entirely for someone like me who likes to do a certain amount of automation from the Desktop but has a particular distaste for scheduled tasks – like the Universal Automation platform this is entirely driven for PowerShell!

“Desktop edition comes packaged as an Electron app that provides all the great automation features of UA without role-based access, remote access or authentication.”

You can use Universal Automation Desktop for free as a trial:

  • 25 Jobs per day

  • Up to 2 concurrent jobs

We are going to be using the Trial here – however, per-user pricing can be found at the following link: Universal Automation

The toolset is quite intuitive a lot of below isn’t worth going into how do use it - as it seems to be easy to pick up but its always pleasant to have it documented and referable! In my example below, we are going to create a Resource Group in Azure.

  • TOC {:toc}

Install Universal Automation Desktop:

Unlike Universal Automation & Universal Dashboard, installation of the Universal Automation Desktop is packaged into an executable.

  1. Download the latest Universal Automation Desktop installer (bottom of the download pages – at time of writing the installer is 120MB and version 1.0.0)
  2. Installation of Universal Automation Desktop is pretty straight forward, just run the downloaded installer: UniversalAutomationInstall
  3. Once complete, Universal Automation Desktop will load.

Use & Configure Universal Automation Desktop:

Add Scripts

Universal Automation supports git, so a Repository folder is created automatically – any scripts that you add will automatically be added to it:

%LOCALAPPDATA%\UniversalAutomation\Repository

  1. On the Scripts pane select Add Scripts UniversalAutomationScriptsPane
  2. Select the script you want to upload – in my example; I am using ‘New-AzureResourceGroup.ps1’ the script I created for quickly testing some of the functionality.

Gist of script found below, but its also in my GitHub Repository under Azure (GitHub link on the site menu).

  1. Once added you should see the script appear and you should be able to see it in the Repository folder now: UniversalAutomationScriptsPanePopulated

Add variables

Universal Automation Desktop supports variables.

  1. Click on the Variables menu item
  2. Select Add Variable
  3. In my example, I am adding the location that the Resource Group will be created, so it is going to be the following Key = Value pair: Location = Australia East
  4. Click Ok to save

Note: Location is a variable in my script, I also tested manually setting the name of the Resource Group as well with the Name value as well and worked well.

UniversalAutomationVariablesPopulated

Note: The Variables are not encrypted! They are in plain text under:

Repository\.ua\variables.ps1

I did have a few issues with the UI freezing on me, so also discovered that I can manually add variables to this file and after a restart, it seemed to be picked up by Universal Automation as well.

UniversalAutomationVariablesVSCode

Change PowerShell version

This is an interesting feature, that allows you to specify what Version of PowerShell you can have the scripts run under (in this example I will be adding PowerShell 7 preview). We do not need this for my example.

Note: If you do not see the below, you may need to update – Automation Desktop will update automatically and should notify you – close and restart Automation Desktop to continue (if you get an error message – navigate to your notification tray by the time and Quit any open Universal Automation Desktop applications you have open and then relaunch).

  1. Click Settings
  2. Navigate down to PowerShell versions
  3. Click Add New Version
  4. A new Table row will appear (Version\Path)
  5. In Version we are going to type in: PowerShell 7-preview (x64)
  6. In path type in: C:\Program Files\PowerShell\7-preview\pwsh.exe
  7. Press Enter UniversalAutomationPowerShellVersions

Now when you run your scripts, you can now specify what Version of PowerShell to use!

Run the script

Now that the variables have been set up and the script has been added, we can then Run it.

  1. On the scripts pane select ‘New-AzureResourceGroup.ps1’ and select Run Universal_Automation_ScriptsRun
  2. Specify the PowerShell version – I believe automating this selection is currently in the backlog: - and click Run Universal_Automation_ScriptsRunVersion
  3. The script will now go to the Jobs screen: Universal_Automation_ScriptsRunJob
  4. Usually, the script would just run – but in my case, I have a parameter in my PowerShell script to request the name of the Resource Group we are going to create, click on Response to Feedback icon
  5. Type in the name of the Resource Group we are going to create – in my example I am going with: UAutomationRGTest and click Ok Universal_Automation_VariablesFeedback
  6. It will now run the script: Universal_Automation_Script Runs
  7. My new Resource Group has been created in Azure, using the name specified in the Parameter (UAutomationRGTest) and the Location (Australia East) that was set in the Variables!

Universal_Automation_Azure Resource Group created

Scheduling scripts

Although at this stage, I am not scheduling any of my scripts to run – it is a core function of the toolset.

  1. Click on Scripts
  2. Select the script you want to schedule and select View
  3. On the right-hand side blade next to Edit, click on the ellipsis (i.e.…) Universal_Automation_Schedule
  4. Select Schedule Universal_Automation_Schedule
  5. Specify the schedule you want and click Ok

You should now see the Schedule under Schedules and view the Job history under Jobs.

Overall opinion

Long story short - Universal Automation has a place and is a toolset I will be looking at more closely and using!

I see myself using it to utilize PowerShell and automation a bit more in completion of general day to day activities (both personal and professional) and service requests - without having to worry about moving to the next step with a bigger toolset.

If I use a script often enough – then there will be a definite need to move to another team based toolset with RBAC tools such as the Universal Automation offering by Adam Driscoll of Ironman Software.

Word of warning – and it should go without saying :

DO NOT RUN UNIVERSAL AUTOMATION DESKTOP ON YOUR DOMAIN COMPUTER FOR PRODUCTION OR SHARED SCRIPTS! PLEASE LOOK AT UNIVERSAL AUTOMATION FOR THAT! YOU DON’T WANT TO GO HOME OR SHUTOFF YOUR PC OR LEAVE FOR BETTER AND BRIGHTER THINGS AND GET CALLED UP BECAUSE SOME VERY IMPORTANT PROCESS DIDN’T RUN!

My Test Script - New-AzureResourceGroup

I created this function to quickly test 2 things:

  • How does Universal Automation work with 3rd party modules?

  • How does Universal Automation work with parameters and variables?

Universal Automation Desktop does not touch your scripts, in fact depending on what your use case is your git repository should be inline with Automation Desktop and you can sync the Variables across multiple installs.

My script is using 2 modules:

  • CredentialManager

  • Azure (AZ)

I thought CredentialManager would be a good test here as Universal Automation is intended to be run from your Desktop (in my case Windows 10) and using Credential Manager to store my Azure SPN details – without revealing it in plan text was a good test. More information can be found below:

ToastIT - Safe Credentials

New-AzureResourceGroup.ps1

#requires -Version 2.0 -Modules Az.Accounts, Az.Resources, CredentialManager


function New-AzureResourceGroup
{
<#
.SYNOPSIS
Creates Azure Resource Group
.DESCRIPTION
Creates Azure Resource Group function, created as a test function for Universal Automation Desktop
.EXAMPLE
New-AzureResourceGroup
#>
param
([Parameter(Mandatory = $true, HelpMessage = 'Enter the name of the Resource Group you want to create', Position = 0)]
[ValidateNotNullorEmpty()]
[string] $Name,
[Parameter(Position = 1)]
[string]
$Location = 'Australia East'

)

$tenantId = (Get-StoredCredential -Target 'MSDN SPN Demo').GetNetworkCredential().UserName
$pscredential = (Get-StoredCredential -Target 'MSDN SPN Demo Key')

Connect-AzAccount -ServicePrincipal -Credential $pscredential -Tenant $tenantId

New-AzResourceGroup -Name $Name -Location $Location -Force
}

New-AzureResourceGroup

Luke - GitHub

· 3 min read

One of the issues you face with setting up an Azure Site to Site VPN is making sure that your Azure Local Network Gateway always has your Public/On-premises IP.

This setup is fine when used in environments that have Static IPs (and yes if setting this up for a Business or Production, it is highly recommended to have a static IP!).

However, when used in environments like my home network or lab environments - which has a Dynamic IP that could change at any time it will cause connectivity issues if your IP changes and the Local Network Gateway is not updated.

The script below – intended to be run on as a Daily scheduled task, will find your Public IP and connect to Azure and if needed – will update the IP of your Local Network Gateway.

Prerequisites:

Once you have the Azure Service Principal and Az Module installed, you need to edit the following variables to suit your environment:

  • $ResourceGroup = 'RESOURCE GROUP OF LOCAL NETWORK GATEWAY'
  • $LocalNetworkGateway = ‘NAME OF AZURE LOCAL NETWORK GATEWAY’
  • $azureAplicationId =’AZURE AD APPLICATION ID’
  • $azureTenantId= ‘AZURE AD TENANCY/DIRECTORY ID’
  • $azureAPI = ‘AZURE AD APPLICATION API/CLIENT SECRET’
Update-LocalNetGatewayIP.ps1

#requires -Version 3.0 -Modules Az.Network
<#
.SYNOPSIS
Custom script to update your Azure Local Network Gateway with your Public IP
.DESCRIPTION
Updates the Azure Local Network Gateway with your Public IP
Version: 1.0
Author: Luke Murray (Luke.Geek.NZ)
If no Public IP parameter is set, it will automatically grab the Public IP of the computer running it and set it.
The intention of this script is to run as as a scheduled task on your network, which connects to Azure and updates. Intended for Homelabs and scenarios which have Dynamic IPs.

#>
#---------------------------------------------------------[Initialisations]--------------------------------------------------------

$ErrorActionPreference = 'Stop'

[Object]$PublicIP = (Invoke-WebRequest -Uri 'http://ifconfig.me/ip').Content
[string]$ResourceGroup = 'z_Network'
[string]$LocalNetworkGateway = 'Prod-SiteToSite-VLAN-LNGateway'

# Use the application ID as the username, and the secret as password
$azureAplicationId ="Azure AD Application Id"
$azureTenantId= "Your Tenant Id"
$azureAPI = "Your API Key"
$azurePassword = ConvertTo-SecureString "$azureAPI" -AsPlainText -Force
$psCred = New-Object System.Management.Automation.PSCredential($azureAplicationId , $azurePassword)
Connect-AzAccount -Credential $psCred -TenantId $azureTenantId -ServicePrincipal

<#

Before adding the Azure Service Principal in and testing as a Scheduled Task, it is recommended that you just test the script first by connecting manually using:

Connect-AzAccount

#>

#-----------------------------------------------------------[Execution]------------------------------------------------------------



$a = Get-AzLocalNetworkGateway -ResourceGroupName $ResourceGroup -Name $LocalNetworkGateway
$GatewayIP = $a.GatewayIpAddress


If ($PublicIP -ne $GatewayIP) {

$a.GatewayIpAddress = $PublicIP
Set-AzLocalNetworkGateway -LocalNetworkGateway $a

}

Else {

$null

}

Note: Script is also hosted on my Github repository. Feel free to clone/recommend improvements or fork.

· 7 min read

Microsoft has built up the Microsoft Azure ecosystem to offer scale and performance as and when needed; this gives customers the ability to not only remain competitive by lead and disrupt their industries without having to worry about on-premises datacentre capacity, redundancy, and manual processes, this, however, comes at a cost, where engineers may have in the past not cared or been responsible for cost – the Cloud has enabled us not only to consume valuable resources but also drive the cost up which has now shifted left to System Administrators or DevOps Engineers to keep things running and keeping cost low.

Microsoft has built (and continuously improving) some great tools to help customers not only be aware of their cost but make data driven decisions; this blog post is intended to help you gain an understanding of various cost management functions in the Microsoft Azure environment to help you drive productivity up but keep costs low.

Microsoft Azure and other Cloud/Software as a Service product operate in the Opex (or Operational Expenditure) model, meaning that you are essentially paying for subscription-based services and resources on a Monthly or as consumed basis – versus the traditional Capex (or Capital Expenditure) model where you may pay for something up-front whether you use it or not and usually leads to waste in the capital due to oversizing machines or purchasing more than is needed, using Opex gives greater flexibility in terms of what you are currently (and not) consuming and what you want to consume, one thing to remember is that if something is scaled up, it can always be scaled down again with little (or none in some cases) downtime or risk.

  • TOC {:toc}

Roles & Responsibilities & Azure Governance

Before I start through some of the Products that can help you on your managing cost journey – I need to cover off the People aspect first; what I mean by this are Roles & Responsibilities; you need to have some clear clarity in your organisations around who is responsible for what costs are not only created but anything running, whether you have a Product Owner approving and managing the financials or entire Agile Squads dedicated to keeping their resources lean and responsibly for any costs incurred you need to be transparent around Responsibility and Accountability of your costs to help manage (and pay for) the costs and avoid waste. Microsoft Azure has a ‘Billing Administrator’ role which may be helpful to give someone visibility of costs in Microsoft Azure, also be aware of what roles users have, and what they can do with it, you don’t want to give someone Contributor rights over a subscription and have them create a ton of resources when all they needed was Reader rights to view someone else work or skip internal processes for deploying resources.

If you haven’t already – I highly recommend getting an Azure Scaffold or Governance model in place to help determine how you not only use Azure, but how you manage the costs – whether it’s per subscription-based or Resource Groups, the use of Tags to tag Azure resources based on cost center or department etc is invaluable.

Pricing Calculator

The first place to start in the journey of managing technical costs in Azure is the Pricing Calculator

https://azure.microsoft.com/en-us/pricing/calculator/

The Pricing Calculator allows you to select various Azure services (Virtual Machines, App Services Plans, IoT Hubs) and work out estimated pricing vs criteria which may be service-specific such as runtime, geo-redundancy, the amount of storage required etc. You need to know whether a service is costing money if it is running, how many read/writes is allowed, etc. I recommend spending some time looking through the Pricing Calculator and various services that Microsoft Azure offers to get a feel of cost – if you are in NZ (make sure to select ‘New Zealand Dollar’), the default is US.

Cost Visibility across Subscriptions & Resource Groups

The Microsoft Azure Portal offers a lot of visibility into the cost of running resources in Azure, whether you want to look at the costs per subscription or in this example the Resource Group.

You can find the cost information under the ‘Resource Costs’ blade in the Resource Group or ‘Cost Analysis’ at a Resource Group level.

Azure Resource Group Costs

Using the built-in Azure Portal tools you filter costs based on Time/Date and Tags.

On the Overview Blade of an Azure Subscription, you can see the highest costs by Resource type and estimated cost based on current consumption.

Azure Subscription Forecast

Invoices & Consumption Insights

For those of you who pay by Credit Card or want to know the Pre-tax costs of your Azure resources, you can go to your subscription and click on the Invoices blade to review current and previous invoices, if not set up already I recommend you configure the Email Invoice to send the invoice to your Billing Administrator automatically.

If you are on an Enterprise Agreement, you can setup Microsoft Azure Consumption Insights PowerBI pack to help give visibility of Azure costs through the use of the API key from your enrolment portal.

Azure Policies

Along with your Cloud Scaffold or Governance framework, you need to be able to force or guide your environment, Azure Policies can be used to not only keep your Azure ecosystem in alignment but stop the creation of unapproved resources, high costing Virtual Machines, or resources in specific regions, you can use Azure Policies to Audit resources or completely prevent them from being created. Azure Policy samples can be at the azure-policy git repository.

Hybrid Use Benefit

If you already own on-premises Windows Server/SQL server licenses – you may be eligible for HUB (Hybrid Use Benefit) which allows you to run certain machines, based on licensed cores in Azure under the same Windows Server licensing for no additional cost, this can be enabled in the Azure Portal on a Virtual Machine with no downtime.

Azure Advisor & Reserved Instances

Microsoft has built an Advisor into Azure, this Advisor not only gives Security & Performance recommendations, it also includes Cost Recommendations

Azure Advisor

Azure Reserved Instance

These Cost recommendations, are based on CPU usage of workloads (and can be adjusted) – such as workloads running at 5% CPU utilization for the past 14 days and recommends Cost Savings by resizing down the Virtual Machine.

The Azure Advisor also recommends Reserved Instances, instead of ‘Pay As You Go’ or ‘Pay As You Consume’ Opex model, you pay for the Virtual Machines up-front (think capital expenditure) for 1 or 3-year terms, in some cases, you can get 72% savings and if you have machines you know will be on 24/7 and won’t need resizing – think Infrastructure servers, such as Domain Controllers then Reserved Instances are a good idea.

Last Considerations

You need to be aware that pricing in the Azure Portal or Pricing Calculator, may not show all costs. These price indications are only based on the service or size of a resource, they do not take into consideration Network dependencies such as data egress (data leaving Azure), storage replication, etc – the reality is, is sometimes the only way to know how much something will cost is to provision it, use it and monitor the costs.

A side bit of information also is that although a service might cost x in AustraliaEast it may be a lot cheaper to run it in the US for example. Hence, if you need to spin something up quickly or test it and not concerned about latency or data sovereignty then check out Azure Price, this website lists the cost of the Virtual Machines, their costs, and recommended regions to get in some cases 30-40% cost savings.

· 3 min read

Distributed File System (DFS) has some service dependencies - so if those don't start the DFS Namespace service will also not start.

DFS Namespace

The dependencies are:

  • Remote Registry
  • Security Accounts Manager
  • Server
  • Workstation

I have seen the Remote Registry service become the culprit of the DFS-N service not starting.

In my experience, this had been caused by antivirus software changing the Remote Registry service to Disabled start-up type so when the DFS-N server restarts, one of the dependency services:

Remote Registry does not start so if you have issues with the DFS-N service not starting – check the Remote Registry Start-up type is configured to Automatic and click Start to confirm there are no errors and try starting the DFS-N service again.

Note: RemoteRegistry – although it is Automatic, will only Start when it is being used so don't be alarmed if it is in a 'Stopped' state.

Remote Registry

I have also created a PowerShell script to do some general checking for the DFS namespace service – which sets the Remote Registry service to Automatic startup then gets the other DFS dependency services and changes the startup type to Automatic and starts them and finally tries to start the DFS Namespace service.

Start-DFS.ps1

#requires -Version 2.0

<#
.SYNOPSIS
Starts the DFS service

.DESCRIPTION
Changes the Remote Registry service to Automatic start-up and Start the DFS NameSpace service dependencies, then start the DFS namespace service.
If the service does not start, it will retrieve the last 10 event log items from the DFS log.

.NOTES
Version: 1.0
Author: Luke Murray (Luke.Geek.NZ)
Creation Date: 20/03/17
Purpose/Change:
20/03/17 - Initial script development
11/06/18 - Updated script formatting

.EXAMPLE
./Start-DFS-Service.ps1

#>

#---------------------------------------------------------[Script Parameters]------------------------------------------------------

$ServiceName = 'DFS'
$ErrorActionPreference = 'Stop'

#-----------------------------------------------------------[Execution]------------------------------------------------------------

Try
{
Get-Service -Name RemoteRegistry | Set-Service -StartupType Automatic
}
Catch
{
Write-Verbose -Message 'There is an issue changing the Remote Registry Service to Automatic Startup Type' -Verbose
}
Try
{
$ServiceDependency = Get-Service -Name $ServiceName -DependentServices
$ServiceDependency | Set-Service -StartupType Automatic | Start-Service
Write-Verbose -Message "$ServiceName dependencies have started. Will now try starting the $ServiceName service.." -Verbose
}
catch [Microsoft.PowerShell.Commands.ServiceCommandException]
{
[Management.Automation.ErrorRecord]$e = $_

$info = New-Object -TypeName PSObject -Property @{
Exception = $e.Exception.Message
Reason = $e.CategoryInfo.Reason
Target = $e.CategoryInfo.TargetName
Line = $e.InvocationInfo.ScriptLineNumber
Column = $e.InvocationInfo.OffsetInLine
}
Write-Verbose -Message 'Opps! There was an error:' -Verbose
$info
}
Catch
{
Write-Verbose -Message "There was an issue starting $ServiceName dependencies" -Verbose
}

try
{
Try
{
Start-Service -Name $ServiceName
Write-Verbose -Message "The $ServiceName service has started." -Verbose
}
Catch
{
Get-WinEvent -LogName Microsoft-Windows-DFSN-Server/Operational | Select-Object -Last 10
}
}

catch
{
[Management.Automation.ErrorRecord]$e = $_

$info = New-Object -TypeName PSObject -Property @{
Exception = $e.Exception.Message
Reason = $e.CategoryInfo.Reason
Target = $e.CategoryInfo.TargetName
Line = $e.InvocationInfo.ScriptLineNumber
Column = $e.InvocationInfo.OffsetInLine
}
Write-Verbose -Message 'Opps! There was an error:' -Verbose
$info
}

Note: Script is also hosted on my Github repository. Feel free to clone/recommend improvements or fork.