Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Aks bicep module #718

Merged
merged 9 commits into from
Sep 13, 2022
1 change: 1 addition & 0 deletions src/bicep/examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ You [must first deploy MissionLZ](../README.md#Deployment), then you can deploy

Example | Description
------- | -----------
[AKS](./aks) | Deploys an AKS cluster into [Tier 3 Spoke Network](../add-ons/tier3/README.md).
[appServicePlan](./app-service-plan) | Deploys an App Service Plan (AKA: Web Server Cluster) to support simple web accessible linux docker containers with optional dynamic auto scaling.
[Automation Account](./automation-account) | Deploys an Azure Automation account that can be used to execute runbooks.
[Container Registry](./container-registry/) | Deploys an Azure Container Registry for holding and deploying docker containers.
Expand Down
64 changes: 64 additions & 0 deletions src/bicep/examples/aks/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Overview

The example below deploys an AKS cluster into [Tier 3 Spoke Network](../../add-ons/tier3/README.md) but could be deployed into any existing Spoke Network.

## Pre-requisites

1. A virtual network and subnet is deployed.
1. Define values for Required Parameters described below

Required Parameters | Description
------------------- | -----------
vnetName | Existing Vnet Name
subnetName | Existing Subnet Name
vnetRgName | Resource group that the Vnet belongs to
dnsServiceIp | An IP address assigned to the Kubernetes DNS service. It must be within the Kubernetes service address range specified in serviceCidr.
serviceCidr | A CIDR notation IP range from which to assign service cluster IPs. It must not overlap with any Subnet IP ranges.
dockerBridgeCidr | A CIDR notation IP range assigned to the Docker bridge network. It must not overlap with any Subnet IP ranges or the Kubernetes service address range.

1. Decide if the optional parameters is appropriate for your deployment. If it needs to change, override one of the optional parameters.

Optional Parameters | Default | Description
------------------- | ----------- | -----------
resourcePrefix | mlz | A prefix, 3 to 10 characters in length, to append to resource names (e.g. "dev", "test", "prod", "mlz"). It defaults to "mlz".
resourceSuffix | mlz | A suffix, 3 to 6 characters in length, to append to resource names (e.g. "dev", "test", "prod", "mlz"). It defaults to "mlz".
aksAgentCount| 1 | Number of agents (VMs) to host docker containers. Allowed values must be in the range of 0 to 1000 (inclusive) for user pools and in the range of 1 to 1000 (inclusive) for system pools. The default value is 1. Please note that increasing this value will require more available IPs in the subnet.
aksDnsPrefix | mlzaks | Optional DNS prefix to use with hosted Kubernetes API server FQDN, 1 to 54 characters in length, can contain alphanumerics and hyphens, but should start and end with alphanumeric. This cannot be updated once the Managed Cluster has been created. It defaults to "mlzaks".
kubernetesVersion | 1.21.9 | AKS cluster kubernetes version.
vmSize | Standard_D2_v2 | VM size availability varies by region. If a node contains insufficient compute resources (memory, cpu, etc) pods might fail to run correctly. For more details on restricted VM sizes, see: [Sizes for virtual machines in Azure](https://docs.microsoft.com/en-us/azure/virtual-machines/sizes).

## Deploy the example

Once you have the Mission LZ output values, you can pass those in as parameters to this deployment.

And deploy with `az deployment sub create` from the Azure CLI or `New-AzSubscriptionDeployment` from Azure PowerShell.

### Deploying AKS cluster into Tier 3 Subnet

Connect to the appropriate Azure Environment and set appropriate context, see [getting started with Azure PowerShell or Azure CLI](../../examples/README.md) for help if needed. The commands below assume you are deploying in Azure Commercial and show the entire process from deploying MLZ and then adding an Azure App Service Plan post-deployment.

```PowerShell
cd .\src\bicep
Connect-AzAccount
New-AzSubscriptionDeployment -Name contoso -TemplateFile .\mlz.bicep -resourcePrefix 'contoso' -Location 'eastus'
cd .\add-ons
(Get-AzSubscriptionDeployment -Name contoso).outputs | ConvertTo-Json | Out-File -FilePath .\deploymentVariables.json
cd .\tier3
New-AzSubscriptionDeployment -DeploymentName deployTier3 -TemplateFile .\tier3.bicep -resourcePrefix myTier3 -subnetAddressPrefix '10.0.125.0/26' -Location 'eastus'
cd ..\aks
(Get-AzSubscriptionDeployment -Name deployTier3).outputs | ConvertTo-Json | Out-File -FilePath .\vnetDeploymentVariables.json
New-AzSubscriptionDeployment -DeploymentName deployAKS -TemplateFile .\aks.bicep -resourcePrefix myAKS -dnsServiceIp '10.1.0.10' -serviceCidr '10.1.0.0/16' -dockerBridgeCidr '170.10.0.1/16' -Location 'eastus'
```

```Azure CLI
az login
cd src/bicep
az deployment sub create -n contoso -f mlz.bicep -l eastus --parameters resourcePrefix=contoso
cd add-ons
az deployment sub show -n contoso --query properties.outputs > ./deploymentVariables.json
cd tier3
az deployment sub create -n deployTier3 -f tier3.bicep -l eastus --parameters resourcePrefix='myTier3' subnetAddressPrefix='10.0.125.0/26'
cd ../../examples/aks
az deployment sub show -n deployTier3 --query properties.outputs > ./vnetDeploymentVariables.json
az deployment sub create -n deployAKS -f aks.bicep -l eastus --parameters resourcePrefix='myAKS' dnsServiceIp='10.1.0.10' serviceCidr='10.1.0.0/16' dockerBridgeCidr='170.10.0.1/16'
```
127 changes: 127 additions & 0 deletions src/bicep/examples/aks/aks.bicep
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/*
Copyright (c) Microsoft Corporation.
Licensed under the MIT License.
*/

targetScope = 'subscription'
/*

PARAMETERS

Here are all the parameters a user can override.

These are the required parameters that aks bicep does not provide a default for:
- vnetName
- subnetName
- vnetRgName
- dnsServiceIp
- serviceCidr
- dockerBridgeCidr
*/

// REQUIRED PARAMETERS

@minLength(3)
@maxLength(10)
@description('A prefix, 3-10 alphanumeric characters without whitespace, used to prefix resources and generate uniqueness for resources with globally unique naming requirements like Storage Accounts and Log Analytics Workspaces')
param resourcePrefix string = 'mlz'

@minLength(3)
@maxLength(6)
@description('A suffix, 3 to 6 characters in length, to append to resource names (e.g. "dev", "test", "prod", "mlz"). It defaults to "mlz".')
param resourceSuffix string = 'mlz'

@description('Vnet deployment output variables in json format. It defaults to the vnetDeploymentVariables.json.')
param vnetDeploymentVariables object = json(loadTextContent('./vnetDeploymentVariables.json'))
param vnetName string = vnetDeploymentVariables.virtualNetworkName.value
param subnetName string = vnetDeploymentVariables.subnetName.value
param vnetRgName string = vnetDeploymentVariables.resourceGroupName.value

@description('An IP address assigned to the Kubernetes DNS service. It must be within the Kubernetes service address range specified in serviceCidr.')
param dnsServiceIp string

@description('A CIDR notation IP range from which to assign service cluster IPs. It must not overlap with any Subnet IP ranges.')
param serviceCidr string

@description('A CIDR notation IP range assigned to the Docker bridge network. It must not overlap with any Subnet IP ranges or the Kubernetes service address range.')
param dockerBridgeCidr string

@description('The region to deploy resources into. It defaults to the deployment location.')
param location string = deployment().location

@description('A string dictionary of tags to add to deployed resources. See https://docs.microsoft.com/en-us/azure/azure-resource-manager/management/tag-resources?tabs=json#arm-templates for valid settings.')
param tags object = {}

@description('Number of agents (VMs) to host docker containers. Allowed values must be in the range of 0 to 1000 (inclusive) for user pools and in the range of 1 to 1000 (inclusive) for system pools. The default value is 1.')
param aksAgentCount int = 1

@minLength(1)
@maxLength(54)
@description('Optional DNS prefix to use with hosted Kubernetes API server FQDN, 1 to 54 characters in length, can contain alphanumerics and hyphens, but should start and end with alphanumeric. This cannot be updated once the Managed Cluster has been created.')
param aksDnsPrefix string = '${resourcePrefix}aks'

@description('AKS cluster kubernetes version.')
param kubernetesVersion string = '1.24.3'

@description('VM size availability varies by region. If a node contains insufficient compute resources (memory, cpu, etc) pods might fail to run correctly. For more details on restricted VM sizes, see: https://docs.microsoft.com/en-us/azure/virtual-machines/sizes')
param vmSize string = 'Standard_D2_v2'

/*

NAMING CONVENTION

Here we define a naming conventions for resources.

First, we take `resourcePrefix` and `resourceSuffix` by params.
Then, using string interpolation "${}", we insert those values into a naming convention.

*/
var resourceToken = 'resource_token'
var nameToken = 'name_token'
var namingConvention = '${toLower(resourcePrefix)}-${resourceToken}-${nameToken}-${toLower(resourceSuffix)}'

var resourceGroupNamingConvention = replace(namingConvention, resourceToken, 'rg')
var aksResourceGroupName = replace(resourceGroupNamingConvention, nameToken, aksName)
var aksName = 'aks'

var defaultTags = {
'DeploymentType': 'MissionLandingZoneARM'
}
var calculatedTags = union(tags, defaultTags)

module resourceGroup '../../modules/resource-group.bicep' = {
name: aksResourceGroupName
params: {
name: aksResourceGroupName
location: location
tags: calculatedTags
}
}

resource vnet 'Microsoft.Network/virtualNetworks@2019-11-01' existing = {
name: vnetName
scope: az.resourceGroup(vnetRgName)
}

resource subnet 'Microsoft.Network/virtualNetworks/subnets@2021-05-01' existing = {
parent: vnet
name: subnetName
}

module aks '../../modules/aks.bicep' = {
name: aksName
scope: az.resourceGroup(resourceGroup.name)
params: {
name: aksName
tags: calculatedTags
location: location
dnsServiceIp: dnsServiceIp
dockerBridgeCidr: dockerBridgeCidr
serviceCidr: serviceCidr
kubernetesVersion: kubernetesVersion
aksDnsPrefix: aksDnsPrefix
aksAgentCount: aksAgentCount
vmSize: vmSize
subnetId: subnet.id
}
}
66 changes: 66 additions & 0 deletions src/bicep/modules/aks.bicep
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
Copyright (c) Microsoft Corporation.
Licensed under the MIT License.
*/

param name string
param location string = resourceGroup().location
param tags object = {}

@description('AKS cluster kubernetes version.')
param kubernetesVersion string = '1.21.9'

@minLength(1)
@maxLength(54)
@description('Optional DNS prefix to use with hosted Kubernetes API server FQDN, 1 to 54 characters in length, can contain alphanumerics and hyphens, but should start and end with alphanumeric. This cannot be updated once the Managed Cluster has been created.')
param aksDnsPrefix string

@description('Number of agents (VMs) to host docker containers. Allowed values must be in the range of 0 to 1000 (inclusive) for user pools and in the range of 1 to 1000 (inclusive) for system pools. The default value is 1.')
param aksAgentCount int = 1

@description('VM size availability varies by region. If a node contains insufficient compute resources (memory, cpu, etc) pods might fail to run correctly. For more details on restricted VM sizes, see: https://docs.microsoft.com/en-us/azure/virtual-machines/sizes')
param vmSize string = 'Standard_D2_v2'

//Network Profile
@description('This is of the form: /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/virtualNetworks/{virtualNetworkName}/subnets/{subnetName}')
param subnetId string

@description('An IP address assigned to the Kubernetes DNS service. It must be within the Kubernetes service address range specified in serviceCidr.')
param dnsServiceIp string

@description('A CIDR notation IP range from which to assign service cluster IPs. It must not overlap with any Subnet IP ranges.')
param serviceCidr string

@description('A CIDR notation IP range assigned to the Docker bridge network. It must not overlap with any Subnet IP ranges or the Kubernetes service address range.')
param dockerBridgeCidr string

resource aksCluster 'Microsoft.ContainerService/managedClusters@2021-10-01' = {
name: name
location: location
tags: tags
identity: {
type: 'SystemAssigned'
}
properties: {
dnsPrefix: aksDnsPrefix
agentPoolProfiles: [
{
name: 'nodepool1'
count: aksAgentCount
vmSize: vmSize
vnetSubnetID: subnetId
osType: 'Linux'
mode: 'System'
}
]
networkProfile: {
loadBalancerSku: 'standard'
networkPlugin: 'azure'
networkPolicy: 'azure'
dnsServiceIP: dnsServiceIp
serviceCidr: serviceCidr
dockerBridgeCidr: dockerBridgeCidr
}
kubernetesVersion: kubernetesVersion
}
}