Intro

In the previous post I showed how to work with Azure Blob Service properties and metadata, in this post I am going to show how to use Azure Content Delivery Network (CDN) with Azure Blob Service, I will use Standard Akamai pricing tier because it is the cheapest option.

Prerequisites

Refer to previous posts to get started with Azure Blob Service.

Code

Azure Content Delivery Network (CDN) caches static web content at strategically placed locations to provide maximum throughput for delivering content to users. Azure CDN can be integrated with Azure Blob Service, I am going to show how to load a simple image to CDN, update and delete it.

Lets start by creating a container:

PS C:\WINDOWS\system32> New-AzureStorageContainer -Permission Blob -Name "static-content"

CloudBlobContainer : Microsoft.WindowsAzure.Storage.Blob.CloudBlobContainer
Permission         : Microsoft.WindowsAzure.Storage.Blob.BlobContainerPermissions
PublicAccess       : Blob
LastModified       : 10/31/2016 12:05:34 AM +00:00
ContinuationToken  :
Context            : Microsoft.WindowsAzure.Commands.Common.Storage.AzureStorageContext
Name               : static-content

Now when we have a container, use the following command to load an image to the container:

PS C:\WINDOWS\system32> Set-AzureStorageBlobContent -File "C:\TestData\azure.jpg" -Container "static-content"

ICloudBlob        : Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob
BlobType          : BlockBlob
Length            : 87341
ContentType       : application/octet-stream
LastModified      : 10/31/2016 12:17:47 AM +00:00
SnapshotTime      :
ContinuationToken :
Context           : Microsoft.WindowsAzure.Commands.Common.Storage.AzureStorageContext
Name              : azure.jpg

This command will upload an image to the container.

Now lets setup CDN and make it serve content from the container. First we need to create a CDN profile, you can do it like this:

PS C:\WINDOWS\system32> New-AzureRmCdnProfile -ProfileName StaticContent -ResourceGroupName Default -Sku StandardAkamai -Location "Australia East"

Sku               : Microsoft.Azure.Commands.Cdn.Models.Profile.PSSku
ResourceState     : Active
ResourceGroupName : Default
Location          : AustraliaEast
Tags              : {}
Id                : /subscriptions/8a2fdad7-75c8-46c4-a740-c547dc545543/resourcegroups/Default/providers/Microsoft.Cdn/profiles/StaticContent
Name              : StaticContent
Type              : Microsoft.Cdn/profiles
ProvisioningState : Succeeded

The following command will create an endpoint:

PS C:\WINDOWS\system32> New-AzureRmCdnEndpoint -ProfileName StaticContent -ResourceGroupName Default -Location "Australia East" -EndpointName static-content -OriginName default748347 -OriginHostName "default748347.blob.core.windows.net" -OriginPath "/static-content" -OriginHostHeader "default748347.blob.core.windows.net"

HostName                   : static-content.azureedge.net
OriginHostHeader           : default748347.blob.core.windows.net
OriginPath                 : /static-content
ContentTypesToCompress     : {}
IsCompressionEnabled       : False
IsHttpAllowed              : True
IsHttpsAllowed             : True
QueryStringCachingBehavior : IgnoreQueryString
Origins                    : {default748347}
ResourceState              : Running
ResourceGroupName          : Default
ProfileName                : StaticContent
Location                   : AustraliaEast
Tags                       : {}
Id                         : /subscriptions/8a2fdad7-75c8-46c4-a740-c547dc545543/resourcegroups/Default/providers/Microsoft.Cdn/profiles/StaticContent/endpoints/static-content
Name                       : static-content
Type                       : Microsoft.Cdn/profiles/endpoints
ProvisioningState          : Succeeded

Now lets check if azure.jpg image can be requested from CDN using the follow command:

PS C:\WINDOWS\system32> Invoke-WebRequest https://static-content.azureedge.net/azure.jpg -Method HEAD

StatusCode        : 200
StatusDescription : OK
Content           : {}
RawContent        : HTTP/1.1 200 OK
                    Content-MD5: Me8FrJfvp341GphA3a8zLA==
                    x-ms-request-id: 2fd33c04-0001-000b-5e20-33c472000000
                    x-ms-version: 2009-09-19
                    x-ms-write-protection: false
                    x-ms-lease-status: unlocked
                    x-ms...
Headers           : {[Content-MD5, Me8FrJfvp341GphA3a8zLA==], [x-ms-request-id, 2fd33c04-0001-000b-5e20-33c472000000], [x-ms-version, 2009-09-19],
                    [x-ms-write-protection, false]...}
RawContentLength  : 0

Looks good. Now we can use https://static-content.azureedge.net/azure.jpg url insted of https://default748347.blob.core.windows.net/static-content/azure.jpg and be sure that azure.jpg image will be loaded from the server that is closest to the user.

If you try to open this image in browser, you will see something similar to this:

https://raw.githubusercontent.com/boades/boades-blog-content/master/03-azure/01-azure-storage/29-azure-blob-with-azure-powershell-cdn/01-azure-image-initial.png

CDN caches a resource for some amount of time, so if you replace the image in the container you won't see the changes until CDN decides to reload the image from the origin. I have updated the image in container, but CDN still has an old version. If you try to use Publish-AzureRmCdnEndpointContent to force CDN to a new version from origin, you will get an error:

PS C:\WINDOWS\system32> Publish-AzureRmCdnEndpointContent -ProfileName StaticContent -ResourceGroupName Default -EndpointName static-content -LoadContent "/azure.jpg"
Publish-AzureRmCdnEndpointContent : Operation returned an invalid status code 'BadRequest'
At line:1 char:1
+ Publish-AzureRmCdnEndpointContent -ProfileName StaticContent -Resourc ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : CloseError: (:) [Publish-AzureRmCdnEndpointContent], ErrorResponseException
    + FullyQualifiedErrorId : Microsoft.Azure.Commands.Cdn.Endpoint.PublishAzureRmCdnEndpointContent

It happens because Standard Akamai CDN doesn't support content publishing, to use this feature you have to use Standard Verizon or Premium Verizon pricing tier. Fortunatly, it is possible to unpublish a resource from CDN servers, so on the next request CDN will fetch it from the storage one more time:

PS C:\WINDOWS\system32> Unpublish-AzureRmCdnEndpointContent -ProfileName StaticContent -ResourceGroupName Default -EndpointName static-content -PurgeContent "/azure.jpg"

Next time you request the image you will get the lattest version of the image:

https://raw.githubusercontent.com/boades/boades-blog-content/master/03-azure/01-azure-storage/29-azure-blob-with-azure-powershell-cdn/03-azure-image-changed-on-cdn.png

Lets assume that we don't use this file anymore and want to delete azure.jpg from our static-content container as well as from all CDN servers. This task should be done in two steps. First, delete an image from container:

PS C:\WINDOWS\system32> Remove-AzureStorageBlob -Container static-content -Blob azure.jpg

If you try to access image on CDN, you will find that it is still there:

PS C:\WINDOWS\system32> Invoke-WebRequest https://static-content.azureedge.net/azure.jpg -Method HEAD

StatusCode        : 200
StatusDescription : OK
Content           : {}
RawContent        : HTTP/1.1 200 OK
                    Content-MD5: Me8FrJfvp341GphA3a8zLA==
                    x-ms-request-id: 9961f4a6-0001-0024-0f20-334548000000
                    x-ms-version: 2009-09-19
                    x-ms-write-protection: false
                    x-ms-lease-status: unlocked
                    x-ms...
Headers           : {[Content-MD5, Me8FrJfvp341GphA3a8zLA==], [x-ms-request-id, 9961f4a6-0001-0024-0f20-334548000000], [x-ms-version, 2009-09-19],
                    [x-ms-write-protection, false]...}
RawContentLength  : 0

But it doesn't exist in storage anymore:

PS C:\WINDOWS\system32> Invoke-WebRequest https://default748347.blob.core.windows.net/static-content/azure.jpg -Method HEAD
Invoke-WebRequest : The remote server returned an error: (404) Not Found.
At line:1 char:1
+ Invoke-WebRequest https://default748347.blob.core.windows.net/static- ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand

So we need to explicitly instruct CDN to remove the image from all CDN servers, consider this example:

PS C:\WINDOWS\system32> Unpublish-AzureRmCdnEndpointContent -ProfileName StaticContent -ResourceGroupName Default -EndpointName static-content -PurgeContent "/azure.jpg"

This command takes some time to complete. Lets check that azure.jpg has been removed from CDN:

PS C:\WINDOWS\system32>  Invoke-WebRequest https://static-content.azureedge.net/azure.jpg -Method HEAD
Invoke-WebRequest : The remote server returned an error: (404) Not Found.
At line:1 char:2
+  Invoke-WebRequest https://static-content.azureedge.net/azure.jpg -Me ...
+  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebExc
   eption
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand

So now we see that azure.jpg has been removed from all CDN servers.

To remove CDN endpoint execute the following command:

PS C:\WINDOWS\system32> Remove-AzureRmCdnEndpoint -ProfileName StaticContent -ResourceGroupName Default -EndpointName static-content

To remove CDN profile run the following command:

PS C:\WINDOWS\system32> Remove-AzureRmCdnProfile -ProfileName StaticContent -ResourceGroupName Default

Summary

In this post I have showed how to work with Azure CDN and Azure Blob Service Blobs. In next posts I am going to switch to Azure File Storage Service.


;