Skip to content

Instantly share code, notes, and snippets.

@gbaeke
Last active June 19, 2022 16:21
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gbaeke/4844db10e11f20e994110e2402fb384d to your computer and use it in GitHub Desktop.
Save gbaeke/4844db10e11f20e994110e2402fb384d to your computer and use it in GitHub Desktop.
Run Azure App Services anywhere with Azure Arc

Run Azure App Services anywhere with Azure Arc

Prerequisites

All commands in the gist should be run from bash. You can use WSL (Windows Subsystem for Linux) to run the commands. You can also use the Azure Cloud Shell and select Bash instead of PowerShell.

Install Azure CLI (not needed in Azure Cloud Shell, CLI is pre-installed) and add the following Azure CLI extensions:

az extension add --name connectedk8s
az extension add --name k8s-extension
az extension add --name customlocation
az extension remove --name appservice-kube
az extension add --upgrade --yes --name appservice-kube

Register providers in a subscription you use for testing (preview):

az provider register --namespace Microsoft.ExtendedLocation --wait
az provider register --namespace Microsoft.Web --wait
az provider register --namespace Microsoft.KubernetesConfiguration --wait

⚠️ Deploy an AKS cluster. You can use the portal, use the dev/test profile and deploy a 1 node cluster. When the cluster is deployed run the following command:

az aks get-credentials --resource-group RESOURCEGROUP --name CLUSTERNAME --admin

Ensure a working kubeconfig to check the pods that land on the cluster. Run kubectl get nodes to check your cluster.

Set variables for resource group and Azure Arc-enabled cluster. You can reuse the resource group where you deployed AKS. The clu variable below is the name of the Azure Arc-enabled cluster.

For example:

rg=rg-arc
clu=arcaks

Connect your AKS cluster to Azure Arc with the command below. Note that we use AKS for testing the Azure Arc Application Services. In the real world, you would never Azure Arc-enable an AKS cluster.

az group create -g $rg -l LOCATION
az connectedk8s connect --resource-group $rg --name $clu

The last command will take a few minutes. When finished, check your cluster for the Azure Arc pods in the azure-arc namespace.

Install the App Service Extension

Set some variables for the extension:

  • extensionName: this is the name of the extension to install; for App Service, this is "appservice-ext"
  • namespace: choose a namespace for your extension
  • kubeEnvironmentName: choose a name for the App Service Kubernetes environment
extensionName="appservice-ext"
namespace="appservice-ns"
kubeEnvironmentName="kube-appenv"

Install the extension using the Azure CLI.

⚠️ Replace STORAGECLASS with the Kubernetes storage class the extension will use. For AKS this can be "managed-premium" but also "default". Use kubectl get sc to see the available storage classes. On other clusters besides AKS, always check the storage classes and use the one that is appropriate.

⚠️ The configuration setting envoy.annotations.service.beta.kubernetes.io/azure-load-balancer-resource-group is specific for AKS; if you deploy the extension to other Kubernetes clusters, like K8S in Digital Ocean, you do not need to set this. Even with AKS, it will work without setting this.

# set below variable to the resource group that contains physical cluster resources of AKS
# if not specified or not set, the extension should still install successfully :-)
aksClusterGroupName="MC_rg-aks_kub001_westeurope"

az k8s-extension create \
    --resource-group $rg \
    --name $extensionName \
    --cluster-type connectedClusters \
    --cluster-name $clu \
    --extension-type 'Microsoft.Web.Appservice' \
    --release-train stable \
    --auto-upgrade-minor-version true \
    --scope cluster \
    --release-namespace $namespace \
    --configuration-settings "Microsoft.CustomLocation.ServiceAccount=default" \
    --configuration-settings "appsNamespace=${namespace}" \
    --configuration-settings "clusterName=${kubeEnvironmentName}" \
    --configuration-settings "keda.enabled=true" \
    --configuration-settings "buildService.storageClassName=default" \
    --configuration-settings "buildService.storageAccessMode=ReadWriteOnce" \
    --configuration-settings "customConfigMap=${namespace}/kube-environment-config" \
    --configuration-settings "envoy.annotations.service.beta.kubernetes.io/azure-load-balancer-resource-group=${aksClusterGroupName}"

The above command creates the extension, which is just an ARM resource. Azure Arc for Kubernetes will check for these extensions and start installing the extension with Helm.

⚠️ You might get errors from the above command. They do not always result in a config that does not work. Remember that these services are still in preview. Run the command again. If it still fails, remove the extension and try again.

Get the extension Id with the following command:

extensionId=$(az k8s-extension show \
    --cluster-type connectedClusters \
    --cluster-name $clu \
    --resource-group $rg \
    --name $extensionName \
    --query id \
    --output tsv)

Now wait for the installation to be complete with az resource wait --ids $extensionId --custom "properties.installState!='Pending'" --api-version "2020-07-01-preview"

When the extension is installed, you can proceed with the creation of a custom location.

Custom Location

Later, you will install the App Service Kubernetes environment. The environment, but also the web apps, functions apps and logic apps need a custom location.

First, set the location name and retrieve the Id of the connected cluster:

customLocationName="YOUR-LOCATION-NAME" # Name of the custom location

connectedClusterId=$(az connectedk8s show --resource-group $rg --name $clu --query id --output tsv)

Now you can create the custom location:

az customlocation create \
    --resource-group $rg \
    --name $customLocationName \
    --host-resource-id $connectedClusterId \
    --namespace $namespace \
    --cluster-extension-ids $extensionId

Check the custom location with az customlocation show --resource-group $rg --name $customLocationName

Save the custom location Id. You need it to create the App Service Kubernetes environment.

customLocationId=$(az customlocation show \
    --resource-group $rg \
    --name $customLocationName \
    --query id \
    --output tsv)

Create App Service Kubernetes Environment

Use the following command to create the environment:

az appservice kube create \
    --resource-group $rg \
    --name $kubeEnvironmentName \
    --custom-location $customLocationId

Verify successful creation with az appservice kube show --resource-group $rg --name $kubeEnvironmentName

The above command just creates the environment to create web apps on Kubernetes.

Creating a sample web app and deploy code

You can use the Azure Portal as shown in the video.

If you want to tuse the Azure CLI, use the following command.

az webapp create \
    --resource-group $rg \
    --name WEBAPPNAME \
    --custom-location $customLocationId \
    --runtime 'NODE|12-lts'

Note: find the Linux runtimes to use with az webapp list-runtimes --linux

When the command succeeds, there will be a new pod in the App Service namespace called WEBAPPNAME-.... Check the hostNames section in the output of the command, it contains the URL to access the app. You will need to use this URL to access the app as asked below.

Deploy code (ensure zip is installed with sudo apt-get install zip))

git clone https://github.com/Azure-Samples/nodejs-docs-hello-world
cd nodejs-docs-hello-world
zip -r package.zip .
az webapp deployment source config-zip --resource-group $rg --name WEBAPPNAME --src package.zip

When you navigate to the web app, you should see a Hello World! message.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment