Skip to content

Commit ad1c4fa

Browse files
Refactor Bicep templates and parameter files for improved clarity and consistency
1 parent 0864845 commit ad1c4fa

File tree

7 files changed

+140
-92
lines changed

7 files changed

+140
-92
lines changed

.github/workflows/deploy-aca-package.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,35 @@ env:
2828
app-config-name: 'red-eus2-academo-appconfig'
2929

3030
jobs:
31+
buildInfra:
32+
runs-on: ubuntu-latest
33+
34+
steps:
35+
- name: Checkout to the branch
36+
uses: actions/checkout@v2
37+
38+
- name: Azure Login
39+
uses: azure/login@v1
40+
with:
41+
creds: ${{ secrets.AZURE_CREDENTIALS }}
42+
43+
- name: Create Resource Group, Deploy Bicep
44+
uses: azure/CLI@v1
45+
with:
46+
inlineScript: |
47+
az group create -l ${{ env.LOCATION }} -n ${{ env.resource-group-name}}
48+
az deployment group create --resource-group ${{ env.resource-group-name }} \
49+
--name todo-webapi-aca \
50+
--parameters ./iac/main-deploy-aca.bicepparam keyValueNames=${{ secrets.KEY_VALUE_NAMES }} keyValueValues=${{ secrets.KEY_VALUE_VALUES }}
51+
52+
- name: Azure CLI script
53+
uses: azure/CLI@v1
54+
with:
55+
inlineScript: |
56+
az logout
57+
az cache purge
58+
az account clear
59+
3160
build:
3261
runs-on: ubuntu-latest
3362

README.md

Lines changed: 63 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,32 @@
1+
# Web API Container App Demo
12

3+
## Table of Contents
24

3-
# Web Api Container App demo
5+
- [Introduction](#introduction)
6+
- [Description](#description)
7+
- [Badges](#badges)
8+
- [How to Use](#how-to-use)
9+
- [Requirements](#requirements)
10+
- [Setup](#setup)
11+
- [GitHub Workflows](#github-workflows)
12+
- [deploy-aca-package.yml](#deploy-aca-packageyml)
13+
- [deploy-aks-package.yml](#deploy-aks-packageyml)
14+
- [deploy-app-service.yml](#deploy-app-serviceyml)
15+
- [deploy-app-service-image-only.yml](#deploy-app-service-image-onlyyml)
416

5-
This application is an example web api that has been containerized so it can be deployed into a Azure Container App, Azure App Service, or AKS depending on which pipeline you would like to use. It is also created as an example of following deployment best practices for [continuously deployment of containers](https://learn.microsoft.com/en-us/azure/app-service/deploy-best-practices#continuously-deploy-containers).
17+
## Introduction
18+
19+
This application is a containerized example of a .NET web API that can be deployed to Azure Container Apps, Azure App Service, or AKS. My attempt is to demonstrates best practices for [continuous deployment of containers](https://learn.microsoft.com/en-us/azure/app-service/deploy-best-practices#continuously-deploy-containers).
620

721
## Description
822

9-
This project was created initially by using the sample todo .Net web api from the Microsoft learn site: [Create web API using ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/tutorials/first-web-api?view=aspnetcore-6.0&tabs=visual-studio-code). Multiple controllers have been added so here is a quick definition of each:
10-
- TodoController
11-
- InMemory representation of a database to store the `TodoItemDTO` object. The api supports the basic CRUD operations.
12-
- WeatherForecastController
13-
- Returns a hard coded weather forecast as an enumerable that can be used for testing.
14-
- ConfigController
15-
- Sample Azure App Configuration implementation that I like to have around to refer back to. Please check here if you would like more info on [Azure App Configuration](https://learn.microsoft.com/en-us/azure/azure-app-configuration/overview)
23+
This project is based on the sample ToDo .NET web API from the Microsoft Learn site: [Create web API using ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/tutorials/first-web-api?view=aspnetcore-6.0&tabs=visual-studio-code). Additional controllers have been added:
24+
25+
- **TodoController**: Implements CRUD operations using an in-memory database for `TodoItemDTO` objects.
26+
- **WeatherForecastController**: Returns a hardcoded weather forecast for testing purposes.
27+
- **ConfigController**: Demonstrates Azure App Configuration. Learn more about [Azure App Configuration](https://learn.microsoft.com/en-us/azure/azure-app-configuration/overview).
1628

17-
There is also a Dockerfile as part of this project that is used to containerize the app and push it up to Azure Container Registry(ACR). Once the image is in ACR, it then creates/updates the Azure Container App for the demo web api. All of this is done in the `deploy-package.yml` GitHub actions workflow. See workflow section below for more specifics on the workflow.
29+
The project includes a Dockerfile for containerization and multiple GitHub Actions workflows. See **Github Worflows** section below for details on each deployment type.
1830

1931
## Badges
2032

@@ -23,87 +35,71 @@ There is also a Dockerfile as part of this project that is used to containerize
2335
| Azure Container App Deployment | [![Trigger container apps deployment](https://github.com/anotherRedbeard/web-api-demo-container/actions/workflows/deploy-aca-package.yml/badge.svg?branch=main)](https://github.com/anotherRedbeard/web-api-demo-container/actions/workflows/deploy-aca-package.yml) |
2436
| Azure App Service Deployment | [![Trigger app service deployment](https://github.com/anotherRedbeard/web-api-demo-container/actions/workflows/deploy-app-service.yml/badge.svg)](https://github.com/anotherRedbeard/web-api-demo-container/actions/workflows/deploy-app-service.yml) |
2537
| Azure App Service Slot Deployment | [![Trigger app service deployment of image only](https://github.com/anotherRedbeard/web-api-demo-container/actions/workflows/deploy-app-service-image-only.yml/badge.svg)](https://github.com/anotherRedbeard/web-api-demo-container/actions/workflows/deploy-app-service-image-only.yml) |
26-
| Azure Kubernetes Service (AKS) Deployment | [![Trigger aks app deployment](https://github.com/anotherRedbeard/web-api-demo-container/actions/workflows/deploy-aks-package.yaml/badge.svg)](https://github.com/anotherRedbeard/web-api-demo-container/actions/workflows/deploy-aks-package.yaml) |
38+
| Azure Kubernetes Service (AKS) Deployment | [![Trigger aks app deployment](https://github.com/anotherRedbeard/web-api-demo-container/actions/workflows/deploy-aks-package.yaml/badge.svg)](https://github.com/anotherRedbeard/web-api-demo-container/actions/workflows/deploy-aks-package.yaml) |
2739

28-
## How to use
40+
## How to Use
2941

30-
This is meant to be a repo that you can clone and use as you like. The only thing you will need to change is the variables in the `deploy-package.yml` workflow. They will be in the `env` section of the workflow. There will need to change to match the resource names you would like to use in your Azure Subscription.
42+
This repository is designed to be cloned and customized. Follow the steps below to set it up.
3143

3244
### Requirements
3345

3446
- **Azure Subscription**
35-
- **This repo cloned in your own GitHub repo**
36-
- **Create an appsettings.Development.json file and fill out with the structure from appsettings.json**
37-
- **Service principle with contributor access to the subscription created as a GitHub Secret**
38-
- This is only so you can create your resource group at the subscription level, if you don't want to give your service principle that kind of access you will need to have another way to create the resource group and then you can remove that step from the workflow
39-
- The credentials for this service principle need to be stored according to this document: [Service Principal Secret](https://learn.microsoft.com/en-us/azure/developer/github/connect-from-azure?tabs=azure-portal%2Clinux#use-the-azure-login-action-with-a-service-principal-secret)
40-
- I have used the name `AZURE_CREDENTIALS` for the secret
41-
- ==For the AKS and App Server deployment== you will need to have write permission which is greater than Contributor because these bicep files are assigning a role to the underlying service principal so you can pull the image from the registry in the app service and you can enable the AKS cluster to communicate with the registry and perform kubectl commands. For my purposes I assigned `User Access Administrator` role to the service principal running the pipeline.
42-
- **Azure App Configuration resource**
43-
- **This is optional and only needed if you want to call the ConfigController**
44-
- Add the following configuration settings
45-
- | Key | Value | Label |
46-
| ----------- | ----------- | -- |
47-
|TestAp:Settings:Message|DEV - Data from Azure App Configuration | dev |
48-
|TestAp:Settings:Message|TEST - Data from Azure App Configuration | test |
49-
|TestAp:Settings:Sentinel|1 | |
50-
|TestAp:<oid for user 1>:Sentinel|ConnectionStringForUser1 | |
51-
|TestAp:<oid for user 2>:Sentinel|ConnectionStringForUser2 | |
52-
\* `<oid for user 1>` and `<oid for user 2>` should be replaced with the actual Object IDs for the users. This is used in the ConfigController.cs to show how to get a different connectionstring at runtime based on the logged in user
53-
- Create a managed identity and grant it `App Configuration Data Reader` on the Azure App Configuration Access Control so it will be able to read the values.
47+
- **GitHub Repository**: Clone this repository into your own GitHub account.
48+
- **Configuration File**: Create an `appsettings.Development.json` file based on the structure in `appsettings.json`.
49+
- **Service Principal**: Create a service principal with Contributor access to your Azure subscription. The credentials for this service principle need to be stored according to this document: [Service Principal Secret](https://learn.microsoft.com/en-us/azure/developer/github/connect-from-azure?tabs=azure-portal%2Clinux#use-the-azure-login-action-with-a-service-principal-secret) and stored in a GitHub secret named `AZURE_CREDENTIALS`. You will also need to assign the `User Access Administrator` role because we are doing role assignments in the bicep files.
50+
- **Azure App Configuration Resource** (Optional):
51+
- Add the following configuration settings:
52+
53+
| Key | Value | Label |
54+
| ----------- | ----------- | -- |
55+
| TestAp:Settings:Message | DEV - Data from Azure App Configuration | dev |
56+
| TestAp:Settings:Message | TEST - Data from Azure App Configuration | test |
57+
| TestAp:Settings:Sentinel | 1 | |
58+
| TestAp:<oid for user 1>:Sentinel | ConnectionStringForUser1 | |
59+
| TestAp:<oid for user 2>:Sentinel | ConnectionStringForUser2 | |
60+
61+
- Replace `<oid for user 1>` and `<oid for user 2>` with actual Object IDs.
62+
- Create a managed identity and grant it `App Configuration Data Reader` access.
63+
64+
### Setup
65+
66+
1. Clone the repository.
67+
2. Update the `env` section in the workflows with your Azure resource names.
68+
3. Add the `AZURE_CREDENTIALS` secret to your GitHub repository.
69+
4. (Optional) Configure Azure App Configuration as described above.
5470

5571
## GitHub Workflows
5672

57-
There are a few workflows used by this project to demonstrate the different ways and resources you can deploy to. Currently there are examples for an App Service, Azure Container App, and Azure Kubernetes Service (AKS).
73+
This project includes workflows for deploying to Azure Container Apps, App Service, and AKS.
5874

5975
### `deploy-aca-package.yml`
6076

61-
The workflow will deploy everything it needs to a given resource group and into an Azure Container App. It has 4 separate stages: expose-env, build-infra, build, deploy
77+
Deploys to Azure Container Apps in four stages:
6278

63-
1. expose-env
64-
- Unfortunately you need to expose the environment variables that you want to use as output variables so they can be passed into the shared workflow. Ideally it would be nice if you could just use the standard `env` variables
65-
2. build-infra
66-
- Uses a shared workflow that accepts the variables that were exposed as environment variables in the first stage to create the required infrastructure you need for Azure Container Apps. These actions are idempotent so they can be run multiple times.
67-
- The shared workflow is just an example of what you might want to do for your organization to keep things consistent.
68-
3. build
69-
- Builds the container and tags the image
70-
4. deploy
71-
- Uses the container image that was built and pushed to ACR and creates/updates that container app with that newly built image. There is [another repo](https://github.com/anotherRedbeard/blazor-demo-container) that contains a UI (Blazor client app) that will call this `todo`. There is a reference here to that client UI to get the URI that can be added to CORS. If it doesn't exist it will add `*`.
79+
1. **build**: Builds and tags the container image.
80+
2. **deploy**: Deploys the container image to Azure Container Apps. There is [another repo](https://github.com/anotherRedbeard/blazor-demo-container) that contains a UI (Blazor client app) that will call this `todo`. There is a reference here to that client UI to get the URI that can be added to CORS. If it doesn't exist it will add `*`.
7281

7382
### `deploy-aks-package.yml`
7483

75-
The workflow is using bicep templates to create everything it needs for an AKS cluster into a given resource group. It has 3 separate stages: buildInfra, buildImage, deploy
84+
Deploys to AKS in three stages:
7685

77-
1. buildInfra
78-
- Uses azure credentials to create a resource group via the `az cli` and then calls the `az deployment group create` command to deploy the bicep templates that are stored in the `./iac/` folder. This will create all the infrastructure you need to support this demo api implementation for AKS. These actions are idempotent so they can be run multiple times.
79-
2. buildImage
80-
- Builds the container and tags the image
81-
3. deploy
82-
- While this repo is only for the `todo` api, there is [another repo](https://github.com/anotherRedbeard/blazor-demo-container) that creates a UI (Blazor client app) that connects to this todo api. The first part of this stage is to get that URL so we can add it to the CORS list.
83-
- Next we use a `sed` script to replace variables in the AKS deployment file so it can be dynamic to use the container image we just built.
84-
- Finally we use the deployment file to setup the deployment in AKS
86+
1. **buildInfra**: Creates infrastructure using Bicep templates.
87+
2. **buildImage**: Builds and tags the container image.
88+
3. **deploy**: Deploys the container to AKS and updates CORS settings. While this repo is only for the `todo` api, there is [another repo](https://github.com/anotherRedbeard/blazor-demo-container) that creates a UI (Blazor client app) that connects to this todo api. The first part of this stage is to get that URL so we can add it to the CORS list. Next we use a `sed` script to replace variables in the AKS deployment file so it can be dynamic to use the container image we just built.
8589

8690
### `deploy-app-service.yml`
8791

88-
The workflow is using bicep templates to create everything it needs for an App services container deployment for this API. It has 2 separate stages: build-infra, build-deploy
92+
Deploys to Azure App Service in two stages:
8993

90-
1. build-infra
91-
- Uses azure credentials to create a resource group via the `az cli` and then calls the `az deployment group create` command to deploy the bicep templates that are stored in the `./iac/` folder. This will create all the infrastructure you need to support this demo api implementation for Azure app service. These actions are idempotent so they can be run multiple times.
92-
2. build-deploy
93-
- Builds the container, tags the image, and deploys it to container registry.
94-
- Deploys the container to the app service and sets up the config so it can get the image again for scaling and failures.
94+
1. **build-infra**: Creates infrastructure using Bicep templates.
95+
2. **build-deploy**: Builds, tags, and deploys the container image.
9596

9697
### `deploy-app-service-image-only.yml`
9798

98-
The workflow deploys a new version of the code to a container, pushes it to the registry and then updates the app service 'stage' slot with the new image revision. This assumes that all of the infrastructure is already in place (see previous workflow `deploy-app-service.yml`) and it meant to demonstrate [slot deployments](https://learn.microsoft.com/en-us/azure/app-service/deploy-staging-slots?tabs=portal) for zero downtime on your app service. It has 2 separate stages: build-deploy, swap-slot
99-
100-
1. build-deploy
101-
- Builds the container, tags the image, and deploys it to container registry.
102-
- Deploys the container to the app service
103-
2. swap-slot
104-
- Uses the environment parameter to ensure that a manual approval can be done before swapping the slots
105-
- Swaps the stage slot to the production slot once it has been approved
99+
Demonstrates [slot deployments](https://learn.microsoft.com/en-us/azure/app-service/deploy-staging-slots?tabs=portal) for zero downtime. Stages:
106100

107-
In order to test this, there is a `monitor-api.sh` file that can be used to ping the api every 2 seconds to show how the latency isn't impacted by just swapping the slots. If you want, you can create a copy of the `monitor-api.sh` file into an environment specific file `monitor-api.dev.sh` that is ignored by the `.gitignore` file. Here is an example output that shows the response changes from being prefixed with 'green' and then swapped to be prefixed with 'blue':
101+
1. **build-deploy**: Builds, tags, and deploys the container image.
102+
2. **swap-slot**: Swaps the staging slot with the production slot after manual approval.
108103

104+
Use the `monitor-api.sh` script to test slot swapping. It pings the api every 2 seconds to show how the latency isn't impacted by just swapping the slots. If you want, you can create a copy of the `monitor-api.sh` file into an environment specific file `monitor-api.dev.sh` that is ignored by the `.gitignore` file. Here is an example output that shows the response changes from being prefixed with 'green' and then swapped to be prefixed with 'blue':
109105
![Image showing slot swapping response times](./img/monitor-example.png)

0 commit comments

Comments
 (0)