Skip to content

Commit

Permalink
Add azure linux app service with docker example (#25)
Browse files Browse the repository at this point in the history
* Add azure linux app service with docker example

* Update azure/azure_linux_docker_app_service/monitoring.tf

Co-authored-by: Lauri Hukkanen <lauri.hukkanen@futurice.com>

Co-authored-by: Lauri Hukkanen <lauri.hukkanen@futurice.com>
  • Loading branch information
tomi and lhuk-futurice authored Nov 29, 2020
1 parent c1412b1 commit 2ccb2fa
Show file tree
Hide file tree
Showing 18 changed files with 836 additions and 6 deletions.
122 changes: 116 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,21 @@ To regenerate the readme, run `npm run readme`
- resource aws_ssm_parameter
- resource random_string
- [azure](azure)
- [azure/azure_linux_docker_app_service](azure/azure_linux_docker_app_service)
- resource azurerm_app_service
- resource azurerm_app_service_plan
- resource azurerm_app_service_slot
- resource azurerm_application_insights
- resource azurerm_application_insights_web_test
- resource azurerm_container_registry
- resource azurerm_key_vault
- resource azurerm_key_vault_access_policy
- resource azurerm_key_vault_secret
- resource azurerm_monitor_action_group
- resource azurerm_monitor_metric_alert
- resource azurerm_monitor_scheduled_query_rules_alert
- resource azurerm_role_assignment
- resource random_string
- [azure/layers](azure/layers)
- resource azurerm_resource_group
- resource azurerm_storage_account
Expand Down Expand Up @@ -1323,6 +1338,101 @@ p.s. Instead of environment variables, you can obviously use .tfvar files for as
# Azure Examples


# [azure/azure_linux_docker_app_service](azure/azure_linux_docker_app_service)
# azure_linux_docker_app_service

This terraform example demonstrates how to create a container based Linux App Service with secret management and monitoring.

## Features

- [Managed identity](https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview) for authentication instead of credentials
- [Key vault references](https://docs.microsoft.com/en-us/azure/app-service/app-service-key-vault-references) for accessing secrets from App Service
- Email alerts for errors and failed availability checks
- Random suffix for resources requiring globally unique name

## Azure services

![Architecture](azure/azure_linux_docker_app_service/images/architecture.png)

### [Azure Container Registry](https://azure.microsoft.com/en-us/services/)

For storing container images

- App Service pulls the image from the registry during deployment
- Authentication using managed identity

### [Key Vault](https://azure.microsoft.com/en-us/services/key-vault/)

For storing and accessing secrets

- Access management using access policies

### App Service plan & [App Service](https://azure.microsoft.com/en-us/services/app-service/)

For hosting the application. App Service is created into the plan. If you have multiple App Services, it is possible to share the same plan among them.

- The application's docker image is deployed from the container registry
- Managed identity for accessing the Key Vault & Container registry
- Deployment slot for high availability deploys
- App service has a lot of settings that can be configured. See all of them [here](https://github.com/projectkudu/kudu/wiki/Configurable-settings).

### [Application Insights](https://docs.microsoft.com/en-us/azure/azure-monitor/app/app-insights-overview)

User for monitoring, metrics, logs and alerts.

- The application should use Application Insights library (e.g. for [Node.js](https://www.npmjs.com/package/applicationinsights)) to instrument the application and integrate it with App Insights
- Includes availability checks from multiple locations
- Email alert for:
- Failed availability checks
- Responses with 5xx response code
- Failed dependencies (e.g. database query or HTTP request fails)

## Example usage

Prerequisites

- Azure account and a service principal
- Resource group
- Terraform [Azure Provider](https://www.terraform.io/docs/providers/azurerm/) set up

```tf
module "my_app" {
# Required
resource_group_name = "my-resource-group"
alert_email_address = "example@example.com"
# Optional (with their default values)
name_prefix = "azure-app-example--"
app_service_name = "appservice"
app_insights_app_type = "other"
app_service_plan_tier = "PremiumV2"
app_service_plan_size = "P1v2"
}
```

We can create rest of the resources with `terraform apply`.

An example of a Node.js application can be found in `./example-app` directory.

## Building an image and deploying to the App Service

- [Using Github actions](https://docs.microsoft.com/en-us/azure/app-service/deploy-container-github-action)
- [Using Azure DevOps pipelines](https://docs.microsoft.com/en-us/azure/devops/pipelines/tasks/deploy/azure-rm-web-app-containers?view=azure-devops)

## Inputs

| Name | Description | Type | Default | Required |
| --------------------- | ------------------------------------------------------------------------------------------------------------------- | :----: | :---------------------: | :------: |
| resource_group_name | Name of the resource group where the resources are deployed | string | | yes |
| alert_email_address | Email address where alerts are sent | string | | yes |
| name_prefix | Name prefix to use for objects that need to be created (only lowercase alphanumeric characters and hyphens allowed) | string | `"azure-app-example--"` | no |
| app_service_name | Name of the app service to be created. Must be globally unique | string | `"appservice"` | no |
| app_insights_app_type | Application insights application type | string | `"other"` | no |
| app_service_plan_tier | App service plan tier | string | `"PremiumV2"` | no |
| app_service_plan_size | App service plan size | string | `"P1v2"` | no |



# [azure/layers](azure/layers)
# Terraform Azure Layers example

Expand All @@ -1348,7 +1458,11 @@ sh destroy.sh ${USER}trylayers
- `destroy.sh` takes a quick, resource-group based approach to wiping out the whole deployment.
- `layers.tf` lists each layer with associated dependencies.
- `main.tf` contains sample resources used on different layers.
- `variables.sh` declares associated variables with sane defaults.
- `variables.sh` declares associated variables with sane defaults


# [azure/layers](azure/layers)
.



Expand Down Expand Up @@ -1463,11 +1577,7 @@ Terraform receipe for running Camunda BPMN workflow engine serverlessly on Cloud
Customize the base image in the main.tf locals.

Read more on the blog
- [Provisioning Serverless Ca


# [google_cloud/camunda-secure](google_cloud/camunda-secure)
munda on Cloud Run](https://www.futurice.com/blog/serverless-camunda-terraform-recipe-using-cloud-run-and-cloud-sql)
- [Provisioning Serverless Camunda on Cloud Run](https://www.futurice.com/blog/serverless-camunda-terraform-recipe-using-cloud-run-and-cloud-sql)
- [Call external services with at-least-once delevery](https://www.futurice.com/blog/at-least-once-delivery-for-serverless-camunda-workflow-automation)


Expand Down
91 changes: 91 additions & 0 deletions azure/azure_linux_docker_app_service/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# azure_linux_docker_app_service

This terraform example demonstrates how to create a container based Linux App Service with secret management and monitoring.

## Features

- [Managed identity](https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview) for authentication instead of credentials
- [Key vault references](https://docs.microsoft.com/en-us/azure/app-service/app-service-key-vault-references) for accessing secrets from App Service
- Email alerts for errors and failed availability checks
- Random suffix for resources requiring globally unique name

## Azure services

![Architecture](images/architecture.png)

### [Azure Container Registry](https://azure.microsoft.com/en-us/services/)

For storing container images

- App Service pulls the image from the registry during deployment
- Authentication using managed identity

### [Key Vault](https://azure.microsoft.com/en-us/services/key-vault/)

For storing and accessing secrets

- Access management using access policies

### App Service plan & [App Service](https://azure.microsoft.com/en-us/services/app-service/)

For hosting the application. App Service is created into the plan. If you have multiple App Services, it is possible to share the same plan among them.

- The application's docker image is deployed from the container registry
- Managed identity for accessing the Key Vault & Container registry
- Deployment slot for high availability deploys
- App service has a lot of settings that can be configured. See all of them [here](https://github.com/projectkudu/kudu/wiki/Configurable-settings).

### [Application Insights](https://docs.microsoft.com/en-us/azure/azure-monitor/app/app-insights-overview)

User for monitoring, metrics, logs and alerts.

- The application should use Application Insights library (e.g. for [Node.js](https://www.npmjs.com/package/applicationinsights)) to instrument the application and integrate it with App Insights
- Includes availability checks from multiple locations
- Email alert for:
- Failed availability checks
- Responses with 5xx response code
- Failed dependencies (e.g. database query or HTTP request fails)

## Example usage

Prerequisites

- Azure account and a service principal
- Resource group
- Terraform [Azure Provider](https://www.terraform.io/docs/providers/azurerm/) set up

```tf
module "my_app" {
# Required
resource_group_name = "my-resource-group"
alert_email_address = "example@example.com"
# Optional (with their default values)
name_prefix = "azure-app-example--"
app_service_name = "appservice"
app_insights_app_type = "other"
app_service_plan_tier = "PremiumV2"
app_service_plan_size = "P1v2"
}
```

We can create rest of the resources with `terraform apply`.

An example of a Node.js application can be found in `./example-app` directory.

## Building an image and deploying to the App Service

- [Using Github actions](https://docs.microsoft.com/en-us/azure/app-service/deploy-container-github-action)
- [Using Azure DevOps pipelines](https://docs.microsoft.com/en-us/azure/devops/pipelines/tasks/deploy/azure-rm-web-app-containers?view=azure-devops)

## Inputs

| Name | Description | Type | Default | Required |
| --------------------- | ------------------------------------------------------------------------------------------------------------------- | :----: | :---------------------: | :------: |
| resource_group_name | Name of the resource group where the resources are deployed | string | | yes |
| alert_email_address | Email address where alerts are sent | string | | yes |
| name_prefix | Name prefix to use for objects that need to be created (only lowercase alphanumeric characters and hyphens allowed) | string | `"azure-app-example--"` | no |
| app_service_name | Name of the app service to be created. Must be globally unique | string | `"appservice"` | no |
| app_insights_app_type | Application insights application type | string | `"other"` | no |
| app_service_plan_tier | App service plan tier | string | `"PremiumV2"` | no |
| app_service_plan_size | App service plan size | string | `"P1v2"` | no |
51 changes: 51 additions & 0 deletions azure/azure_linux_docker_app_service/access_policies.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Key vault access for the current client principal
resource "azurerm_key_vault_access_policy" "principal" {
key_vault_id = azurerm_key_vault.current.id

tenant_id = data.azurerm_client_config.current.tenant_id
object_id = data.azurerm_client_config.current.object_id

secret_permissions = [
"get",
"set",
"delete"
]
}

# Key vault access for the App Service
resource "azurerm_key_vault_access_policy" "app_service" {
key_vault_id = azurerm_key_vault.current.id

tenant_id = data.azurerm_client_config.current.tenant_id
object_id = azurerm_app_service.current.identity.0.principal_id

secret_permissions = [
"get",
]
}

# Key vault access for the App Service's next slot
resource "azurerm_key_vault_access_policy" "app_service_next_slot" {
key_vault_id = azurerm_key_vault.current.id

tenant_id = data.azurerm_client_config.current.tenant_id
object_id = azurerm_app_service_slot.next.identity.0.principal_id

secret_permissions = [
"get",
]
}

# Pull access for the app service
resource "azurerm_role_assignment" "app_service_acr_pull" {
scope = azurerm_container_registry.current.id
role_definition_name = "AcrPull"
principal_id = azurerm_app_service.current.identity.0.principal_id
}

# Pull access for the app service's next slot
resource "azurerm_role_assignment" "app_service_next_slot_acr_pull" {
scope = azurerm_container_registry.current.id
role_definition_name = "AcrPull"
principal_id = azurerm_app_service_slot.next.identity.0.principal_id
}
Loading

0 comments on commit 2ccb2fa

Please sign in to comment.