Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,16 @@ The values stored in [/apimartifacts](./apimartifacts/) correspond to the dev en

## Infrastructure overview

For the MVE we'll use 2 environments. Each environment has its own instance of API management in dedicated VNet.
For the MVE we'll use 2 types of environment. Each environment has its own instance of API management in dedicated VNet.
We will have multiple application environment.

For backend applications we'll use shared AKS cluster. Each environment will have its own Kubernetes namespace. All backend services will be exposed via the same
ingress and will be available for APIm by urls:
- apim-mve-dev.${some-public-dns-zone}
- apim-mve-stage.${some-public-dns-zone}
- apim-mve-prod.${some-public-dns-zone}

![Infrastructure](./assets/Infra-backend.drawio.png)
![Infrastructure](./assets/Azure-Infrastructure.png)

## Pre-Requisites

Expand Down
172 changes: 172 additions & 0 deletions assets/Azure-Infrastructure.drawio

Large diffs are not rendered by default.

Binary file added assets/Azure-Infrastructure.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
73 changes: 0 additions & 73 deletions assets/Infra-backend.drawio

This file was deleted.

Binary file removed assets/Infra-backend.drawio.png
Binary file not shown.
82 changes: 82 additions & 0 deletions infrastructure/backend.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
resource "azurerm_resource_group" "backend_rg" {
name = var.backend_rg_name
location = var.location
}

module "aks" {
source = "./modules/azure-public-aks"
aks_name = var.aks_name
aks_rg = azurerm_resource_group.backend_rg.name
}

resource "azurerm_role_assignment" "aks_pull_acr" {
depends_on = [module.aks]
scope = azurerm_container_registry.acr.id
role_definition_name = "AcrPull"
principal_id = module.aks.principal_id
}

provider "kubernetes" {
host = module.aks.host
client_certificate = module.aks.client_certificate
client_key = module.aks.client_key
cluster_ca_certificate = module.aks.cluster_ca_certificate
}

provider "kubectl" {
host = module.aks.host
client_certificate = module.aks.client_certificate
client_key = module.aks.client_key
cluster_ca_certificate = module.aks.cluster_ca_certificate
load_config_file = false
}

provider "helm" {
kubernetes {
host = module.aks.host
client_certificate = module.aks.client_certificate
client_key = module.aks.client_key
cluster_ca_certificate = module.aks.cluster_ca_certificate
}
}

resource "azurerm_public_ip" "ingress_nginx_public_ip" {
name = "${var.aks_name}-ingress-nginx"
resource_group_name = module.aks.node_resource_group
location = var.location
allocation_method = "Static"
sku = "Standard"
zones = ["1", "2", "3"]
ip_tags = {}
tags = {
k8s-azure-cluster-name = var.aks_name
k8s-azure-service = "ingress-nginx/ingress-nginx-controller"
}
}

module "ingress-nginx" {
depends_on = [module.aks, azurerm_public_ip.ingress_nginx_public_ip]
source = "./modules/kubernetes-ingress-nginx"
public_ip_address = azurerm_public_ip.ingress_nginx_public_ip.ip_address
providers = {
helm = helm
}
}

module "cert-manager" {
source = "./modules/kubernetes-cert-manager"
acme_email = "[email protected]"
providers = {
helm = helm
kubectl = kubectl
}
}

resource "azurerm_dns_a_record" "backend_a_records" {
for_each = toset(var.backend_endpoints)
name = each.value
zone_name = azurerm_dns_zone.public_dns_zone.name
resource_group_name = azurerm_resource_group.services_rg.name
ttl = 300
records = [azurerm_public_ip.ingress_nginx_public_ip.ip_address]
}
9 changes: 9 additions & 0 deletions infrastructure/datasources.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
data "azuread_client_config" "current" {}

data "azurerm_role_definition" "aks_cluster_admin" {
role_definition_id = "0ab0b1a8-8aac-4efd-b8c2-3ee1fb270be8"
}

data "azurerm_role_definition" "aks_cluster_user" {
role_definition_id = "4abbcc35-e782-43d8-92c5-2d3f1bd2253f"
}
97 changes: 41 additions & 56 deletions infrastructure/main.tf
Original file line number Diff line number Diff line change
@@ -1,56 +1,41 @@
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.67.0"
}
azuread= {
source = "hashicorp/azuread"
version = "~> 2.41.0"
}
}

required_version = ">= 0.15.3"
}

provider "azurerm" {
skip_provider_registration = "true"
features {}
}

provider "azuread" {
}

# Configure a Service Principal so that we can access the APIM in the different Resource Groups
data "azurerm_client_config" "current" {}

# The current logged in user will be the owner of the application
resource "azuread_application" "apim_app" {
display_name = "api_ops_app"
owners = [data.azurerm_client_config.current.object_id]
}

resource "azuread_service_principal" "apim_spn" {
application_id = azuread_application.apim_app.application_id
owners = [data.azurerm_client_config.current.object_id]
}

resource "azuread_service_principal_password" "spn" {
service_principal_id = azuread_service_principal.apim_spn.id
}

module "apim_dev" {
source = "./apim"
location = var.location
prefix = var.prefix
service_principal_object_id = azuread_service_principal.apim_spn.object_id
environment = "dev"
}

module "apim_prod" {
source = "./apim"
location = var.location
prefix = var.prefix
service_principal_object_id = azuread_service_principal.apim_spn.object_id
environment = "prod"
}
## The current logged in user will be the owner of the application

# TODO:

# Deploy helm - AKS admin

# push APIm config to dev
# push APIm config to dev

# push APIm config to dev


# resource "azuread_application" "apim_app" {
# display_name = "api_ops_app"
# owners = [data.azurerm_client_config.current.object_id]
# }

# resource "azuread_service_principal" "apim_spn" {
# application_id = azuread_application.apim_app.application_id
# owners = [data.azurerm_client_config.current.object_id]
# }

# resource "azuread_service_principal_password" "spn" {
# service_principal_id = azuread_service_principal.apim_spn.id
# }

#module "apim_dev" {
# source = "./modules/apim"
# location = var.location
# prefix = var.prefix
# service_principal_object_id = azuread_service_principal.apim_spn.object_id
# environment = "dev"
#}
#
#module "apim_prod" {
# source = "./modules/apim"
# location = var.location
# prefix = var.prefix
# service_principal_object_id = azuread_service_principal.apim_spn.object_id
# environment = "prod"
#}
File renamed without changes.
File renamed without changes.
5 changes: 5 additions & 0 deletions infrastructure/modules/azure-public-aks/datasources.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
data "azuread_client_config" "current" {}

data "azurerm_role_definition" "aks_cluster_user" {
role_definition_id = "4abbcc35-e782-43d8-92c5-2d3f1bd2253f"
}
55 changes: 55 additions & 0 deletions infrastructure/modules/azure-public-aks/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
resource "azurerm_kubernetes_cluster" "aks" {
name = var.aks_name
location = var.aks_location
resource_group_name = var.aks_rg
dns_prefix = "${var.aks_name}-dns"
kubernetes_version = var.aks_version
automatic_channel_upgrade = "patch"
identity {
type = "SystemAssigned"
}

default_node_pool {
name = "default"
vm_size = var.default_vm_size
enable_auto_scaling = true
min_count = var.default_pool_min_nodes
max_count = var.default_pool_max_nodes
os_disk_size_gb = var.default_pool_os_disk_size_gb
os_sku = "Ubuntu"
tags = {}
}
network_profile {
dns_service_ip = var.dns_service_ip
ip_versions = ["IPv4"]
load_balancer_sku = "standard"
network_plugin = "kubenet"
outbound_type = "loadBalancer"
pod_cidr = var.aks_pod_cidr
service_cidr = var.aks_service_cidr
}
}

resource "azuread_application" "aks_cluster_user" {
display_name = format("%s%s", var.aks_name, "-user")
owners = [data.azuread_client_config.current.object_id]
}

resource "azuread_service_principal" "aks_cluster_user" {
application_id = azuread_application.aks_cluster_user.application_id
owners = [data.azuread_client_config.current.object_id]
}

resource "azurerm_role_assignment" "aks_cluster_user" {
scope = azurerm_kubernetes_cluster.aks.id
role_definition_id = data.azurerm_role_definition.aks_cluster_user.id
principal_id = azuread_service_principal.aks_cluster_user.object_id

lifecycle {
ignore_changes = [role_definition_id] # see https://github.com/hashicorp/terraform-provider-azurerm/issues/4258
}
}

resource "azuread_service_principal_password" "aks_cluster_user_password" {
service_principal_id = azuread_service_principal.aks_cluster_user.object_id
}
23 changes: 23 additions & 0 deletions infrastructure/modules/azure-public-aks/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
output "principal_id" {
value = azurerm_kubernetes_cluster.aks.kubelet_identity[0].object_id
}

output "host" {
value = azurerm_kubernetes_cluster.aks.kube_config.0.host
}

output "client_certificate" {
value = base64decode(azurerm_kubernetes_cluster.aks.kube_config.0.client_certificate)
}

output "client_key" {
value = base64decode(azurerm_kubernetes_cluster.aks.kube_config.0.client_key)
}

output "cluster_ca_certificate" {
value = base64decode(azurerm_kubernetes_cluster.aks.kube_config.0.cluster_ca_certificate)
}

output "node_resource_group" {
value = lower(azurerm_kubernetes_cluster.aks.node_resource_group)
}
Loading