- Let's get Started with Containers on Azure (Erik St. Martin) - c5m.ca/aaa-ep18
- Let's build a website with Node.js on Azure (Tiemey Cyren) - c5m.ca/aaa-ep19
- Adding all functionalities from previous version into TinyBlazorAdmin website - c5m.ca/stream-ep115
- DevOps Lab: Demystifying ARM Templates: Variables (Abel Wang) - c5m.ca/learn-arm-ep5
- Monitoring the new followers, displaying the highest scores in order - c5m.ca/stream-ep116
Showing posts with label azure resource manager. Show all posts
Showing posts with label azure resource manager. Show all posts
Recap/ Summary Week #31
Labels:
.Net,
arm,
azure resource manager,
blazor recap,
chat bot,
container,
docker,
nodejs,
serverless,
summary
Every beginning of weekend, I will share a recap of the week and at the same time a summary of my streams. Those videos are at least two hour longs, so I thought a short summary to know if topic interest you could be useful. Watch only the summary or relax and enjoy the longer version that up to you!
Recap/ Summary of Week #30
Labels:
.Net,
arm,
azure resource manager,
chat bot,
mixted reality,
recap,
serverless,
summary,
youtube
Every beginning of weekend, I will share a recap of the week and at the same time a summary of my streams. Those videos are at least two hour longs, so I thought a short summary to know if topic interest you could be useful. Watch only the summary or relax and enjoy the longer version that up to you!
- Let's get started why Azure static web apps (John Papa): https://c5m.ca/aaa-ep15
- Mixed Reality QnA Bot (April): https://c5m.ca/aaa-ep16
- Why it's not working?! Investigating login Azure AD Token with Blazor WebAssembly: https://c5m.ca/stream-ep113
- ARM Series #4: Template Functions (Abel): https://c5m.ca/learn-arm-ep4
- Learning Node js: Serializing and deserializing an object to a file: https://c5m.ca/stream-ep114
Deploy to Azure Directly From the Repository with GitHub Actions
You hear about that new GitHub Actions. Or maybe you didn't but would like to add a continuous integration, continuous deployment (CI-CD) to your web application. In this post, I will show you how to add a CI-CD to deploy automatically to Azure using the GitHub Actions.
What are GitHub Actions
GitHub Actions are automated workflows to do things. One of these could be a CI-CD. Using a workflow you could decide to compile and execute some unit tests at every push or pull request (PR). Another workflow could be that you deploy that application.
In this article, I will deploy a .Net Core application in Azure. However, you can use any languages you would like and deploy anywhere you like... I just needed to pick one :)
Now, let's get started.
Step 1 - The Code.
We need some code in a GitHub repo. Create a GitHub repo, clone it locally. And your app in it. I created mine with
dotnet new blazorserver -n cloud5minsdemo -o src
. Then commit and push.Step 2 - Define the workflow
We got the code, now it's time to define our workflow. I will be providing all the code snippets required for the scenario cover in this post, but there is tons of template ready to be used available directly from your GitHub repository! Let's have a look. From your repository click on the Action tab, and voila!
When I wrote this post, a lot of available templates assumed the Azure resources already existed and you and adding a CI-CD to the mixt to automated your deployment. It's great but in my case, I was building a brand new web site so those didn't fit my needs. This is why I created my own template. The workflow I created was inspired by Azure/webapps-deploy. And there a lot of information also available on Deploy to App Service using GitHub Actions.
Let's add our template to our solution. GitHub will look in the folder
.github/workflows/
from the root of the repository. Then create a file with the extension .yml
Here the code for my
dotnet.yml
, as any YAML file the secret is in the indentation as it is whitespace sensitive:on: [push,pull_request]
env:
AZURE_WEBAPP_NAME: cloud5minsdemo # set this to your application's name
AZURE_GROUP_NAME: cloud5mins2
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
# checkout the repo
- uses: actions/checkout@master
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
with:
dotnet-version: 3.0.101
# dotnet build and publish
- name: Build with dotnet
run: dotnet build ./src --configuration Release
- name: dotnet publish
run: |
dotnet publish ./src -c Release -o myapp
- uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- run: |
az group create -n ${{ env.AZURE_GROUP_NAME }} -l eastus
az group deployment create -n ghaction -g ${{ env.AZURE_GROUP_NAME }} --template-file deployment/azuredepoy.json
# deploy web app using Azure credentials
- name: 'Azure webapp deploy'
uses: azure/webapps-deploy@v1
with:
app-name: ${{ env.AZURE_WEBAPP_NAME }}
package: './myapp'
# Azure logout
- name: logout
run: |
az logout
The Agent
There is a lot in there let's start by the first line. The
on:
is to define the trigger, in this case, the workflow will be trigger at every push or PR.The
env:
is where you can declare variables. It's totally optional, but I think it will help then templates are more complex or simply to reuse them easily.Then comes the
jobs:
definition. In this case, we will use the latest version of Ubuntu as our build agent. Of course, in a production environment, you should be more specify and select the OS that matches your needs. This job will have multiples steps defined in the, you guess it, steps:
section/We specify a branch to work with and set up our agent by:
uses: actions/setup-dotnet@v1
with:
dotnet-version: 3.0.101
This is because I have a .Net Core project. For Node.js project, it would be
uses: actions/setup-node@v1
with:
node-version: 10.x
And it would be a better idea to set the version as an environment variable to be able to change it quickly.
The next two instructions are really .Net Core focus as they will build and package the application into a folder
myapp
. Of course, in the "section" you could execute some unit test or any other validation that you may find useful.The next section may be less obvious.
- uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
Access and Secrets
To have our GitHub Action to be able to create resources and deploy the code it needs to have access. The
azure/login@v1
will let the Action login, using a Service Principal. In other words, we will create an authentication in the Azure Active Directory, with enough permission to do what we need.Let's examine the following Azure CLI command:
`az ad sp create-for-rbac --name "c5m-Frankdemo" --role contributor --scopes /subscriptions/{subscription-id} --sdk-auth`
This will create a Service Principal named "c5m-Frankdemo" with the role "contributor" on the subscription specified. The role contributor can do mostly anything except granting permission.
Because no resources already existed the GitHub Action will require more permission. If you create the Resource Group outside of the CI-CD, you could limit the access only to this specific resource group. Using this command instead:
`az ad sp create-for-rbac --name "c5m-Frankdemo" --role contributor --scopes /subscriptions/{subscription-id}/resourceGroups/{resource-group} --sdk-auth`
The Azure CLI command will return a JSON. We will copy-paste this JSON into a GitHub secret. GitHub secrets encrypted secrets and allow you to store sensitive information, such as access tokens, in your repository. To access them go in the Settings of the repository and select Secrets from the left menu.
Click the Add a new secret button, and type
AZURE_CREDENTIALS
as the name. It could be anything, as long as you use that value in the YAML file describing the workflow. Put the JSON including the curly brackets in the Value textbox and click the save button.Provisioning the Azure Resources
Now that the workflow has access we could execute some Azure CLI commands, but let's see what missing:
- run: |
az group create -n ${{ env.AZURE_GROUP_NAME }} -l eastus
az group deployment create -n ghaction -g ${{ env.AZURE_GROUP_NAME }} --template-file deployment/azuredepoy.json --parameters myWebAppName=${{ env.AZURE_WEBAPP_NAME }}
The first command will create an Azure Resource Group, where all the resources will be created. The second one will deploy the website using an Azure Resource Manager (ARM) template. The
--template-file deployment/azuredepoy.json
tells us the template is a file named azuredeploy.json located in the folder deployment. Notice that the application name is passed to a parameter myWebAppName, using the environment variable.An ARM template is simply a flat file that a lot like a JSON document. Use can use any text editor, I like doing mine with Visual Studio Code and two extensions: Azure Resource Manager Snippets, and Azure Resource Manager (ARM) Tools With those tools I can build ARM template very efficiently. For this template, we need a service plane and a web App. Here what the template looks like.
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"myWebAppName": {
"type": "string",
"metadata": {
"description": "WebAppName"
}
}
},
"variables": {},
"resources": [
{
"name": "[parameters('myWebAppName')]",
"type": "Microsoft.Web/sites",
"apiVersion": "2016-08-01",
"location": "[resourceGroup().location]",
"tags": {
"[concat('hidden-related:', resourceGroup().id, '/providers/Microsoft.Web/serverfarms/frankdemoplan')]": "Resource",
"displayName": "[parameters('myWebAppName')]"
},
"dependsOn": [
"[resourceId('Microsoft.Web/serverfarms', 'frankdemoplan')]"
],
"properties": {
"name": "[parameters('myWebAppName')]",
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', 'frankdemoplan')]"
}
},
{
"name": "frankdemoplan",
"type": "Microsoft.Web/serverfarms",
"apiVersion": "2018-02-01",
"location": "[resourceGroup().location]",
"sku": {
"name": "F1",
"capacity": 1
},
"tags": {
"displayName": "frankdemoplan"
},
"properties": {
"name": "frankdemoplan"
}
}
],
"outputs": {},
"functions": []
}
This template is simple, it only contains the two required resources: a service plan, and a web app. To learn more about the ARM Template you can read my other post or check out this excellent introduction in the documentation.
Once the template is created and saved in its folder.
The deployment
There are only two last steps to the YAML file: the deployment and logout. Let's have a quick look at the deployment.
# deploy web app using Azure credentials
- name: 'Azure webapp deploy'
uses: azure/webapps-deploy@v1
with:
app-name: ${{ env.AZURE_WEBAPP_NAME }}
package: './myapp'
Now that we are sure the resources exist in Azure we can deploy the code. This will be done with
azure/webapps-deploy@v1
that will take the package generated by dotnet into myapp. Since we are already authenticated there is no need to specify anything at this point.Everything is ready for the deployment. You just need to commit and push (into master) and the GitHub Action will be triggered. You can follow the deployment by going into the Actions tab.
After a few minutes, the website should be available in Azure. This post only shows a very simple build and deployment, but you can do so many things with those GitHub Actions, like executing tasks or packaging a container... I would love to know how you use them. Leave a comment or reach out on social media.
If you prefer, I also did a video of this post:
~
How to make your deployments successful every time
Labels:
arm,
azure,
azure resource manager,
best practices,
cloud,
cloud5mins,
post,
video
You are done with your code and you are ready to deploy it in Azure. You execute the PowerShell or Bash script you have and BOOM! The error message saying that this name is already taken. In this post, I will show you a simple way to look like a boss and make your deployment working all the time.
You could try to add a digit at the end of the resource name (ex: demo-app1, demo-app2, demo-app123...), but that’s not really professional. You could create a random string and append it to the name. Yes, that will works, once. If you are trying to redeploy your resources that value will change, therefore it will never be the same.
The solution would be to have a unique string that is constant in our environment.
The solution is to use the function
If you try to deploy this template, you will have an error because the name
Let’s create a new variable
It’s that simple! Now every time you will deploy a unique string will be added to your resource name. That string will always be the same for a Resource Group-Location deployment.
Because some resource types are more restrictive than others you may need adapt your new name. Maybe the name of your resource plus those thirteen characters hash will be too long... No problem, you can easily make it shorter and all lower case just by using
Voila, and now by using ARM template you can deploy and redeploy without any problem reproducing the same solution you built. To learn move about the ARM template you can jump in the documentation, where you will find samples, step-by-step tutorials and more.
If you have a specific question about ARM templates or if you would like to see more tips like this one, don't hesitate to ask in the comments section or reach out on social media!
I also have a video of this post if you prefer.
Image by StartupStockPhotos from Pixabay
____ with given name ____ already exists.
The tricks other use
You could try to add a digit at the end of the resource name (ex: demo-app1, demo-app2, demo-app123...), but that’s not really professional. You could create a random string and append it to the name. Yes, that will works, once. If you are trying to redeploy your resources that value will change, therefore it will never be the same.
The solution would be to have a unique string that is constant in our environment.
The solution
The solution is to use the function
UniqueString()
part of the Azure Resource Manager (ARM) template. If we look in the documentation, UniqueString creates a deterministic hash string based on the values provided as parameters. Let’s see a quick example of an ARM template to deploy a website named demo-app
.{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
"variables": {
"webAppName": "demo-app"
},
"resources": [
{
"type": "Microsoft.Web/sites",
"apiVersion": "2015-08-01",
"name": "[variables('webAppName')]",
"location": "[resourceGroup().location]",
"tags": {
"[concat('hidden-related:', resourceGroup().id, '/providers/Microsoft.Web/serverfarms/frankdemo-plan')]": "Resource",
"displayName": "[variables('webAppName')]"
},
"dependsOn": [
"Microsoft.Web/serverfarms/frankdemo-plan"
],
"properties": {
"name": "[variables('webAppName')]",
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms/', 'frankdemo-plan')]"
}
},
{
"type": "Microsoft.Web/serverfarms",
"apiVersion": "2016-09-01",
"name": "frankdemo-plan",
"location": "[resourceGroup().location]",
"sku": {
"name": "F1",
"capacity": 1
},
"tags": {
"displayName": "frankdemo-plan"
},
"properties": {
"name": "frankdemo-plan"
}
}
],
"outputs": {}
}
If you try to deploy this template, you will have an error because the name
demo-app
is already taken... no surprise here.Let’s create a new variable
suffix
and we will use the Resource Group Id and Location as values. Then we just need to append this value to our name using the function concat()
. "variables": {
"suffix": "[uniqueString(resourceGroup().id, resourceGroup().location)]",
"webAppName": "[concat('demo-app', variables('suffix'))]"
}
It’s that simple! Now every time you will deploy a unique string will be added to your resource name. That string will always be the same for a Resource Group-Location deployment.
Because some resource types are more restrictive than others you may need adapt your new name. Maybe the name of your resource plus those thirteen characters hash will be too long... No problem, you can easily make it shorter and all lower case just by using
substring()
and toLower()
. "parameters": {},
"variables": {
"suffix": "[substring(toLower(uniqueString(resourceGroup().id, resourceGroup().location)),0,5)]",
"webAppName": "[concat('demo-app', variables('suffix'))]"
}
Voila, and now by using ARM template you can deploy and redeploy without any problem reproducing the same solution you built. To learn move about the ARM template you can jump in the documentation, where you will find samples, step-by-step tutorials and more.
If you have a specific question about ARM templates or if you would like to see more tips like this one, don't hesitate to ask in the comments section or reach out on social media!
In a video, please!
I also have a video of this post if you prefer.
Image by StartupStockPhotos from Pixabay
Subscribe to:
Posts (Atom)