diff --git a/.github/workflows/publish_bicep_module.yml b/.github/workflows/publish_bicep_module.yml deleted file mode 100644 index e3b0740..0000000 --- a/.github/workflows/publish_bicep_module.yml +++ /dev/null @@ -1,43 +0,0 @@ -name: Publish Bicep modules - -on: - workflow_dispatch: - -permissions: - id-token: write - contents: read - -jobs: - publish: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - - name: 'Az CLI login' - uses: azure/login@v1 - with: - client-id: ${{ secrets.AZURE_CLIENT_ID }} - tenant-id: ${{ secrets.AZURE_TENANT_ID }} - subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} - - - name: Install Bicep - run: | - az version - az bicep install - - - name: Publish Bicep modules to Azure Container Registry - run: | - for d in */ - do - cd $d - version="v$(cat metadata.json | jq -r '.version.major').$(cat metadata.json | jq -r '.version.minor')" - if [ -z "$(az acr repository show -n ${{ secrets.ACR_SERVER }} --image bicep/modules/${d::-1}:$version 2>/dev/null)" ]; - then - echo "Publishing br:${{ secrets.ACR_SERVER }}/bicep/modules/${d::-1}:$version"; - az bicep publish --file main.bicep --target "br:${{ secrets.ACR_SERVER }}/bicep/modules/${d::-1}:$version"; - else - echo "Skipping br:${{ secrets.ACR_SERVER }}/bicep/modules/${d::-1}:$version as it already exists"; - fi - cd - > /dev/null - done - working-directory: bicep/modules diff --git a/bicep/modules/azure-cli-script/README.md b/bicep/modules/azure-cli-script/README.md deleted file mode 100644 index f9f475f..0000000 --- a/bicep/modules/azure-cli-script/README.md +++ /dev/null @@ -1,22 +0,0 @@ -# azure-cli-script - -This module deploys a [Microsoft.Resources/deploymentScripts](https://learn.microsoft.com/azure/templates/microsoft.resources/deploymentscripts?pivots=deployment-language-bicep) resource to run Azure CLI commands as part of your deployment. The deployment will create a User-Assigned Managed Identity and it will be granted Contributor permissions to perform actions within your subscription. - -## Inputs - -| Name | Description | Expected Value | -|------|-------------|----------------| -| `name` | This is the name of the resource | Whatever you want | -| `location` | Region to deploy resource into | Azure region that offers this resource | -| `tags` | Tags | Object of key/value pairs | -| `azCliVersion` | Azure CLI version | Usually supports latest-1 | -| `cleanupPreference` | Indicates when to cleanup Azure Container Instance | Defaults to `OnSuccess` | -| `scriptContent` | Inline Azure CLI script | | - -## Outputs - -| Name | Description | -|------|-------------| -| N/A | | - -https://learn.microsoft.com/en-us/azure/templates/microsoft.resources/deploymentscripts?pivots=deployment-language-bicep#azurecliscriptproperties \ No newline at end of file diff --git a/bicep/modules/azure-cli-script/main.bicep b/bicep/modules/azure-cli-script/main.bicep deleted file mode 100644 index f059a0d..0000000 --- a/bicep/modules/azure-cli-script/main.bicep +++ /dev/null @@ -1,62 +0,0 @@ -param name string -param location string -param tags object - -@description('https://learn.microsoft.com/en-us/cli/azure/release-notes-azure-cli') -param azCliVersion string = '2.40.0' - -@allowed([ - 'Always' - 'OnExpiration' - 'OnSuccess' -]) -param cleanupPreference string = 'OnSuccess' -param scriptContent string - -resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: 'uid-${name}' - location: location -} - -// Get the role definition resource by name, to find the name for the role Contributor, you can look -// it up at the following url: https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles#contributor -resource contributorRoleDefinition 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { - name: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - scope: subscription() -} - -resource roleAssignmentDeploymentContributor 'Microsoft.Authorization/roleAssignments@2020-08-01-preview' = { - name: guid(managedIdentity.id, 'Contributor') - properties: { - roleDefinitionId: contributorRoleDefinition.id - principalId: managedIdentity.properties.principalId - principalType: 'ServicePrincipal' - } -} - -resource deploymentScript 'Microsoft.Resources/deploymentScripts@2020-10-01' = { - name: name - location: location - tags: tags - identity: { - type: 'UserAssigned' - userAssignedIdentities: { - '${managedIdentity.id}': {} - } - } - kind: 'AzureCLI' - properties: { - azCliVersion: azCliVersion - cleanupPreference: cleanupPreference - containerSettings: { - containerGroupName: 'deploymentScript' - } - retentionInterval: 'PT1H' - scriptContent: scriptContent - timeout: 'PT1H' - } - - dependsOn: [ - roleAssignmentDeploymentContributor - ] -} diff --git a/bicep/modules/azure-cli-script/metadata.json b/bicep/modules/azure-cli-script/metadata.json deleted file mode 100644 index 7dd04c0..0000000 --- a/bicep/modules/azure-cli-script/metadata.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "version": { - "major": 0, - "minor": 1 - } -} \ No newline at end of file diff --git a/bicep/modules/azure-container-registry/README.MD b/bicep/modules/azure-container-registry/README.MD deleted file mode 100644 index c179df1..0000000 --- a/bicep/modules/azure-container-registry/README.MD +++ /dev/null @@ -1,23 +0,0 @@ -# azure-container-registry - -This module deploys a [Microsoft.ContainerRegistry/registries](https://learn.microsoft.com/azure/templates/microsoft.containerregistry/registries?pivots=deployment-language-bicep) resource using only parameters scoped for these labs. - -## Inputs - -| Name | Description | Expected Value | -|------|-------------|----------------| -| `name` | This is the name of the resource | Whatever you want | -| `location` | Region to deploy resource into | Azure region that offers this resource | -| `tags` | Tags | Object of key/value pairs | -| `sku` | SKU to deploy | `'Basic'`
`'Standard'`
`'Premium'` -| `managedIdentityType` | Managed identity type to assign on the resource | `'SystemAssigned'`
`'UserAssigned'` | -| `userAssignedIdentities` | List of user assigned identity resource IDs to assign to the resource when the managed identity type is set to `UserAssigned` | Array of resource IDs | -| `adminUserEnabled` | Enables the admin account | `true` or `false` | -| `anonymousPullEnabled` | Enables anonymous pull access | `true` or `false` | -| `publicNetworkAccess` | Enables public network access | `true` or `false` | - -## Outputs - -| Name | Description | -|------|-------------| -| `name` | This is the name of the resource | diff --git a/bicep/modules/azure-container-registry/main.bicep b/bicep/modules/azure-container-registry/main.bicep deleted file mode 100644 index 4942591..0000000 --- a/bicep/modules/azure-container-registry/main.bicep +++ /dev/null @@ -1,48 +0,0 @@ -param name string -param location string -param tags object - -@allowed([ - 'Basic' - 'Standard' - 'Premium' -]) -@description('Defaults to Standard') -param sku string = 'Standard' - -@allowed([ - 'SystemAssigned' - 'UserAssigned' -]) -@description('Two options are available: SystemAssigned or UserAssigned') -param managedIdentityType string = 'SystemAssigned' - -@description('Required when managed identity type is set to UserAssigned') -param userAssignedIdentities object = {} - -param adminUserEnabled bool = false - -param anonymousPullEnabled bool = false - -@description('Disableing public network access is not supported for Basic and Standard SKUs') -param publicNetworkAccess bool = (sku == 'Premium' ? false : true) - -resource registry 'Microsoft.ContainerRegistry/registries@2022-02-01-preview' = { - name: name - location: location - tags: tags - sku: { - name: sku - } - identity: { - type: managedIdentityType - userAssignedIdentities: managedIdentityType != 'SystemAssigned' ? userAssignedIdentities : null - } - properties: { - adminUserEnabled: adminUserEnabled - anonymousPullEnabled: anonymousPullEnabled - publicNetworkAccess: publicNetworkAccess ? 'Enabled' : 'Disabled' - } -} - -output name string = registry.name diff --git a/bicep/modules/azure-container-registry/metadata.json b/bicep/modules/azure-container-registry/metadata.json deleted file mode 100644 index 28e74a8..0000000 --- a/bicep/modules/azure-container-registry/metadata.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "version": { - "major": 0, - "minor": 2 - } -} \ No newline at end of file diff --git a/bicep/modules/azure-cosmos-db/README.md b/bicep/modules/azure-cosmos-db/README.md deleted file mode 100644 index 541f032..0000000 --- a/bicep/modules/azure-cosmos-db/README.md +++ /dev/null @@ -1,21 +0,0 @@ -# azure-cosmos-db - -This module deploys a [Microsoft.DocumentDB/databaseAccounts](https://learn.microsoft.com/en-us/azure/templates/microsoft.documentdb/databaseaccounts?pivots=deployment-language-bicep) resource using only parameters scoped for these labs. - -## Inputs - -| Name | Description | Expected Value | -|------|-------------|----------------| -| `name` | This is the name of the resource | Whatever you want | -| `location` | Region to deploy resource into | Azure region that offers this resource | -| `tags` | Tags | Object of key/value pairs | -| `kind` | Type of database account | `'GlobalDocumentDB'`
`'MongoDB'` (default)
`'Parse'` | -| `mongoApiVersion` | MongoApi version | `'3.2'`
`'3.6'`
`'4.0'`
`'4.2'` (default) | -| `managedIdentityType` | Managed identity type to assign on the resource | `'SystemAssigned'`
`'UserAssigned'` | -| `locations` | Array of geo-replication location objects | See: [locations](https://learn.microsoft.com/azure/templates/microsoft.documentdb/databaseaccounts?pivots=deployment-language-bicep#location) | -| `userAssignedIdentities` | List of user assigned identity resource IDs to assign to the resource when the managed identity type is set to `UserAssigned` | Array of resource IDs | - -## Outputs - -| Name | Description | -|------|-------------| diff --git a/bicep/modules/azure-cosmos-db/main.bicep b/bicep/modules/azure-cosmos-db/main.bicep deleted file mode 100644 index 1bd0be6..0000000 --- a/bicep/modules/azure-cosmos-db/main.bicep +++ /dev/null @@ -1,50 +0,0 @@ -param name string -param location string -param tags object - -@allowed([ - 'GlobalDocumentDB' - 'MongoDB' - 'Parse' -]) -param kind string = 'MongoDB' - -@allowed([ - '3.2' - '3.6' - '4.0' - '4.2' -]) -param mongoApiVersion string = '4.2' - -@allowed([ - 'None' - 'SystemAssigned' - 'UserAssigned' - 'SystemAssigned,UserAssigned' -]) -param managedIdentityType string = 'SystemAssigned' - -@description('Used when managedIdentityType is UserAssigned') -param userAssignedIdentities object = {} - -@description('Array of location objects with the following properties: failoverPriority, isZoneRedundant, locationName') -param locations array - -resource databaseAccount 'Microsoft.DocumentDB/databaseAccounts@2022-05-15' = { - name: name - location: location - tags: tags - kind: kind - identity: { - type: managedIdentityType - userAssignedIdentities: empty(userAssignedIdentities) ? null : userAssignedIdentities - } - properties: { - databaseAccountOfferType: 'Standard' - locations: locations - apiProperties: kind == 'MongoDB' ? { - serverVersion: mongoApiVersion - } : null - } -} diff --git a/bicep/modules/azure-cosmos-db/metadata.json b/bicep/modules/azure-cosmos-db/metadata.json deleted file mode 100644 index 7dd04c0..0000000 --- a/bicep/modules/azure-cosmos-db/metadata.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "version": { - "major": 0, - "minor": 1 - } -} \ No newline at end of file diff --git a/bicep/modules/azure-dns/README.md b/bicep/modules/azure-dns/README.md deleted file mode 100644 index 9322d5c..0000000 --- a/bicep/modules/azure-dns/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# azure-dns-zone - -This module deploys a [Microsoft.Network/dnsZones](https://learn.microsoft.com/azure/templates/microsoft.network/dnszones?pivots=deployment-language-bicep) resource using only parameters scoped for these labs. - -## Inputs - -| Name | Description | Expected Value | -|------|-------------|----------------| -| `name` | This is the name of the resource | Whatever you want | -| `location` | Region to deploy resource into | Azure region that offers this resource | -| `tags` | Tags | Object of key/value pairs | -| `zoneType` | Zone type | `'Public'`
`'Private'` | - -## Outputs - -| Name | Description | -|------|-------------| -| `id` | Resource identifier | diff --git a/bicep/modules/azure-dns/main.bicep b/bicep/modules/azure-dns/main.bicep deleted file mode 100644 index ec62a30..0000000 --- a/bicep/modules/azure-dns/main.bicep +++ /dev/null @@ -1,20 +0,0 @@ -param name string -param location string -param tags object - -@allowed([ - 'Public' - 'Private' -]) -param zoneType string - -resource dnsZone 'Microsoft.Network/dnsZones@2018-05-01' = { - name: name - location: location - tags: tags - properties: { - zoneType: zoneType - } -} - -output id string = dnsZone.id diff --git a/bicep/modules/azure-dns/metadata.json b/bicep/modules/azure-dns/metadata.json deleted file mode 100644 index 7dd04c0..0000000 --- a/bicep/modules/azure-dns/metadata.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "version": { - "major": 0, - "minor": 1 - } -} \ No newline at end of file diff --git a/bicep/modules/azure-key-vault/README.md b/bicep/modules/azure-key-vault/README.md deleted file mode 100644 index 97b20a0..0000000 --- a/bicep/modules/azure-key-vault/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# azure-key-vault - -This module deploys a [Microsoft.KeyVault/vaults](https://learn.microsoft.com/azure/templates/microsoft.keyvault/vaults?pivots=deployment-language-bicep) resource using only parameters scoped for these labs. The deployment will set initial access policy for the user that runs the Bicep template and also accepts an array of `resourceAccessPolicies` for additional policy assignments. - -## Inputs - -| Name | Description | Expected Value | -|------|-------------|----------------| -| `name` | This is the name of the resource | Whatever you want | -| `location` | Region to deploy resource into | Azure region that offers this resource | -| `tags` | Tags | Object of key/value pairs | -| `sku` | Resource SKU | `premium` or `standard` (default) | -| `userObjectId` | The user object Id to give full-access to | This is typically the identity that runs the template | -| `tenantId` | The tenant which the objectIds belong to for access policy assignments | | -| `accessPolicies` | Array of `accessPolicy` objects | See: [AccessPolicyEntry](https://learn.microsoft.com/azure/templates/microsoft.keyvault/vaults?pivots=deployment-language-bicep#accesspolicyentry) | - -## Outputs - -| Name | Description | -|------|-------------| diff --git a/bicep/modules/azure-key-vault/main.bicep b/bicep/modules/azure-key-vault/main.bicep deleted file mode 100644 index 4b0d568..0000000 --- a/bicep/modules/azure-key-vault/main.bicep +++ /dev/null @@ -1,57 +0,0 @@ -param name string -param location string -param tags object - -@allowed([ - 'premium' - 'standard' -]) -param sku string = 'standard' - -@description('The object ID of a user, service principal or security group in AAD tenant.') -param userObjectId string -param tenantId string - -@description('List of AccessPolicyEntry which is used when granting additional permissions for other users or managed identities') -param accessPolicies array = [] - -resource vault 'Microsoft.KeyVault/vaults@2022-07-01' = { - name: name - location: location - tags: tags - properties: { - accessPolicies: [ - { - objectId: userObjectId - permissions: { - certificates: [ - 'all' - ] - keys: [ - 'all' - ] - secrets: [ - 'all' - ] - storage: [ - 'all' - ] - } - tenantId: tenantId - } - ] - sku: { - family: 'A' - name: sku - } - tenantId: tenantId - } -} - -resource resourceAccessPolicies 'Microsoft.KeyVault/vaults/accessPolicies@2022-07-01' = if (!empty(accessPolicies)) { - name: 'add' - parent: vault - properties: { - accessPolicies: accessPolicies - } -} diff --git a/bicep/modules/azure-key-vault/metadata.json b/bicep/modules/azure-key-vault/metadata.json deleted file mode 100644 index 7dd04c0..0000000 --- a/bicep/modules/azure-key-vault/metadata.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "version": { - "major": 0, - "minor": 1 - } -} \ No newline at end of file diff --git a/bicep/modules/azure-kubernetes-service-addons/README.md b/bicep/modules/azure-kubernetes-service-addons/README.md deleted file mode 100644 index b98c121..0000000 --- a/bicep/modules/azure-kubernetes-service-addons/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# azure-kubernetes-service-addons - -This module updates an AKS cluster to append add-ons. [`addonProfiles`](https://learn.microsoft.com/azure/templates/microsoft.containerservice/managedclusters?pivots=deployment-language-bicep#managedclusterproperties) are not very well documented. - -> This Bicep template will emit warnings due to the `mode: 'Incremental'` setting. This module still works and the warning messaging is being tracked here: https://github.com/Azure/bicep/issues/784 - -## Inputs - -| Name | Description | Expected Value | -|------|-------------|----------------| -| `location` | Region to deploy resource into | Azure region that offers this resource | -| `clusterId` | Existing cluster resource Id | | -| `addonProfiles` | Add-ons to enable | No concrete definition so your best bet is to deploy using Azure CLI or Portal and see what the JSON metadata looks like | - -## Outputs - -| Name | Description | -|------|-------------| diff --git a/bicep/modules/azure-kubernetes-service-addons/main.bicep b/bicep/modules/azure-kubernetes-service-addons/main.bicep deleted file mode 100644 index 8d3ccf2..0000000 --- a/bicep/modules/azure-kubernetes-service-addons/main.bicep +++ /dev/null @@ -1,18 +0,0 @@ -param location string -param clusterId string - -@description('AKS addons to enable') -param addonProfiles object - -@description('Pull out the cluster name from the resource ID') -var clusterName = split(clusterId, '/')[8] - -resource managedCluster 'Microsoft.ContainerService/managedClusters@2022-08-03-preview' = { - name: clusterName - location: location - properties: { - mode: 'Incremental' - id: clusterId - addonProfiles: addonProfiles - } -} diff --git a/bicep/modules/azure-kubernetes-service-addons/metadata.json b/bicep/modules/azure-kubernetes-service-addons/metadata.json deleted file mode 100644 index 7dd04c0..0000000 --- a/bicep/modules/azure-kubernetes-service-addons/metadata.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "version": { - "major": 0, - "minor": 1 - } -} \ No newline at end of file diff --git a/bicep/modules/azure-kubernetes-service-ingress-dns/README.md b/bicep/modules/azure-kubernetes-service-ingress-dns/README.md deleted file mode 100644 index ab03dc1..0000000 --- a/bicep/modules/azure-kubernetes-service-ingress-dns/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# azure-kubernetes-service-ingress-dns - -**Work in Progress** - -This module will take the `principalId` of the `webapprouting` managed identity resource and assign the "DNS Zone Contributor" to it at the Azure DNS resource scope. - -> This Bicep template will emit warnings due to the `mode: 'Incremental'` setting. This module still works and the warning messaging is being tracked here: https://github.com/Azure/bicep/issues/784 - -## Inputs - -| Name | Description | Expected Value | -|------|-------------|----------------| -| `dnsZoneName` | The DNS zone name used to pull the existing resource for RBAC assignment | -| `principalId` | The principal id of the user-assigned managed identity that is provisioned in the AKS managed cluster resource group (starts with `MC_*`) | | - -## Outputs - -| Name | Description | -|------|-------------| -| N/A | | diff --git a/bicep/modules/azure-kubernetes-service-ingress-dns/main.bicep b/bicep/modules/azure-kubernetes-service-ingress-dns/main.bicep deleted file mode 100644 index 5da4140..0000000 --- a/bicep/modules/azure-kubernetes-service-ingress-dns/main.bicep +++ /dev/null @@ -1,23 +0,0 @@ -param dnsZoneName string -param principalId string - -resource dnsZone 'Microsoft.Network/dnsZones@2018-05-01' existing = { - name: dnsZoneName -} - -// Get the role definition resource by name, to find the name for the role DNS Zone Contributor, you can look -// it up at the following url: https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles#dns-zone-contributor -resource dnsZoneContributorRoleDefinition 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { - scope: subscription() - name: 'befefa01-2a29-4197-83a8-272ff33ce314' -} - -resource dnsZoneContributorRoleAssignment 'Microsoft.Authorization/roleAssignments@2020-08-01-preview' = { - name: guid(dnsZone.id, 'DNS Zone Contributor') - scope: dnsZone - properties: { - roleDefinitionId: dnsZoneContributorRoleDefinition.id - principalId: principalId - principalType: 'User' - } -} diff --git a/bicep/modules/azure-kubernetes-service-ingress-dns/metadata.json b/bicep/modules/azure-kubernetes-service-ingress-dns/metadata.json deleted file mode 100644 index 7dd04c0..0000000 --- a/bicep/modules/azure-kubernetes-service-ingress-dns/metadata.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "version": { - "major": 0, - "minor": 1 - } -} \ No newline at end of file diff --git a/bicep/modules/azure-kubernetes-service-ingress/README.md b/bicep/modules/azure-kubernetes-service-ingress/README.md deleted file mode 100644 index 4344e58..0000000 --- a/bicep/modules/azure-kubernetes-service-ingress/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# azure-kubernetes-service-ingress - -This module updates an AKS cluster to install the `webAppRouting` add-on via `ingressProfile`. [`ingressProfiles`](https://learn.microsoft.com/azure/templates/microsoft.containerservice/managedclusters?pivots=deployment-language-bicep#managedclusteringressprofile) requires a [`webAppRouting`](https://learn.microsoft.com/azure/templates/microsoft.containerservice/managedclusters?pivots=deployment-language-bicep#managedclusteringressprofilewebapprouting) object to enable the managed NGINX ingress controller in the cluster. This object accepts an optional `dnsZoneResourceId` to enable the `external-dns` controller. - -> This Bicep template will emit warnings due to the `mode: 'Incremental'` setting. This module still works and the warning messaging is being tracked here: https://github.com/Azure/bicep/issues/784 - -## Inputs - -| Name | Description | Expected Value | -|------|-------------|----------------| -| `location` | Region to deploy resource into | Azure region that offers this resource | -| `clusterId` | Existing cluster resource Id | | -| `dnsZoneResourceId` | Azure DNS zone resource identifier | This is optional and not required for `webAppRouting` | - -## Outputs - -| Name | Description | -|------|-------------| -| N/A | | diff --git a/bicep/modules/azure-kubernetes-service-ingress/main.bicep b/bicep/modules/azure-kubernetes-service-ingress/main.bicep deleted file mode 100644 index 1dd47ca..0000000 --- a/bicep/modules/azure-kubernetes-service-ingress/main.bicep +++ /dev/null @@ -1,21 +0,0 @@ -param location string -param clusterId string -param dnsZoneResourceId string = '' - -var clusterName = split(clusterId, '/')[8] -var attachDnsZone = dnsZoneResourceId != '' - -resource updateManagedCluster 'Microsoft.ContainerService/managedClusters@2022-08-03-preview' = { - name: clusterName - location: location - properties: { - mode: 'Incremental' - id: clusterId - ingressProfile: { - webAppRouting: { - dnsZoneResourceId: attachDnsZone ? dnsZoneResourceId : null - enabled: true - } - } - } -} diff --git a/bicep/modules/azure-kubernetes-service-ingress/metadata.json b/bicep/modules/azure-kubernetes-service-ingress/metadata.json deleted file mode 100644 index 7dd04c0..0000000 --- a/bicep/modules/azure-kubernetes-service-ingress/metadata.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "version": { - "major": 0, - "minor": 1 - } -} \ No newline at end of file diff --git a/bicep/modules/azure-kubernetes-service-nodepools/README.md b/bicep/modules/azure-kubernetes-service-nodepools/README.md deleted file mode 100644 index 6a7bc44..0000000 --- a/bicep/modules/azure-kubernetes-service-nodepools/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# azure-kubernetes-service-nodepools - -This module deploys a [Microsoft.ContainerService/managedClusters/agentPools](https://learn.microsoft.com/azure/templates/microsoft.containerservice/managedclusters/agentpools?pivots=deployment-language-bicep) resource using only parameters scoped for these labs. - -## Inputs - -| Name | Description | Expected Value | -|------|-------------|----------------| -| `name` | This is the name of the resource | Whatever you want | -| `location` | Region to deploy resource into | Azure region that offers this resource | -| `tags` | Tags | Object of key/value pairs | -| `managedClusterName` | Name of the AKS resource | Resource name | -| `userNodes` | Array of userNode objects. This is a dynamic object so parameter names will not always match up with template specifications. The Bicep code will iterate through each userNode object and deploy into your AKS resource. | Array of objects | - -## Outputs - -| Name | Description | -|------|-------------| -| N/A | | diff --git a/bicep/modules/azure-kubernetes-service-nodepools/main.bicep b/bicep/modules/azure-kubernetes-service-nodepools/main.bicep deleted file mode 100644 index 5f47c18..0000000 --- a/bicep/modules/azure-kubernetes-service-nodepools/main.bicep +++ /dev/null @@ -1,25 +0,0 @@ -param managedClusterName string -param userNodes array - -// Get the managed cluster by name -resource managedCluster 'Microsoft.ContainerService/managedClusters@2022-08-03-preview' existing = { - name: managedClusterName -} - -resource userNodePools 'Microsoft.ContainerService/managedClusters/agentPools@2024-02-01' = [for i in range(0, length(userNodes)): { - name: userNodes[i].name - parent: managedCluster - properties: { - vmSize: userNodes[i].vmSize - mode: userNodes[i].mode - enableAutoScaling: userNodes[i].enableAutoScaling - count: contains(userNodes[i], 'maxCount') ? userNodes[i].maxCount : 1 - minCount: userNodes[i].enableAutoScaling && contains(userNodes[i], 'minCount') ? userNodes[i].minCount : null - maxCount: userNodes[i].enableAutoScaling && contains(userNodes[i], 'maxCount') ? userNodes[i].maxCount : null - scaleDownMode: userNodes[i].enableAutoScaling && contains(userNodes[i], 'scaleDownMode') ? userNodes[i].scaleDownMode : null - nodeTaints: empty(userNodes[i].nodeTaints) ? null : userNodes[i].nodeTaints - type: userNodes[i].type - osDiskType: userNodes[i].osDiskType - vnetSubnetID: empty(userNodes[i].vnetSubnetID) ? null : userNodes[i].vnetSubnetID - } -}] diff --git a/bicep/modules/azure-kubernetes-service-nodepools/metadata.json b/bicep/modules/azure-kubernetes-service-nodepools/metadata.json deleted file mode 100644 index 28e74a8..0000000 --- a/bicep/modules/azure-kubernetes-service-nodepools/metadata.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "version": { - "major": 0, - "minor": 2 - } -} \ No newline at end of file diff --git a/bicep/modules/azure-kubernetes-service/README.md b/bicep/modules/azure-kubernetes-service/README.md deleted file mode 100644 index 0de4942..0000000 --- a/bicep/modules/azure-kubernetes-service/README.md +++ /dev/null @@ -1,39 +0,0 @@ -# azure-kubernetes-service - -This module deploys a [Microsoft.ContainerService/managedClusters](https://learn.microsoft.com/azure/templates/microsoft.containerservice/managedclusters?pivots=deployment-language-bicep) resource using only parameters scoped for these labs. - -## Inputs - -| Name | Description | Expected Value | -|------|-------------|----------------| -| `name` | This is the name of the resource | Whatever you want | -| `location` | Region to deploy resource into | Azure region that offers this resource | -| `tags` | Tags | Object of key/value pairs | -| `slaTier` | Defaults to Free tier | `'Free'`
'Paid' | -| `managedIdentityType` | Two options are available: SystemAssigned or UserAssigned | `'SystemAssigned'`
`'UserAssigned'` | -| `userAssignedIdentities` | Required when managed identity type is set to UserAssigned | | -| `kubernetesVersion` | Default is `1.29` | `'1.29'` | -| `defenderEnabled` | Enables Defender on AKS cluster | `true` or `false` | -| `imageCleanerEnabled` | Enables ImageCleaner on AKS cluster. | `true` or `false` | -| `imageCleanerIntervalHours` | ImageCleaner scanning interval in hours | Number | -| `systemNodeCount` | Number of nodes to deploy in the system node pool | Number | -| `systemNodeVmSize` | Default system node pool size is `Standard_D2s_v5` | A valid SKU available in your chosen Azure region | -| `registryName` | Optional parameter to attach AKS cluster to an existing ACR | Name of your registry (you can omit the `azurecr.io` suffix) | -| `networkPlugin` | Network plugin used for building the Kubernetes network. | `'kubenet'`
`'azure'`
`'none'` | -| `networkPolicy` | Network policy used for building the Kubernetes network. | `'calico'`
`'azure'` | -| `loadBalancerSku` | The default is standard | `'Standard'`
`'Basic'` | -| `dnsServiceIP` | An IP address assigned to the Kubernetes DNS service. It must be within the Kubernetes service address range specified in serviceCidr. | `'10.0.0.10'` | -| `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. | `'172.17.0.1/16'` | -| `outboundType` | This can only be set at cluster creation time and cannot be changed later. | `'loadBalancer'`
`'managedNATGateway'`
`'userAssignedNATGateway'`
`'userDefinedRouting'` | -| `podCidrs` | One IPv4 CIDR is expected for single-stack networking. Two CIDRs, one for each IP family (IPv4/IPv6), is expected for dual-stack networking. | `'10.244.0.0/16'` | -| `serviceCidrs` | One IPv4 CIDR is expected for single-stack networking. Two CIDRs, one for each IP family (IPv4/IPv6), is expected for dual-stack networking. They must not overlap with any Subnet IP ranges. | `'10.0.0.0/16'` | -| `ipFamilies` | | `'IPv4'`
`'IPv6'` | -| `vnetSubnetID` | Id of the Vnet to deploy cluster into | | -| `nodeTaints` | Enable nodeTaints on the system node pool (e.g., [\'CriticalAddonsOnly=true:NoSchedule\']) | | -| `addonProfiles` | Add-ons to enable | No concrete definition so your best bet is to deploy using Azure CLI or Portal and see what the JSON metadata looks like | - -## Outputs - -| Name | Description | -|------|-------------| -| `name` | This is the name of the AKS resource | diff --git a/bicep/modules/azure-kubernetes-service/main.bicep b/bicep/modules/azure-kubernetes-service/main.bicep deleted file mode 100644 index 5f5a1c3..0000000 --- a/bicep/modules/azure-kubernetes-service/main.bicep +++ /dev/null @@ -1,211 +0,0 @@ -param name string -param location string -param tags object - -@allowed([ - 'Free' - 'Paid' -]) -@description('Defaults to Free tier') -param slaTier string = 'Free' - -@allowed([ - 'SystemAssigned' - 'UserAssigned' -]) -@description('Two options are available: SystemAssigned or UserAssigned') -param managedIdentityType string = 'SystemAssigned' - -@description('Required when managed identity type is set to UserAssigned') -param userAssignedIdentities object = {} - -@description('Default is 1.29') -param kubernetesVersion string = '1.29' - -param defenderEnabled bool = false - -param imageCleanerEnabled bool = false -param imageCleanerIntervalHours int = 12 - -param systemNodeCount int = 3 - -@description('Default system node pool size is Standard_D2s_v5') -param systemNodeVmSize string = 'Standard_D2s_v5' - -@description('Optional parameter to attach AKS cluster to an existing ACR') -param registryName string = '' - -@allowed([ - 'kubenet' - 'azure' - 'none' -]) -@description('Network plugin used for building the Kubernetes network.') -param networkPlugin string = 'kubenet' - -@allowed([ - 'calico' - 'azure' -]) -@description('Network policy used for building the Kubernetes network.') -param networkPolicy string = 'calico' - -@allowed([ - 'Standard' - 'Basic' -]) -@description('The default is standard.') -param loadBalancerSku string = 'Standard' - -@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 = '10.0.0.10' - -@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 = '172.17.0.1/16' - -@description('Resource ID of log analytics workspace for auditing') -param logAnalyticsWorkspaceResourceId string = '' - -@allowed([ - 'loadBalancer' - 'managedNATGateway' - 'userAssignedNATGateway' - 'userDefinedRouting' -]) -@description('This can only be set at cluster creation time and cannot be changed later.') -param outboundType string = 'loadBalancer' - -@description('One IPv4 CIDR is expected for single-stack networking. Two CIDRs, one for each IP family (IPv4/IPv6), is expected for dual-stack networking.') -param podCidrs array = [ - '10.244.0.0/16' -] - -@description('One IPv4 CIDR is expected for single-stack networking. Two CIDRs, one for each IP family (IPv4/IPv6), is expected for dual-stack networking. They must not overlap with any Subnet IP ranges.') -param serviceCidrs array = [ - '10.0.0.0/16' -] - -@allowed([ - 'IPv4' - 'IPv6' -]) -param ipFamilies array = [ - 'IPv4' -] - -@description('If the cluster is using azure network plugin, then you can pass in the subnet resource ID like this `vnet.outputs.subnetId`; otherwise, leave it empty') -param vnetSubnetID string = '' - -@description('Enable nodeTaints on the system node pool (e.g., [\'CriticalAddonsOnly=true:NoSchedule\'])') -param nodeTaints array = [] - -@description('AKS addons to enable') -param addonProfiles object = {} - -param enablePrometheusMetrics bool = false -param prometheusMetricLabelsAllowlist string = '' -param prometheusMetricAnnotationsAllowList string = '' - -resource managedCluster 'Microsoft.ContainerService/managedClusters@2022-08-03-preview' = { - name: name - location: location - tags: tags - sku: { - name: 'Basic' - tier: slaTier - } - identity: { - type: managedIdentityType - userAssignedIdentities: managedIdentityType == 'UserAssigned' ? userAssignedIdentities : null - } - properties: { - kubernetesVersion: kubernetesVersion - dnsPrefix: name - azureMonitorProfile: enablePrometheusMetrics ? { - metrics: { - enabled: true // Requires Microsoft.ContainerService/AKS-PrometheusAddonPreview - kubeStateMetrics: { - metricLabelsAllowlist: prometheusMetricLabelsAllowlist - metricAnnotationsAllowList: prometheusMetricAnnotationsAllowList - } - } - } : null - networkProfile: { - networkPlugin: networkPlugin - networkPolicy: networkPolicy - loadBalancerSku: loadBalancerSku - dnsServiceIP: dnsServiceIP - dockerBridgeCidr: dockerBridgeCidr - outboundType: outboundType - podCidrs: podCidrs - serviceCidrs: serviceCidrs - ipFamilies: ipFamilies - } - agentPoolProfiles: [ - { - name: 'system' - count: systemNodeCount - vmSize: systemNodeVmSize - mode: 'System' - vnetSubnetID: empty(vnetSubnetID) ? null : vnetSubnetID - nodeTaints: empty(nodeTaints) ? null : nodeTaints - } - ] - securityProfile: { - defender: { - securityMonitoring: { - enabled: defenderEnabled - } - } - imageCleaner: { - enabled: imageCleanerEnabled - intervalHours: imageCleanerIntervalHours - } - } - addonProfiles: addonProfiles - } -} - -// Get the registry by name -resource registry 'Microsoft.ContainerRegistry/registries@2022-02-01-preview' existing = if (registryName != '') { - name: registryName -} - -// Get the role definition resource by name, to find the name for the role AcrPull, you can look -// it up at the following url: https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles#acrpull -resource acrPullRoleDefinition 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = if (registryName != '') { - scope: subscription() - name: '7f951dda-4ed3-4680-a7ca-43fe172d538d' -} - -// Give the kubelet user assigned managed identity the AcrPull permissions to pull containers from ACR -resource acrPullRoleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = if (registryName != '') { - name: guid(managedCluster.id, registryName) - scope: registry - properties: { - principalId: managedCluster.properties.identityProfile.kubeletidentity.objectId - roleDefinitionId: acrPullRoleDefinition.id - } -} - -// Get the role definition resource by name, to find the name for the role Contributor, you can look -// it up at the following url: https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles#contributor -resource contributorRoleDefinition 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { - scope: subscription() - name: 'b24988ac-6180-42a0-ab88-20f7382dd24c' -} - -// Give the managedCluster identity the Contributor permissions -resource contribtorRoleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(managedCluster.id, resourceGroup().id) - scope: resourceGroup() - properties: { - principalId: managedCluster.identity.principalId - roleDefinitionId: contributorRoleDefinition.id - } -} - -output name string = managedCluster.name -output id string = managedCluster.id -output kubeletIdentityObjectId string = managedCluster.properties.identityProfile.kubeletidentity.objectId -output nodeResourceGroupName string = managedCluster.properties.nodeResourceGroup diff --git a/bicep/modules/azure-kubernetes-service/metadata.json b/bicep/modules/azure-kubernetes-service/metadata.json deleted file mode 100644 index 28e74a8..0000000 --- a/bicep/modules/azure-kubernetes-service/metadata.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "version": { - "major": 0, - "minor": 2 - } -} \ No newline at end of file diff --git a/bicep/modules/azure-log-analytics-workspace/README.md b/bicep/modules/azure-log-analytics-workspace/README.md deleted file mode 100644 index 8630572..0000000 --- a/bicep/modules/azure-log-analytics-workspace/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# azure-log-analytics-workspace - -This module deploys a [Microsoft.OperationalInsights/workspaces](https://learn.microsoft.com/azure/templates/microsoft.operationalinsights/workspaces?pivots=deployment-language-bicep) resource. - -## Inputs - -| Name | Description | Expected Value | -|------|-------------|----------------| -| `name` | This is the name of the resource | Whatever you want | -| `location` | Region to deploy resource into | Azure region that offers this resource | -| `tags` | Tags | Object of key/value pairs | - -## Outputs - -| Name | Description | -|------|-------------| -| `id` | This is the id of the virtual network resource | diff --git a/bicep/modules/azure-log-analytics-workspace/main.bicep b/bicep/modules/azure-log-analytics-workspace/main.bicep deleted file mode 100644 index c7297b0..0000000 --- a/bicep/modules/azure-log-analytics-workspace/main.bicep +++ /dev/null @@ -1,17 +0,0 @@ -param name string -param location string -param tags object - -resource workspace 'Microsoft.OperationalInsights/workspaces@2021-12-01-preview' = { - name: name - location: location - tags: tags - properties: { - retentionInDays: 30 - sku: { - name: 'PerGB2018' - } - } -} - -output id string = workspace.id diff --git a/bicep/modules/azure-log-analytics-workspace/metadata.json b/bicep/modules/azure-log-analytics-workspace/metadata.json deleted file mode 100644 index 7dd04c0..0000000 --- a/bicep/modules/azure-log-analytics-workspace/metadata.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "version": { - "major": 0, - "minor": 1 - } -} \ No newline at end of file diff --git a/bicep/modules/azure-managed-prometheus-grafana-for-aks/README.md b/bicep/modules/azure-managed-prometheus-grafana-for-aks/README.md deleted file mode 100644 index 94fd15e..0000000 --- a/bicep/modules/azure-managed-prometheus-grafana-for-aks/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# azure-managed-prometheus-grafana-for-aks - -This module deploys a [Microsoft.Dashboard/grafana](https://learn.microsoft.com/en-us/azure/templates/microsoft.dashboard/grafana?pivots=deployment-language-bicep) resource using only parameters scoped for these labs. - -## Inputs - -| Name | Description | Expected Value | -|------|-------------|----------------| -| `name` | This is the name of the resource | Whatever you want | -| `location` | Region to deploy resource into | Azure region that offers this resource | -| `tags` | Tags | Object of key/value pairs | - -## Outputs - -| Name | Description | -|------|-------------| - diff --git a/bicep/modules/azure-managed-prometheus-grafana-for-aks/main.bicep b/bicep/modules/azure-managed-prometheus-grafana-for-aks/main.bicep deleted file mode 100644 index 515521a..0000000 --- a/bicep/modules/azure-managed-prometheus-grafana-for-aks/main.bicep +++ /dev/null @@ -1,370 +0,0 @@ -param name string - -@allowed([ - 'eastus2euap' - 'centraluseuap' - 'centralus' - 'eastus' - 'eastus2' - 'northeurope' - 'southcentralus' - 'southeastasia' - 'uksouth' - 'westeurope' - 'westus' - 'westus2' -]) -param location string - -param tags object - -@allowed([ - 'SystemAssigned' - 'UserAssigned' -]) -@description('Two options are available: SystemAssigned or UserAssigned') -param managedIdentityType string = 'SystemAssigned' - -@description('Required when managed identity type is set to UserAssigned') -param userAssignedIdentities object = {} - -param publicNetworkAccess bool = true - -param zoneRedundancy bool = false - -param clusterName string - -param metricLabelsAllowlist string = '' -param metricAnnotationsAllowList string = '' - -param userObjectId string - -resource monitor 'microsoft.monitor/accounts@2021-06-03-preview' = { - name: name - location: location -} - -resource dataCollectionEndpoint 'Microsoft.Insights/dataCollectionEndpoints@2021-09-01-preview' = { - name: 'MSPROM-${clusterName}-${location}' - location: location - kind: 'Linux' - properties: { - } -} - -resource dataCollectionRule 'Microsoft.Insights/dataCollectionRules@2021-09-01-preview' = { - name: 'MSPROM-${clusterName}-${location}' - location: location - kind: 'Linux' - properties: { - dataCollectionEndpointId: dataCollectionEndpoint.id - dataFlows: [ - { - destinations: [ - 'MonitoringAccount1' - ] - streams: [ - 'Microsoft-PrometheusMetrics' - ] - } - ] - dataSources: { - prometheusForwarder: [ - { - name: 'PrometheusDataSource' - streams: [ - 'Microsoft-PrometheusMetrics' - ] - labelIncludeFilter: { - } - } - ] - } - description: 'Data collection rule for Azure Monitor Metrics Profile (Managed Prometheus)' - destinations: { - monitoringAccounts: [ - { - accountResourceId: monitor.id - name: 'MonitoringAccount1' - } - ] - } - } -} - -resource dataCollectionRuleAssociation 'Microsoft.ContainerService/managedClusters/providers/dataCollectionRuleAssociations@2021-09-01-preview' = { - name: '${clusterName}/microsoft.insights/MSPROM-${clusterName}--${location}' - location: location - properties: { - description: 'Association of data collection rule. Deleting this association will break the data collection for this AKS Cluster.' - dataCollectionRuleId: dataCollectionRule.id - } - - dependsOn: [ - dataCollectionEndpoint - ] -} - -resource cluster 'Microsoft.ContainerService/managedClusters@2022-07-02-preview' existing = { - name: clusterName -} - -resource azureMonitorProfile 'Microsoft.ContainerService/managedClusters@2022-07-02-preview' = { - name: clusterName - location: location - properties: { - mode: 'Incremental' - id: cluster.id - azureMonitorProfile: { - metrics: { - enabled: true - kubeStateMetrics: { - metricLabelsAllowlist: metricLabelsAllowlist - metricAnnotationsAllowList: metricAnnotationsAllowList - } - } - } - } - - dependsOn: [ - cluster - dataCollectionRuleAssociation - ] -} - -resource nodeRecordingRuleGroup 'Microsoft.AlertsManagement/prometheusRuleGroups@2021-07-22-preview' = { - name: 'NodeRecordingRulesRuleGroup-${clusterName}' - location: location - properties: { - description: 'Node Recording Rules RuleGroup - 0.1' - scopes: [ - monitor.id - ] - clusterName: clusterName - interval: 'PT1M' - rules: [ - { - record: 'instance:node_num_cpu:sum' - expression: 'count without (cpu, mode) ( node_cpu_seconds_total{job="node",mode="idle"})' - } - { - record: 'instance:node_cpu_utilisation:rate5m' - expression: '1 - avg without (cpu) ( sum without (mode) (rate(node_cpu_seconds_total{job="node", mode=~"idle|iowait|steal"}[5m])))' - } - { - record: 'instance:node_load1_per_cpu:ratio' - expression: '( node_load1{job="node"}/ instance:node_num_cpu:sum{job="node"})' - } - { - record: 'instance:node_memory_utilisation:ratio' - expression: '1 - ( ( node_memory_MemAvailable_bytes{job="node"} or ( node_memory_Buffers_bytes{job="node"} + node_memory_Cached_bytes{job="node"} + node_memory_MemFree_bytes{job="node"} + node_memory_Slab_bytes{job="node"} ) )/ node_memory_MemTotal_bytes{job="node"})' - } - { - record: 'instance:node_vmstat_pgmajfault:rate5m' - expression: 'rate(node_vmstat_pgmajfault{job="node"}[5m])' - } - { - record: 'instance_device:node_disk_io_time_seconds:rate5m' - expression: 'rate(node_disk_io_time_seconds_total{job="node", device!=""}[5m])' - } - { - record: 'instance_device:node_disk_io_time_weighted_seconds:rate5m' - expression: 'rate(node_disk_io_time_weighted_seconds_total{job="node", device!=""}[5m])' - } - { - record: 'instance:node_network_receive_bytes_excluding_lo:rate5m' - expression: 'sum without (device) ( rate(node_network_receive_bytes_total{job="node", device!="lo"}[5m]))' - } - { - record: 'instance:node_network_transmit_bytes_excluding_lo:rate5m' - expression: 'sum without (device) ( rate(node_network_transmit_bytes_total{job="node", device!="lo"}[5m]))' - } - { - record: 'instance:node_network_receive_drop_excluding_lo:rate5m' - expression: 'sum without (device) ( rate(node_network_receive_drop_total{job="node", device!="lo"}[5m]))' - } - { - record: 'instance:node_network_transmit_drop_excluding_lo:rate5m' - expression: 'sum without (device) ( rate(node_network_transmit_drop_total{job="node", device!="lo"}[5m]))' - } - ] - } -} - -resource kubernetesRecordingRuleGroup 'Microsoft.AlertsManagement/prometheusRuleGroups@2021-07-22-preview' = { - name: 'KubernetesReccordingRulesRuleGroup-${clusterName}' - location: location - properties: { - description: 'Kubernetes Recording Rules RuleGroup - 0.1' - scopes: [ - monitor.id - ] - clusterName: clusterName - interval: 'PT1M' - rules: [ - { - record: 'node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate' - expression: 'sum by (cluster, namespace, pod, container) ( irate(container_cpu_usage_seconds_total{job="cadvisor", image!=""}[5m])) * on (cluster, namespace, pod) group_left(node) topk by (cluster, namespace, pod) ( 1, max by(cluster, namespace, pod, node) (kube_pod_info{node!=""}))' - } - { - record: 'node_namespace_pod_container:container_memory_working_set_bytes' - expression: 'container_memory_working_set_bytes{job="cadvisor", image!=""}* on (namespace, pod) group_left(node) topk by(namespace, pod) (1, max by(namespace, pod, node) (kube_pod_info{node!=""}))' - } - { - record: 'node_namespace_pod_container:container_memory_rss' - expression: 'container_memory_rss{job="cadvisor", image!=""}* on (namespace, pod) group_left(node) topk by(namespace, pod) (1, max by(namespace, pod, node) (kube_pod_info{node!=""}))' - } - { - record: 'node_namespace_pod_container:container_memory_cache' - expression: 'container_memory_cache{job="cadvisor", image!=""}* on (namespace, pod) group_left(node) topk by(namespace, pod) (1, max by(namespace, pod, node) (kube_pod_info{node!=""}))' - } - { - record: 'node_namespace_pod_container:container_memory_swap' - expression: 'container_memory_swap{job="cadvisor", image!=""}* on (namespace, pod) group_left(node) topk by(namespace, pod) (1, max by(namespace, pod, node) (kube_pod_info{node!=""}))' - } - { - record: 'cluster:namespace:pod_memory:active:kube_pod_container_resource_requests' - expression: 'kube_pod_container_resource_requests{resource="memory",job="kube-state-metrics"} * on (namespace, pod, cluster)group_left() max by (namespace, pod, cluster) ( (kube_pod_status_phase{phase=~"Pending|Running"} == 1))' - } - { - record: 'namespace_memory:kube_pod_container_resource_requests:sum' - expression: 'sum by (namespace, cluster) ( sum by (namespace, pod, cluster) ( max by (namespace, pod, container, cluster) ( kube_pod_container_resource_requests{resource="memory",job="kube-state-metrics"} ) * on(namespace, pod, cluster) group_left() max by (namespace, pod, cluster) ( kube_pod_status_phase{phase=~"Pending|Running"} == 1 ) ))' - } - { - record: 'cluster:namespace:pod_cpu:active:kube_pod_container_resource_requests' - expression: 'kube_pod_container_resource_requests{resource="cpu",job="kube-state-metrics"} * on (namespace, pod, cluster)group_left() max by (namespace, pod, cluster) ( (kube_pod_status_phase{phase=~"Pending|Running"} == 1))' - } - { - record: 'namespace_cpu:kube_pod_container_resource_requests:sum' - expression: 'sum by (namespace, cluster) ( sum by (namespace, pod, cluster) ( max by (namespace, pod, container, cluster) ( kube_pod_container_resource_requests{resource="cpu",job="kube-state-metrics"} ) * on(namespace, pod, cluster) group_left() max by (namespace, pod, cluster) ( kube_pod_status_phase{phase=~"Pending|Running"} == 1 ) ))' - } - { - record: 'cluster:namespace:pod_memory:active:kube_pod_container_resource_limits' - expression: 'kube_pod_container_resource_limits{resource="memory",job="kube-state-metrics"} * on (namespace, pod, cluster)group_left() max by (namespace, pod, cluster) ( (kube_pod_status_phase{phase=~"Pending|Running"} == 1))' - } - { - record: 'namespace_memory:kube_pod_container_resource_limits:sum' - expression: 'sum by (namespace, cluster) ( sum by (namespace, pod, cluster) ( max by (namespace, pod, container, cluster) ( kube_pod_container_resource_limits{resource="memory",job="kube-state-metrics"} ) * on(namespace, pod, cluster) group_left() max by (namespace, pod, cluster) ( kube_pod_status_phase{phase=~"Pending|Running"} == 1 ) ))' - } - { - record: 'cluster:namespace:pod_cpu:active:kube_pod_container_resource_limits' - expression: 'kube_pod_container_resource_limits{resource="cpu",job="kube-state-metrics"} * on (namespace, pod, cluster)group_left() max by (namespace, pod, cluster) ( (kube_pod_status_phase{phase=~"Pending|Running"} == 1) )' - } - { - record: 'namespace_cpu:kube_pod_container_resource_limits:sum' - expression: 'sum by (namespace, cluster) ( sum by (namespace, pod, cluster) ( max by (namespace, pod, container, cluster) ( kube_pod_container_resource_limits{resource="cpu",job="kube-state-metrics"} ) * on(namespace, pod, cluster) group_left() max by (namespace, pod, cluster) ( kube_pod_status_phase{phase=~"Pending|Running"} == 1 ) ))' - } - { - record: 'namespace_workload_pod:kube_pod_owner:relabel' - expression: 'max by (cluster, namespace, workload, pod) ( label_replace( label_replace( kube_pod_owner{job="kube-state-metrics", owner_kind="ReplicaSet"}, "replicaset", "$1", "owner_name", "(.*)" ) * on(replicaset, namespace) group_left(owner_name) topk by(replicaset, namespace) ( 1, max by (replicaset, namespace, owner_name) ( kube_replicaset_owner{job="kube-state-metrics"} ) ), "workload", "$1", "owner_name", "(.*)" ))' - labels: { - workload_type: 'deployment' - } - } - { - record: 'namespace_workload_pod:kube_pod_owner:relabel' - expression: 'max by (cluster, namespace, workload, pod) ( label_replace( kube_pod_owner{job="kube-state-metrics", owner_kind="DaemonSet"}, "workload", "$1", "owner_name", "(.*)" ))' - labels: { - workload_type: 'daemonset' - } - } - { - record: 'namespace_workload_pod:kube_pod_owner:relabel' - expression: 'max by (cluster, namespace, workload, pod) ( label_replace( kube_pod_owner{job="kube-state-metrics", owner_kind="StatefulSet"}, "workload", "$1", "owner_name", "(.*)" ))' - labels: { - workload_type: 'statefulset' - } - } - { - record: 'namespace_workload_pod:kube_pod_owner:relabel' - expression: 'max by (cluster, namespace, workload, pod) ( label_replace( kube_pod_owner{job="kube-state-metrics", owner_kind="Job"}, "workload", "$1", "owner_name", "(.*)" ))' - labels: { - workload_type: 'job' - } - } - { - record: ':node_memory_MemAvailable_bytes:sum' - expression: 'sum( node_memory_MemAvailable_bytes{job="node"} or ( node_memory_Buffers_bytes{job="node"} + node_memory_Cached_bytes{job="node"} + node_memory_MemFree_bytes{job="node"} + node_memory_Slab_bytes{job="node"} )) by (cluster)' - } - { - record: 'cluster:node_cpu:ratio_rate5m' - expression: 'sum(rate(node_cpu_seconds_total{job="node",mode!="idle",mode!="iowait",mode!="steal"}[5m])) by (cluster) /count(sum(node_cpu_seconds_total{job="node"}) by (cluster, instance, cpu)) by (cluster)' - } - ] - } -} - -resource grafana 'Microsoft.Dashboard/grafana@2022-08-01' = { - name: name - location: location - tags: tags - sku: { - name: 'Standard' - } - identity: { - type: managedIdentityType - userAssignedIdentities: managedIdentityType == 'UserAssigned' ? userAssignedIdentities : null - } - properties: { - apiKey: 'Enabled' - autoGeneratedDomainNameLabelScope: 'TenantReuse' - deterministicOutboundIP: 'Enabled' - grafanaIntegrations: { - azureMonitorWorkspaceIntegrations: [ - { - azureMonitorWorkspaceResourceId: monitor.id - } - ] - } - publicNetworkAccess: publicNetworkAccess ? 'Enabled' : 'Disabled' - zoneRedundancy: zoneRedundancy ? 'Enabled' : 'Disabled' - } -} - -@description('This is the built-in Monitoring Reader role.') -resource monitoringReaderRoleDefinition 'Microsoft.Authorization/roleDefinitions@2018-01-01-preview' existing = { - scope: subscription() - name: '43d0d8ad-25c7-4714-9337-8ba259a9fe05' //Monitoring Reader -} - -resource monitoringReaderRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(resourceGroup().id, grafana.id) - scope: resourceGroup() - properties: { - roleDefinitionId: monitoringReaderRoleDefinition.id - principalId: grafana.identity.principalId - principalType: 'ServicePrincipal' - } -} - -@description('This is the built-in Monitoring Data Reader role.') -resource monitoringDataReaderRoleDefinition 'Microsoft.Authorization/roleDefinitions@2018-01-01-preview' existing = { - scope: subscription() - name: 'b0d8363b-8ddd-447d-831f-62ca05bff136' //Monitoring Data Reader -} - -resource monitorDataReaderRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(monitor.id, grafana.id) - scope: monitor - properties: { - roleDefinitionId: monitoringDataReaderRoleDefinition.id - principalId: grafana.identity.principalId - principalType: 'ServicePrincipal' - } -} - -@description('This is the built-in Grafana Admin role.') -resource grafanaAdminRoleDefinition 'Microsoft.Authorization/roleDefinitions@2018-01-01-preview' existing = { - scope: subscription() - name: '22926164-76b3-42b3-bc55-97df8dab3e41' //Grafana Admin -} - -resource grafanaAdminRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(grafana.id, userObjectId) - scope: grafana - properties: { - roleDefinitionId: grafanaAdminRoleDefinition.id - principalId: userObjectId - principalType: 'User' - } -} diff --git a/bicep/modules/azure-managed-prometheus-grafana-for-aks/metadata.json b/bicep/modules/azure-managed-prometheus-grafana-for-aks/metadata.json deleted file mode 100644 index 7dd04c0..0000000 --- a/bicep/modules/azure-managed-prometheus-grafana-for-aks/metadata.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "version": { - "major": 0, - "minor": 1 - } -} \ No newline at end of file diff --git a/bicep/modules/azure-network-security-group/README.md b/bicep/modules/azure-network-security-group/README.md deleted file mode 100644 index ce336da..0000000 --- a/bicep/modules/azure-network-security-group/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# azure-network-security-group - -This module deploys a [Microsoft.Network/networkSecurityGroups](https://learn.microsoft.com/azure/templates/microsoft.network/networksecuritygroups?pivots=deployment-language-bicep) resource using only parameters scoped for these labs. - -## Inputs - -| Name | Description | Expected Value | -|------|-------------|----------------| -| `name` | This is the name of the resource | Whatever you want | -| `location` | Region to deploy resource into | Azure region that offers this resource | -| `tags` | Tags | Object of key/value pairs | - -## Outputs - -| Name | Description | -|------|-------------| -| `id` | This is the id of the resource | diff --git a/bicep/modules/azure-network-security-group/main.bicep b/bicep/modules/azure-network-security-group/main.bicep deleted file mode 100644 index 8f43dca..0000000 --- a/bicep/modules/azure-network-security-group/main.bicep +++ /dev/null @@ -1,14 +0,0 @@ -param name string -param tags object -param location string - -resource networkSecurityGroup 'Microsoft.Network/networkSecurityGroups@2022-01-01' = { - name: name - location: location - properties: { - securityRules: [] - } - tags: tags -} - -output id string = networkSecurityGroup.id diff --git a/bicep/modules/azure-network-security-group/metadata.json b/bicep/modules/azure-network-security-group/metadata.json deleted file mode 100644 index 7dd04c0..0000000 --- a/bicep/modules/azure-network-security-group/metadata.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "version": { - "major": 0, - "minor": 1 - } -} \ No newline at end of file diff --git a/bicep/modules/azure-virtual-network/README.md b/bicep/modules/azure-virtual-network/README.md deleted file mode 100644 index 3434f99..0000000 --- a/bicep/modules/azure-virtual-network/README.md +++ /dev/null @@ -1,24 +0,0 @@ -# azure-virtual-network - -This module deploys a [Microsoft.Network/virtualNetworks](https://learn.microsoft.com/azure/templates/microsoft.network/virtualnetworks?pivots=deployment-language-bicep) resource with a single [Microsoft.Network/virtualNetworks/subnets](https://learn.microsoft.com/azure/templates/microsoft.network/virtualnetworks/subnets?pivots=deployment-language-bicep) resource using only parameters scoped for these labs. - -## Inputs - -| Name | Description | Expected Value | -|------|-------------|----------------| -| `name` | This is the name of the resource | Whatever you want | -| `location` | Region to deploy resource into | Azure region that offers this resource | -| `tags` | Tags | Object of key/value pairs | -| `vnetAddressPrefix` | Network CIDR range | Ex: 10.21.0.0/16 | -| `snetAddressPrefix` | Subnet CIDR range | Ex: 10.21.0.0/24 | -| `snetName` | Name of the subnet | Whatever you want | -| `networkSecurityGroupId` | Resource ID of the network security group. This will be associated to the subnet | Resource ID | -| `dnsServer` | Optionally, set a DNS server IP or leave empty to use Azure DNS | IP address or empty string | - -## Outputs - -| Name | Description | -|------|-------------| -| `id` | This is the id of the virtual network resource | -| `name` | This is the name of the virtual network resource | -| `subnetId` | This is the id of the subnet resource | diff --git a/bicep/modules/azure-virtual-network/main.bicep b/bicep/modules/azure-virtual-network/main.bicep deleted file mode 100644 index 0685e23..0000000 --- a/bicep/modules/azure-virtual-network/main.bicep +++ /dev/null @@ -1,41 +0,0 @@ -param name string -param location string -param tags object -param vnetAddressPrefix string -param snetAddressPrefix string -param snetName string -param networkSecurityGroupId string -param dnsServer string - -resource virtualNetwork 'Microsoft.Network/virtualNetworks@2022-01-01' = { - name: name - location: location - tags: tags - properties: { - addressSpace: { - addressPrefixes: [ - vnetAddressPrefix - ] - } - dhcpOptions: (!empty(dnsServer) ? { - dnsServers: [ - dnsServer - ] - } : null) - subnets: [ - { - name: snetName - properties: { - addressPrefix: snetAddressPrefix - networkSecurityGroup: { - id: networkSecurityGroupId - } - } - } - ] - } -} - -output id string = virtualNetwork.id -output name string = virtualNetwork.name -output subnetId string = virtualNetwork.properties.subnets[0].id diff --git a/bicep/modules/azure-virtual-network/metadata.json b/bicep/modules/azure-virtual-network/metadata.json deleted file mode 100644 index 7dd04c0..0000000 --- a/bicep/modules/azure-virtual-network/metadata.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "version": { - "major": 0, - "minor": 1 - } -} \ No newline at end of file diff --git a/cloud-native/README.md b/cloud-native/README.md index 9678adb..8f793fb 100644 --- a/cloud-native/README.md +++ b/cloud-native/README.md @@ -13,12 +13,11 @@ ## Azure Kubernetes Service -- [Lab: Explore KEDA (Kubernetes Event-driven Autoscaling) and the KEDA HTTP Add-on with Azure Kubernetes Service (AKS) and Bicep](aks-bicep-keda/) +- Lab: Explore KEDA (Kubernetes Event-driven Autoscaling) and the KEDA HTTP Add-on with Azure Kubernetes Service (AKS) and Bicep (returning soon) - [Lab: Deploy a Scalable and Secure Azure Kubernetes Service cluster using the Azure CLI](aks-https/) -- [Lab: Azure Kubernetes Service with ARM64 node pools](aks-arm64/) +- Lab: Azure Kubernetes Service with ARM64 node pools (returning soon) - [Lab: Azure Kubernetes Service with ARM64 node pools and Terraform](aks-arm64-terraform/) -- [Lab: Web Application Routing with Azure Kubernetes Service](aks-webapp-routing/) -- [Lab: Azure Kubernetes Service with Open Service Mesh](./aks-open-service-mesh/) +- Lab: Web Application Routing with Azure Kubernetes Service (returning soon) - [Lab: Azure Kubernetes Service with Open Service Mesh and Terraform](./aks-open-service-mesh-terraform/) - [Run scalable and resilient Redis with Kubernetes and Azure Kubernetes Service (techcommunity.microsoft.com)](https://techcommunity.microsoft.com/t5/apps-on-azure-blog/run-scalable-and-resilient-redis-with-kubernetes-and-azure/ba-p/3247956) - [Walkthrough (aaronmsft.com)](https://aaronmsft.com/posts/oss-aks-redis/) diff --git a/cloud-native/aks-arm64/README.md b/cloud-native/aks-arm64/README.md deleted file mode 100644 index 2b76cbc..0000000 --- a/cloud-native/aks-arm64/README.md +++ /dev/null @@ -1,368 +0,0 @@ -# Azure Kubernetes Service with ARM64 node pools - -This lab will walk you though deploying Azure Kubernetes Service (AKS) with ARM64-based user node pools and deploy a sample application to it. - -You will perform the following tasks: - -* Provision Azure resources -* Build and publish ARM64-based container to Azure Container Registry -* Deploy ARM64-based image to Azure Kubernetes Service - -As part of the application deployment process, we'll also explore some things you can do to ensure your container images are prepared for ARM64-based OS architecture. - -## Requirements - -* An Azure Subscription (e.g. [Free](https://aka.ms/azure-free-account) or [Student](https://aka.ms/azure-student-account) account) -* The [Azure CLI](https://docs.microsoft.com/cli/azure/install-azure-cli) -* A [GitHub](https://github.com/) account -* The [GitHub CLI](https://cli.github.com/) -* Bash shell (e.g. macOS, Linux, [Windows Subsystem for Linux (WSL)](https://docs.microsoft.com/windows/wsl/about), [Multipass](https://multipass.run/), [Azure Cloud Shell](https://docs.microsoft.com/azure/cloud-shell/quickstart), [GitHub Codespaces](https://github.com/features/codespaces), etc) -* The [Docker CLI](https://www.docker.com/products/docker-desktop/) - -> **⚠️ NOTE** -> -> This deployment uses Azure Bicep templates to provision Azure infrastructure. If you'd like to use Terraform instead, head over to [Azure Kubernetes Service with ARM64 node pools and Terraform](../aks-arm64-terraform#deploy-azure-resources-using-terraform) then come back to complete the remainder of the steps in this lab guide. - -[![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure-Samples%2Fazure-opensource-labs%2Fmain%2Fcloud-native%2Faks-arm64%2Fmain.json) - -> Use the button above if you'd like to deploy using the Azure Portal instead of Azure CLI commands. - -## Deploy Azure Resources using Azure Bicep - -Start by cloning this repo and navigating to the `cloud-native/aks-arm64` directory. - -```bash -git clone https://github.com/Azure-Samples/azure-opensource-labs.git -cd azure-opensource-labs/cloud-native/aks-arm64 -``` - -Next, make sure you are logged into Azure CLI - -```bash -az login -``` - -If you have access to multiple subscriptions, you can select the proper subscription to use with the following command: - -```bash -az account set -s -``` - -> **⚠️ NOTE** -> -> You will need proper permissions in your subscription as the AKS deployment will require granting the `AcrPull` permissions to the `kubelets` on the AKS cluster, so that images can be pulled from your Azure Container Registry. - -Prepare for deployment by setting a few environment variables. You will need to pass in a `location` (aka Azure region) that [supports your deployment resources](https://azure.microsoft.com/explore/global-infrastructure/products-by-region/?products=container-registry,kubernetes-service) and SKUs as well as a `name` for your resource deployments. - -> **💡 TIP** -> -> To validate that a VM SKU is available in your preferred Azure region you can run a command like this: -> -> az vm list-sizes --location $location --query "[? contains(name, 'Standard_Dpds_v5')]" -o table` - -The `name` variable will be used to name Azure resources. The naming convention used wil be adopted from this [guide](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/resource-naming#example-names-general). Some resources have specific requirements around resource naming so it is generally safe to use shorter alphanumeric names and ensure they will be globally unique since ACR names must meet this criteria. - -Set up your `location` and `name` variables. - -```bash -location=eastus -name=arm$RANDOM -``` - -Run the Bicep template deployment using the following command: - -```bash -az deployment sub create --name "$name-deploy" --location $location -f ./main.bicep --parameters name=$name location=$location -``` - -The deployment of Azure resources can take up to 10 minutes to complete. If you are interested in learning how the Bicep template modules work, click the `show` link below. - -
show - -The [main.bicep](./main.bicep) file deploys the following resources in your subscription: - -* Azure Resource Group -* Azure Container Registry -* Azure Kubernetes Cluster with system node pool -* ARM64-based user node pool with SKU (`Standard_D4pds_v5`) - -The template leverages Bicep modules which have been published to a separate ACR (`cloudnativeadvocates.azurecr.io`). To avoid having to include the ACR server name in all module calls, the ACR server name has been aliased in the [bicepconfig.json](./bicepconfig.json) file. - -The code for each Bicep module is hosted in this repo in the [bicep/modules](/bicep/modules/) directory. There you will find subdirectories for each of the modules we use for this lab's deployment. - -Within each module's subdirectory, there is a `README.md` file with additional information on the inputs and outputs for each module including links to the [resource template](https://learn.microsoft.com/azure/templates/) documentation. - -Here's a quick summary of the resources being deployed - -### Azure Resource Group - -This deployment is at subscription scope, so we create a resource group in the `main.bicep` file to deploy all resources for this lab. - -### Azure Container Registry - -Uses `br/oss-labs:bicep/modules/azure-container-registry:v0.1` module to deploy a private container registry in which we will publish our sample container image to. - -This ACR resource will have the admin account enabled to be able to publish container images using GitHub Actions. - -### Azure Kubernetes Cluster with system node pool - -Uses `br/oss-labs:bicep/modules/azure-kubernetes-service:v0.1` to deploy a managed cluster with Kubernetes version `1.24.3`. Some of the basic options have been enabled such as using a standard load balancer for inbound services and outbound NAT. The system node pool will use the `Standard_D2s_v5` Virtual Machine Scale Set SKU and deploy `2` instances. - -AKS clusters can be provisioned with Defender enabled; however, at the time of this writing, ARM64-based node pools are not supported when AKS clusters have Defender enabled. - -This AKS cluster will also have the ACR "attached" by granting the `kubelet` managed identity the `AcrPull` role assignment on the ACR resource. - -### ARM64-based user node pool with SKU (`Standard_D4pds_v5`) - -Uses `br/oss-labs:bicep/modules/azure-kubernetes-service-nodepools:v0.1` module to deploy a 2-node ARM64-based node pool with SKU `Standard_D4pds_v5`. This module accepts `userNodes` which is an array of dynamic objects. Each of the dynamic object properties are mapped to Bicep template properties in the module implementation. - -With the node pool type of `VirtualMachineScaleSets`, we can enable autoscaling. You can specify the scale down mode to either `Deallocate` or `Delete`. This lab sets it to `Deallocate` to ensure faster scale up/down times; therefore, the `osDiskType` setting must be set to `Managed` so that Azure persists the OS disks. - -> The default `osDiskType` is `Ephemeral` - -This user node pool will auto scale from `0` to `3` instances based on load - -If you want to ensure only specific workloads are scheduled on your user node pools, you can add `nodeTaints`. Refer to this [doc](https://learn.microsoft.com/azure/aks/use-multiple-node-pools#setting-nodepool-taints) for additional information. -

-
- -Once the deployment has completed, you can run the following command to gain access to the cluster: - -```bash -az aks get-credentials --resource-group "rg-${name}" --name "aks-${name}" -``` - -To verify the cluster is up, run the command `kubectl get nodes -o wide` and should see something like this - -```bash -kubectl get nodes -o wide -NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME -aks-arm64-10552501-vmss000000 NotReady agent 139m v1.24.3 10.21.0.62 Ubuntu 22.04.1 LTS 5.15.0-1019-azure containerd://1.6.4+azure-4 -aks-arm64-10552501-vmss000001 NotReady agent 139m v1.24.3 10.21.0.91 Ubuntu 22.04.1 LTS 5.15.0-1019-azure containerd://1.6.4+azure-4 -aks-arm64-10552501-vmss000002 NotReady agent 139m v1.24.3 10.21.0.120 Ubuntu 22.04.1 LTS 5.15.0-1019-azure containerd://1.6.4+azure-4 -aks-system-23779925-vmss000000 Ready agent 143m v1.24.3 10.21.0.4 Ubuntu 18.04.6 LTS 5.4.0-1090-azure containerd://1.6.4+azure-4 -aks-system-23779925-vmss000001 Ready agent 143m v1.24.3 10.21.0.33 Ubuntu 18.04.6 LTS 5.4.0-1090-azure containerd://1.6.4+azure-4 -``` - -> 💡 TIP -> -> If you do not have `kubectl` installed on your system, you can run the following command to install it: -> -> `az aks install-cli` - -## Deploying `ARM64` workloads to Kubernetes - -With the ARM64-based user node pool deployed, we can begin deploying our first workload onto it. - -We will deploy the famous [Azure Voting App](https://learn.microsoft.com/azure/aks/tutorial-kubernetes-prepare-app) which can be found in many AKS tutorials, labs, blogs, etc. - -![Azure Voting App](https://learn.microsoft.com/en-us/azure/aks/media/container-service-kubernetes-tutorials/azure-vote-local.png) - -This application is a multi-container application and upon inspection of the [`docker-compose.yaml`](https://github.com/Azure-Samples/azure-voting-app-redis/blob/master/docker-compose.yaml) file, we can see it uses the `mcr.microsoft.com/oss/bitnami/redis:6.0.8` image for the backend and the `mcr.microsoft.com/azuredocs/azure-vote-front:v1` for the frontend. - -In order for Kubernetes to schedule containers to your ARM64-based node pool, the container images must be published to support the appropriate OS architectures. - -### Investigation - -You can inspect the container manifests by running the following commands: - -```bash -docker manifest inspect mcr.microsoft.com/azuredocs/azure-vote-front:v1 -docker manifest inspect mcr.microsoft.com/oss/bitnami/redis:6.0.8 -``` - -Unfortunately, neither of these images support `arm64` architecture 😞 - -Let's check if Redis has an updated image on Docker Hub that supports `arm64` - -```bash -docker manifest inspect redis:latest -``` - -From the output, we can see it does 🥳 - -```json -... -{ - "mediaType": "application/vnd.docker.distribution.manifest.v2+json", - "size": 1572, - "digest": "sha256:6444b125d6e2b7aae5732039a22bf4abb92bcb1535cefe89e52bb269f6374826", - "platform": { - "architecture": "arm64", - "os": "linux", - "variant": "v8" - } -} -... -``` - -Easy enough, we can swap out `mcr.microsoft.com/oss/bitnami/redis:6.0.8` with `redis:latest` and fix that dependency 😅 - -Now, browse to the [source repo](https://github.com/Azure-Samples/azure-voting-app-redis) for the Azure Voting App and view the [Dockerfile](https://github.com/Azure-Samples/azure-voting-app-redis/blob/master/azure-vote/Dockerfile) to see how the image is built. - -From the Dockerfile, we can see it is using `tiangolo/uwsgi-nginx-flask:python3.6` as a base image. - -If we run the `docker manifest inspect` command again, we can see the base image also doesn't support `arm64` architecture 😞 - -```bash -docker manifest inspect tiangolo/uwsgi-nginx-flask:python3.6 -``` - -On Docker Hub, we can see the [tiangolo/uwsgi-nginx-flask](https://hub.docker.com/r/tiangolo/uwsgi-nginx-flask) image is built using this [this Dockerfile](https://github.com/tiangolo/uwsgi-nginx-flask-docker/blob/master/docker-images/python3.6.dockerfile) - -Upon inspection of the Dockerfile, you can see this image sources from yet another base image called `tiangolo/uwsgi-nginx:python3.6` - -Back in Docker Hub, we can view information for the [tiangolo/uwsgi-nginx](https://hub.docker.com/r/tiangolo/uwsgi-nginx) image. Here we see [this Dockerfile](https://github.com/tiangolo/uwsgi-nginx-docker/blob/master/docker-images/python3.6.dockerfile) is used to build the base image. - -In the Dockerfile, we see it's base image is `python:3.6-buster` - -This image is also hosted on Docker Hub so we can check to see if this image supports `arm64` - -```bash -docker manifest inspect python:3.6-buster -``` - -In the output, we can see it supports many architectures including `arm64` 🥳 - -```json -... -{ - "mediaType": "application/vnd.docker.distribution.manifest.v2+json", - "size": 2217, - "digest": "sha256:293f12079921200fb3b9d17996bb0a06d743828d2bdd7eb49e245aee26d2f802", - "platform": { - "architecture": "arm64", - "os": "linux", - "variant": "v8" - } -} -... -``` - -The existing [Azure Voting App](https://github.com/Azure-Samples/azure-voting-app-redis/blob/master/azure-vote/Dockerfile) container image will not work for us, we must build and publish our own container and have it support multiple OS architectures. Thankfully, we can borrow a lot of [tiangolo's](https://github.com/tiangolo) code and build our own custom Dockerfile from it. - -With the focus of this lab being on deploying `arm64` workloads to AKS, we've saved you some time and combined the container image code from the original [Azure Voting App](https://github.com/Azure-Samples/azure-voting-app-redis) repo and [tiangolo's](https://github.com/tiangolo) Dockerfiles and published a new Azure Voting App repo [here](https://github.com/pauldotyu/azure-voting-app/blob/main/src/Dockerfile). This repo supports both AMD64 and ARM64 OS architectures by building and pushing images using [`docker buildx`](https://docs.docker.com/engine/reference/commandline/buildx/). - -### Deploying the Azure Voting App - -#### Build and publish the container image - -Navigate to the updated [Azure Voting App](https://github.com/pauldotyu/azure-voting-app) repo and click on the green "Use this template" button. This will allow you to create a new repo in your GitHub account. - -With the repo created in your GitHub account, clone the repo and open it in a terminal. - -This repo contains a [GitHub Actions workflow file](https://github.com/pauldotyu/azure-voting-app/blob/main/.github/workflows/docker-image.yml), which builds and publishes the app to your new Azure Container Registry. You will need to [create repository secrets](https://docs.github.com/en/actions/security-guides/encrypted-secrets#creating-encrypted-secrets-for-a-repository) so that your workflow can authenticate and publish to your registry. - -Run the following commands to pull out the registry credentials: - -> If you are using a new terminal, you will need to reset the `name` variable. Run the following command: -> -> name= - -```bash -acrServer=$(az acr show --name "acr${name}" --query loginServer -o tsv) -acrUsername=$(az acr credential show --name "acr${name}" --query username -o tsv) -acrPassword=$(az acr credential show --name "acr${name}" --query "passwords[0].value" -o tsv) -``` - -Using the GitHub CLI, run the following commands to set your repository secrets - -```bash -ghRepo="/" - -gh auth login -gh secret set ACR_SERVER --body $acrServer --repo $ghRepo -gh secret set ACR_USERNAME --body $acrUsername --repo $ghRepo -gh secret set ACR_PASSWORD --body $acrPassword --repo $ghRepo -``` - -To push an image to the Azure Container Registry, create a new release using the following command: - -```bash -gh release create v1.0.0 --notes "" --repo $ghRepo -``` - -Publishing a new release will trigger the GitHub Action workflow to build and publish the container image. - -> The build and publish will take approximately 8-10 minutes - -To view the output of the workflow, you can run these commands: - -```bash -gh run view --repo $ghRepo -gh run view --repo $ghRepo --job=XXXXXXXXX # your job number will be listed in the command above -gh run view --repo $ghRepo --log --job=XXXXXXXXXX # the log will be available when the job is complete -``` - -To validate your image, you can run the following: - -```bash -az acr manifest list-metadata --registry "acr${name}" --name azure-vote-front -``` - -#### Deploy the Kubernetes manifest - -The **azure-voting-app** repo includes a sample [Kubernetes manifest file](https://github.com/pauldotyu/azure-voting-app/blob/main/azure-voting-app-deploy.yaml) which you can use to deploy. There is a `` placeholder in the file and this can be swapped out using the `sed` command. - -The app deployment leverages [Kustomize](https://kustomize.io/) to customize your configuration at deployment time. The `kustomization.yaml` file includes a placeholder which you will swap out with your container registry server name. As the template is deployed to your Kubernetes cluster, Kustomize will replace the image value. - -Run the following command to update your `kustomization.yaml` file. - -```bash -sed -i'' -e "s//$acrServer/" kustomization.yaml -``` - -Now we can deploy the workload with the following command: - -```bash -kubectl apply -k . -``` - -> 📝 NOTE -> -> Kustomize is built into `kubectl` - -Inspect the pods to ensure they've deployed successfully: - -```bash -kubectl get po - -NAME READY STATUS RESTARTS AGE -azure-vote-back-54576c54f-bktkk 1/1 Running 0 3m23s -azure-vote-front-5694d5cc45-fx87s 1/1 Running 0 3m23s -``` - -Inspect the service to ensure you can browse to the site: - -```bash -kubectl get svc - -NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE -azure-vote-back ClusterIP 10.0.136.122 6379/TCP 117s -azure-vote-front LoadBalancer 10.0.74.8 20.81.58.34 80:30303/TCP 117s -kubernetes ClusterIP 10.0.0.1 443/TCP 32m -``` - -Once the `EXTERNAL-IP` is populated for the `azure-vote-front` service, you can use the IP address and browse to the Azure Voting App 🚀 - -## Summary - -Congratulations! 🎉 - -You've deployed an AKS cluster with an ARM64-based user node pool, built and published a new Azure Voting App container image which supports multiple OS architectures, and deployed the app into the AKS cluster. We also explored how we can inspect container image manifests to view the OS architectures they support. If your container images only support AMD64 OS architectures, you can easily re-target to support multiple platforms using Docker Buildx as demonstrated when we created a new release of the Azure Voting App. However, as we found in our exercise, you'll need to inspect the base layers of the container images to see if they also support ARM64. - -## Cleanup - -When you are finished exploring resources in this lab, you can delete the deployment by running the following commands: - -```bash -az group delete --name "rg-${name}" -az deployment sub delete --name "${name}-deploy" -``` - -If you do not wish to keep the Azure Voting App repo in your GitHub account, you can delete it by running the following GitHub CLI commands: - -```bash -gh auth refresh -h github.com -s delete_repo -gh repo delete $ghRepo -``` diff --git a/cloud-native/aks-arm64/azure-voting-app-deploy.yaml b/cloud-native/aks-arm64/azure-voting-app-deploy.yaml deleted file mode 100644 index 99e7859..0000000 --- a/cloud-native/aks-arm64/azure-voting-app-deploy.yaml +++ /dev/null @@ -1,94 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: azure-vote-back -spec: - replicas: 1 - selector: - matchLabels: - app: azure-vote-back - template: - metadata: - labels: - app: azure-vote-back - spec: - nodeSelector: - "kubernetes.io/os": linux - containers: - - name: azure-vote-back - image: redis:latest - env: - - name: ALLOW_EMPTY_PASSWORD - value: "yes" - ports: - - containerPort: 6379 - name: redis ---- -apiVersion: v1 -kind: Service -metadata: - name: azure-vote-back -spec: - ports: - - port: 6379 - selector: - app: azure-vote-back ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: azure-vote-front -spec: - replicas: 1 - selector: - matchLabels: - app: azure-vote-front - strategy: - rollingUpdate: - maxSurge: 1 - maxUnavailable: 1 - minReadySeconds: 5 - template: - metadata: - labels: - app: azure-vote-front - spec: - nodeSelector: - "kubernetes.io/os": linux - containers: - - name: azure-vote-front - image: cloudnativeadvocates.azurecr.io/azure-vote-front:v1.0.0 - ports: - - containerPort: 80 - resources: - requests: - cpu: 250m - limits: - cpu: 500m - env: - - name: REDIS - value: "azure-vote-back" ---- -apiVersion: v1 -kind: Service -metadata: - name: azure-vote-front -spec: - type: LoadBalancer - ports: - - port: 80 - selector: - app: azure-vote-front ---- -apiVersion: autoscaling/v1 -kind: HorizontalPodAutoscaler -metadata: - name: azure-vote-front -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: azure-vote-front - minReplicas: 1 - maxReplicas: 50 - targetCPUUtilizationPercentage: 50 diff --git a/cloud-native/aks-arm64/bicepconfig.json b/cloud-native/aks-arm64/bicepconfig.json deleted file mode 100644 index 91b4f8a..0000000 --- a/cloud-native/aks-arm64/bicepconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "moduleAliases": { - "ts": {}, - "br": { - "oss-labs": { - "registry": "cloudnativeadvocates.azurecr.io" - } - } - } -} \ No newline at end of file diff --git a/cloud-native/aks-arm64/kustomization.yaml b/cloud-native/aks-arm64/kustomization.yaml deleted file mode 100644 index f812c85..0000000 --- a/cloud-native/aks-arm64/kustomization.yaml +++ /dev/null @@ -1,8 +0,0 @@ -resources: -- azure-voting-app-deploy.yaml - -# Change the image name and version -images: -- name: cloudnativeadvocates.azurecr.io/azure-vote-front:v1.0.0 - newName: /azure-vote-front - newTag: v1.0.0 \ No newline at end of file diff --git a/cloud-native/aks-arm64/main.bicep b/cloud-native/aks-arm64/main.bicep deleted file mode 100644 index 86bca95..0000000 --- a/cloud-native/aks-arm64/main.bicep +++ /dev/null @@ -1,128 +0,0 @@ -targetScope = 'subscription' - -param name string -param location string -param tags object = {} - -var networkPlugin = 'kubenet' -var networkPolicy = 'calico' - -// Set up the resource group -resource rg 'Microsoft.Resources/resourceGroups@2021-04-01' = { - name: 'rg-${name}' - location: location - tags: tags -} - -// Set up the container registry -module acr '../../bicep/modules/azure-container-registry/main.bicep' = { - scope: rg - name: 'acrDeploy' - params: { - name: 'acr${toLower(name)}' - location: location - tags: tags - sku: 'Basic' - adminUserEnabled: true - managedIdentityType: 'SystemAssigned' - publicNetworkAccess: true - } -} - -// Set up the network security group -module nsg '../../bicep/modules/azure-network-security-group/main.bicep' = if (networkPlugin != 'kubenet') { - scope: rg - name: 'nsgDeploy' - params: { - name: 'nsg-${name}' - location: location - tags: tags - } -} - -// Setup the virtual network and subnet -module vnet '../../bicep/modules/azure-virtual-network/main.bicep' = if (networkPlugin != 'kubenet') { - scope: rg - name: 'vnetDeploy' - params: { - name: 'vnet-${name}' - location: location - tags: tags - vnetAddressPrefix: '10.21.0.0/16' - snetName: 'snet-${name}' - snetAddressPrefix: '10.21.0.0/24' - networkSecurityGroupId: networkPlugin != 'kubenet' ? nsg.outputs.id : '' - dnsServer: '' // Leave empty if you want to use Azure's default DNS - } -} - -// Setup the log analytics workspace -module law '../../bicep/modules/azure-log-analytics-workspace/main.bicep' = { - scope: rg - name: 'lawDeploy' - params: { - name: 'law-${name}' - location: location - tags: tags - } -} - -// Setup the Kubernetes cluster -module aks '../../bicep/modules/azure-kubernetes-service/main.bicep' = { - scope: rg - name: 'aksDeploy' - params: { - name: 'aks-${name}' - location: location - tags: tags - slaTier: 'Free' - managedIdentityType: 'SystemAssigned' - kubernetesVersion: '1.29' - networkPlugin: networkPlugin - networkPolicy: networkPolicy - loadBalancerSku: 'Standard' - outboundType: 'loadBalancer' - dnsServiceIP: '10.0.0.10' - podCidrs: [ - '10.244.0.0/16' - ] - serviceCidrs: [ - '10.0.0.0/16' - ] - ipFamilies: [ - 'IPv4' - ] - defenderEnabled: false - imageCleanerEnabled: false - systemNodeCount: 2 - systemNodeVmSize: 'Standard_D2s_v5' - registryName: acr.outputs.name - vnetSubnetID: networkPlugin != 'kubenet' ? vnet.outputs.subnetId : '' - logAnalyticsWorkspaceResourceId: law.outputs.id - nodeTaints: [ 'CriticalAddonsOnly=true:NoSchedule' ] // If deploying a user node pool too, you can taint the system node pool to prevent application pods from being scheduled on it; otherwise, leave empty - } -} - -// Setup the user node pools and deploy into a subnet -module aksPools '../../bicep/modules/azure-kubernetes-service-nodepools/main.bicep' = { - scope: rg - name: 'armNodePoolsDeploy' - params: { - managedClusterName: aks.outputs.name - userNodes: [ - { - name: 'arm64' - mode: 'User' - vmSize: 'Standard_D4pds_v5' // Make sure the SKU is available in your region. - enableAutoScaling: true - scaleDownMode: 'Delete' // Delete is the default. - minCount: 0 // If autoscale is enabled, then set the min number of nodes you wish to run. - maxCount: 2 // Set this to the maximum number of nodes to run. If autoscale is not enabled, this value will be used as the node count. - type: 'VirtualMachineScaleSets' // If autoscale is enabled, then the node type must be VirtualMachineScaleSets (default is AvailabilitySet). - osDiskType: 'Ephemeral' // If autoscale is enabled and scale down mode is set to Deallocate, then the OS disk must be managed (default is Ephemeral). - nodeTaints: '' // Add a taint like this `key=value:NoSchedule` or leave as empty string to not taint your nodes - vnetSubnetID: networkPlugin != 'kubenet' ? vnet.outputs.subnetId : '' // If the cluster is using azure network plugin, then you can pass in the subnet resource ID like this `vnet.outputs.subnetId`; otherwise, leave it empty - } - ] - } -} diff --git a/cloud-native/aks-arm64/main.json b/cloud-native/aks-arm64/main.json deleted file mode 100644 index 2961961..0000000 --- a/cloud-native/aks-arm64/main.json +++ /dev/null @@ -1,914 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "17685315886462117336" - } - }, - "parameters": { - "name": { - "type": "string" - }, - "location": { - "type": "string" - }, - "tags": { - "type": "object", - "defaultValue": {} - } - }, - "variables": { - "networkPlugin": "kubenet", - "networkPolicy": "calico" - }, - "resources": [ - { - "type": "Microsoft.Resources/resourceGroups", - "apiVersion": "2021-04-01", - "name": "[format('rg-{0}', parameters('name'))]", - "location": "[parameters('location')]", - "tags": "[parameters('tags')]" - }, - { - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "acrDeploy", - "resourceGroup": "[format('rg-{0}', parameters('name'))]", - "properties": { - "expressionEvaluationOptions": { - "scope": "inner" - }, - "mode": "Incremental", - "parameters": { - "name": { - "value": "[format('acr{0}', toLower(parameters('name')))]" - }, - "location": { - "value": "[parameters('location')]" - }, - "tags": { - "value": "[parameters('tags')]" - }, - "sku": { - "value": "Basic" - }, - "adminUserEnabled": { - "value": true - }, - "managedIdentityType": { - "value": "SystemAssigned" - }, - "publicNetworkAccess": { - "value": true - } - }, - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "17364936891097374484" - } - }, - "parameters": { - "name": { - "type": "string" - }, - "location": { - "type": "string" - }, - "tags": { - "type": "object" - }, - "sku": { - "type": "string", - "defaultValue": "Standard", - "allowedValues": [ - "Basic", - "Standard", - "Premium" - ], - "metadata": { - "description": "Defaults to Standard" - } - }, - "managedIdentityType": { - "type": "string", - "defaultValue": "SystemAssigned", - "allowedValues": [ - "SystemAssigned", - "UserAssigned" - ], - "metadata": { - "description": "Two options are available: SystemAssigned or UserAssigned" - } - }, - "userAssignedIdentities": { - "type": "object", - "defaultValue": {}, - "metadata": { - "description": "Required when managed identity type is set to UserAssigned" - } - }, - "adminUserEnabled": { - "type": "bool", - "defaultValue": false - }, - "anonymousPullEnabled": { - "type": "bool", - "defaultValue": false - }, - "publicNetworkAccess": { - "type": "bool", - "defaultValue": "[if(equals(parameters('sku'), 'Premium'), false(), true())]", - "metadata": { - "description": "Disableing public network access is not supported for Basic and Standard SKUs" - } - } - }, - "resources": [ - { - "type": "Microsoft.ContainerRegistry/registries", - "apiVersion": "2022-02-01-preview", - "name": "[parameters('name')]", - "location": "[parameters('location')]", - "tags": "[parameters('tags')]", - "sku": { - "name": "[parameters('sku')]" - }, - "identity": { - "type": "[parameters('managedIdentityType')]", - "userAssignedIdentities": "[if(not(equals(parameters('managedIdentityType'), 'SystemAssigned')), parameters('userAssignedIdentities'), null())]" - }, - "properties": { - "adminUserEnabled": "[parameters('adminUserEnabled')]", - "anonymousPullEnabled": "[parameters('anonymousPullEnabled')]", - "publicNetworkAccess": "[if(parameters('publicNetworkAccess'), 'Enabled', 'Disabled')]" - } - } - ], - "outputs": { - "name": { - "type": "string", - "value": "[parameters('name')]" - } - } - } - }, - "dependsOn": [ - "[subscriptionResourceId('Microsoft.Resources/resourceGroups', format('rg-{0}', parameters('name')))]" - ] - }, - { - "condition": "[not(equals(variables('networkPlugin'), 'kubenet'))]", - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "nsgDeploy", - "resourceGroup": "[format('rg-{0}', parameters('name'))]", - "properties": { - "expressionEvaluationOptions": { - "scope": "inner" - }, - "mode": "Incremental", - "parameters": { - "name": { - "value": "[format('nsg-{0}', parameters('name'))]" - }, - "location": { - "value": "[parameters('location')]" - }, - "tags": { - "value": "[parameters('tags')]" - } - }, - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "5609067551621364305" - } - }, - "parameters": { - "name": { - "type": "string" - }, - "tags": { - "type": "object" - }, - "location": { - "type": "string" - } - }, - "resources": [ - { - "type": "Microsoft.Network/networkSecurityGroups", - "apiVersion": "2022-01-01", - "name": "[parameters('name')]", - "location": "[parameters('location')]", - "properties": { - "securityRules": [] - }, - "tags": "[parameters('tags')]" - } - ], - "outputs": { - "id": { - "type": "string", - "value": "[resourceId('Microsoft.Network/networkSecurityGroups', parameters('name'))]" - } - } - } - }, - "dependsOn": [ - "[subscriptionResourceId('Microsoft.Resources/resourceGroups', format('rg-{0}', parameters('name')))]" - ] - }, - { - "condition": "[not(equals(variables('networkPlugin'), 'kubenet'))]", - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "vnetDeploy", - "resourceGroup": "[format('rg-{0}', parameters('name'))]", - "properties": { - "expressionEvaluationOptions": { - "scope": "inner" - }, - "mode": "Incremental", - "parameters": { - "name": { - "value": "[format('vnet-{0}', parameters('name'))]" - }, - "location": { - "value": "[parameters('location')]" - }, - "tags": { - "value": "[parameters('tags')]" - }, - "vnetAddressPrefix": { - "value": "10.21.0.0/16" - }, - "snetName": { - "value": "[format('snet-{0}', parameters('name'))]" - }, - "snetAddressPrefix": { - "value": "10.21.0.0/24" - }, - "networkSecurityGroupId": "[if(not(equals(variables('networkPlugin'), 'kubenet')), createObject('value', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, format('rg-{0}', parameters('name'))), 'Microsoft.Resources/deployments', 'nsgDeploy'), '2022-09-01').outputs.id.value), createObject('value', ''))]", - "dnsServer": { - "value": "" - } - }, - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "3087759273833726789" - } - }, - "parameters": { - "name": { - "type": "string" - }, - "location": { - "type": "string" - }, - "tags": { - "type": "object" - }, - "vnetAddressPrefix": { - "type": "string" - }, - "snetAddressPrefix": { - "type": "string" - }, - "snetName": { - "type": "string" - }, - "networkSecurityGroupId": { - "type": "string" - }, - "dnsServer": { - "type": "string" - } - }, - "resources": [ - { - "type": "Microsoft.Network/virtualNetworks", - "apiVersion": "2022-01-01", - "name": "[parameters('name')]", - "location": "[parameters('location')]", - "tags": "[parameters('tags')]", - "properties": { - "addressSpace": { - "addressPrefixes": [ - "[parameters('vnetAddressPrefix')]" - ] - }, - "dhcpOptions": "[if(not(empty(parameters('dnsServer'))), createObject('dnsServers', createArray(parameters('dnsServer'))), null())]", - "subnets": [ - { - "name": "[parameters('snetName')]", - "properties": { - "addressPrefix": "[parameters('snetAddressPrefix')]", - "networkSecurityGroup": { - "id": "[parameters('networkSecurityGroupId')]" - } - } - } - ] - } - } - ], - "outputs": { - "id": { - "type": "string", - "value": "[resourceId('Microsoft.Network/virtualNetworks', parameters('name'))]" - }, - "name": { - "type": "string", - "value": "[parameters('name')]" - }, - "subnetId": { - "type": "string", - "value": "[reference(resourceId('Microsoft.Network/virtualNetworks', parameters('name')), '2022-01-01').subnets[0].id]" - } - } - } - }, - "dependsOn": [ - "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, format('rg-{0}', parameters('name'))), 'Microsoft.Resources/deployments', 'nsgDeploy')]", - "[subscriptionResourceId('Microsoft.Resources/resourceGroups', format('rg-{0}', parameters('name')))]" - ] - }, - { - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "lawDeploy", - "resourceGroup": "[format('rg-{0}', parameters('name'))]", - "properties": { - "expressionEvaluationOptions": { - "scope": "inner" - }, - "mode": "Incremental", - "parameters": { - "name": { - "value": "[format('law-{0}', parameters('name'))]" - }, - "location": { - "value": "[parameters('location')]" - }, - "tags": { - "value": "[parameters('tags')]" - } - }, - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "4630854867665059244" - } - }, - "parameters": { - "name": { - "type": "string" - }, - "location": { - "type": "string" - }, - "tags": { - "type": "object" - } - }, - "resources": [ - { - "type": "Microsoft.OperationalInsights/workspaces", - "apiVersion": "2021-12-01-preview", - "name": "[parameters('name')]", - "location": "[parameters('location')]", - "tags": "[parameters('tags')]", - "properties": { - "retentionInDays": 30, - "sku": { - "name": "PerGB2018" - } - } - } - ], - "outputs": { - "id": { - "type": "string", - "value": "[resourceId('Microsoft.OperationalInsights/workspaces', parameters('name'))]" - } - } - } - }, - "dependsOn": [ - "[subscriptionResourceId('Microsoft.Resources/resourceGroups', format('rg-{0}', parameters('name')))]" - ] - }, - { - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "aksDeploy", - "resourceGroup": "[format('rg-{0}', parameters('name'))]", - "properties": { - "expressionEvaluationOptions": { - "scope": "inner" - }, - "mode": "Incremental", - "parameters": { - "name": { - "value": "[format('aks-{0}', parameters('name'))]" - }, - "location": { - "value": "[parameters('location')]" - }, - "tags": { - "value": "[parameters('tags')]" - }, - "slaTier": { - "value": "Free" - }, - "managedIdentityType": { - "value": "SystemAssigned" - }, - "kubernetesVersion": { - "value": "1.29" - }, - "networkPlugin": { - "value": "[variables('networkPlugin')]" - }, - "networkPolicy": { - "value": "[variables('networkPolicy')]" - }, - "loadBalancerSku": { - "value": "Standard" - }, - "outboundType": { - "value": "loadBalancer" - }, - "dnsServiceIP": { - "value": "10.0.0.10" - }, - "podCidrs": { - "value": [ - "10.244.0.0/16" - ] - }, - "serviceCidrs": { - "value": [ - "10.0.0.0/16" - ] - }, - "ipFamilies": { - "value": [ - "IPv4" - ] - }, - "defenderEnabled": { - "value": false - }, - "imageCleanerEnabled": { - "value": false - }, - "systemNodeCount": { - "value": 2 - }, - "systemNodeVmSize": { - "value": "Standard_D2s_v5" - }, - "registryName": { - "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, format('rg-{0}', parameters('name'))), 'Microsoft.Resources/deployments', 'acrDeploy'), '2022-09-01').outputs.name.value]" - }, - "vnetSubnetID": "[if(not(equals(variables('networkPlugin'), 'kubenet')), createObject('value', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, format('rg-{0}', parameters('name'))), 'Microsoft.Resources/deployments', 'vnetDeploy'), '2022-09-01').outputs.subnetId.value), createObject('value', ''))]", - "logAnalyticsWorkspaceResourceId": { - "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, format('rg-{0}', parameters('name'))), 'Microsoft.Resources/deployments', 'lawDeploy'), '2022-09-01').outputs.id.value]" - }, - "nodeTaints": { - "value": [ - "CriticalAddonsOnly=true:NoSchedule" - ] - } - }, - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "5599997474738078815" - } - }, - "parameters": { - "name": { - "type": "string" - }, - "location": { - "type": "string" - }, - "tags": { - "type": "object" - }, - "slaTier": { - "type": "string", - "defaultValue": "Free", - "allowedValues": [ - "Free", - "Paid" - ], - "metadata": { - "description": "Defaults to Free tier" - } - }, - "managedIdentityType": { - "type": "string", - "defaultValue": "SystemAssigned", - "allowedValues": [ - "SystemAssigned", - "UserAssigned" - ], - "metadata": { - "description": "Two options are available: SystemAssigned or UserAssigned" - } - }, - "userAssignedIdentities": { - "type": "object", - "defaultValue": {}, - "metadata": { - "description": "Required when managed identity type is set to UserAssigned" - } - }, - "kubernetesVersion": { - "type": "string", - "defaultValue": "1.29", - "metadata": { - "description": "Default is 1.29" - } - }, - "defenderEnabled": { - "type": "bool", - "defaultValue": false - }, - "imageCleanerEnabled": { - "type": "bool", - "defaultValue": false - }, - "imageCleanerIntervalHours": { - "type": "int", - "defaultValue": 12 - }, - "systemNodeCount": { - "type": "int", - "defaultValue": 3 - }, - "systemNodeVmSize": { - "type": "string", - "defaultValue": "Standard_D2s_v5", - "metadata": { - "description": "Default system node pool size is Standard_D2s_v5" - } - }, - "registryName": { - "type": "string", - "defaultValue": "", - "metadata": { - "description": "Optional parameter to attach AKS cluster to an existing ACR" - } - }, - "networkPlugin": { - "type": "string", - "defaultValue": "kubenet", - "allowedValues": [ - "kubenet", - "azure", - "none" - ], - "metadata": { - "description": "Network plugin used for building the Kubernetes network." - } - }, - "networkPolicy": { - "type": "string", - "defaultValue": "calico", - "allowedValues": [ - "calico", - "azure" - ], - "metadata": { - "description": "Network policy used for building the Kubernetes network." - } - }, - "loadBalancerSku": { - "type": "string", - "defaultValue": "Standard", - "allowedValues": [ - "Standard", - "Basic" - ], - "metadata": { - "description": "The default is standard." - } - }, - "dnsServiceIP": { - "type": "string", - "defaultValue": "10.0.0.10", - "metadata": { - "description": "An IP address assigned to the Kubernetes DNS service. It must be within the Kubernetes service address range specified in serviceCidr." - } - }, - "dockerBridgeCidr": { - "type": "string", - "defaultValue": "172.17.0.1/16", - "metadata": { - "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." - } - }, - "logAnalyticsWorkspaceResourceId": { - "type": "string", - "defaultValue": "", - "metadata": { - "description": "Resource ID of log analytics workspace for auditing" - } - }, - "outboundType": { - "type": "string", - "defaultValue": "loadBalancer", - "allowedValues": [ - "loadBalancer", - "managedNATGateway", - "userAssignedNATGateway", - "userDefinedRouting" - ], - "metadata": { - "description": "This can only be set at cluster creation time and cannot be changed later." - } - }, - "podCidrs": { - "type": "array", - "defaultValue": [ - "10.244.0.0/16" - ], - "metadata": { - "description": "One IPv4 CIDR is expected for single-stack networking. Two CIDRs, one for each IP family (IPv4/IPv6), is expected for dual-stack networking." - } - }, - "serviceCidrs": { - "type": "array", - "defaultValue": [ - "10.0.0.0/16" - ], - "metadata": { - "description": "One IPv4 CIDR is expected for single-stack networking. Two CIDRs, one for each IP family (IPv4/IPv6), is expected for dual-stack networking. They must not overlap with any Subnet IP ranges." - } - }, - "ipFamilies": { - "type": "array", - "defaultValue": [ - "IPv4" - ], - "allowedValues": [ - "IPv4", - "IPv6" - ] - }, - "vnetSubnetID": { - "type": "string", - "defaultValue": "", - "metadata": { - "description": "If the cluster is using azure network plugin, then you can pass in the subnet resource ID like this `vnet.outputs.subnetId`; otherwise, leave it empty" - } - }, - "nodeTaints": { - "type": "array", - "defaultValue": [], - "metadata": { - "description": "Enable nodeTaints on the system node pool (e.g., ['CriticalAddonsOnly=true:NoSchedule'])" - } - }, - "addonProfiles": { - "type": "object", - "defaultValue": {}, - "metadata": { - "description": "AKS addons to enable" - } - }, - "enablePrometheusMetrics": { - "type": "bool", - "defaultValue": false - }, - "prometheusMetricLabelsAllowlist": { - "type": "string", - "defaultValue": "" - }, - "prometheusMetricAnnotationsAllowList": { - "type": "string", - "defaultValue": "" - } - }, - "resources": [ - { - "type": "Microsoft.ContainerService/managedClusters", - "apiVersion": "2022-08-03-preview", - "name": "[parameters('name')]", - "location": "[parameters('location')]", - "tags": "[parameters('tags')]", - "sku": { - "name": "Basic", - "tier": "[parameters('slaTier')]" - }, - "identity": { - "type": "[parameters('managedIdentityType')]", - "userAssignedIdentities": "[if(equals(parameters('managedIdentityType'), 'UserAssigned'), parameters('userAssignedIdentities'), null())]" - }, - "properties": { - "kubernetesVersion": "[parameters('kubernetesVersion')]", - "dnsPrefix": "[parameters('name')]", - "azureMonitorProfile": "[if(parameters('enablePrometheusMetrics'), createObject('metrics', createObject('enabled', true(), 'kubeStateMetrics', createObject('metricLabelsAllowlist', parameters('prometheusMetricLabelsAllowlist'), 'metricAnnotationsAllowList', parameters('prometheusMetricAnnotationsAllowList')))), null())]", - "networkProfile": { - "networkPlugin": "[parameters('networkPlugin')]", - "networkPolicy": "[parameters('networkPolicy')]", - "loadBalancerSku": "[parameters('loadBalancerSku')]", - "dnsServiceIP": "[parameters('dnsServiceIP')]", - "dockerBridgeCidr": "[parameters('dockerBridgeCidr')]", - "outboundType": "[parameters('outboundType')]", - "podCidrs": "[parameters('podCidrs')]", - "serviceCidrs": "[parameters('serviceCidrs')]", - "ipFamilies": "[parameters('ipFamilies')]" - }, - "agentPoolProfiles": [ - { - "name": "system", - "count": "[parameters('systemNodeCount')]", - "vmSize": "[parameters('systemNodeVmSize')]", - "mode": "System", - "vnetSubnetID": "[if(empty(parameters('vnetSubnetID')), null(), parameters('vnetSubnetID'))]", - "nodeTaints": "[if(empty(parameters('nodeTaints')), null(), parameters('nodeTaints'))]" - } - ], - "securityProfile": { - "defender": { - "securityMonitoring": { - "enabled": "[parameters('defenderEnabled')]" - } - }, - "imageCleaner": { - "enabled": "[parameters('imageCleanerEnabled')]", - "intervalHours": "[parameters('imageCleanerIntervalHours')]" - } - }, - "addonProfiles": "[parameters('addonProfiles')]" - } - }, - { - "condition": "[not(equals(parameters('registryName'), ''))]", - "type": "Microsoft.Authorization/roleAssignments", - "apiVersion": "2022-04-01", - "scope": "[format('Microsoft.ContainerRegistry/registries/{0}', parameters('registryName'))]", - "name": "[guid(resourceId('Microsoft.ContainerService/managedClusters', parameters('name')), parameters('registryName'))]", - "properties": { - "principalId": "[reference(resourceId('Microsoft.ContainerService/managedClusters', parameters('name')), '2022-08-03-preview').identityProfile.kubeletidentity.objectId]", - "roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')]" - }, - "dependsOn": [ - "[resourceId('Microsoft.ContainerService/managedClusters', parameters('name'))]" - ] - }, - { - "type": "Microsoft.Authorization/roleAssignments", - "apiVersion": "2022-04-01", - "name": "[guid(resourceId('Microsoft.ContainerService/managedClusters', parameters('name')), resourceGroup().id)]", - "properties": { - "principalId": "[reference(resourceId('Microsoft.ContainerService/managedClusters', parameters('name')), '2022-08-03-preview', 'full').identity.principalId]", - "roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]" - }, - "dependsOn": [ - "[resourceId('Microsoft.ContainerService/managedClusters', parameters('name'))]" - ] - } - ], - "outputs": { - "name": { - "type": "string", - "value": "[parameters('name')]" - }, - "id": { - "type": "string", - "value": "[resourceId('Microsoft.ContainerService/managedClusters', parameters('name'))]" - }, - "kubeletIdentityObjectId": { - "type": "string", - "value": "[reference(resourceId('Microsoft.ContainerService/managedClusters', parameters('name')), '2022-08-03-preview').identityProfile.kubeletidentity.objectId]" - }, - "nodeResourceGroupName": { - "type": "string", - "value": "[reference(resourceId('Microsoft.ContainerService/managedClusters', parameters('name')), '2022-08-03-preview').nodeResourceGroup]" - } - } - } - }, - "dependsOn": [ - "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, format('rg-{0}', parameters('name'))), 'Microsoft.Resources/deployments', 'acrDeploy')]", - "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, format('rg-{0}', parameters('name'))), 'Microsoft.Resources/deployments', 'lawDeploy')]", - "[subscriptionResourceId('Microsoft.Resources/resourceGroups', format('rg-{0}', parameters('name')))]", - "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, format('rg-{0}', parameters('name'))), 'Microsoft.Resources/deployments', 'vnetDeploy')]" - ] - }, - { - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "armNodePoolsDeploy", - "resourceGroup": "[format('rg-{0}', parameters('name'))]", - "properties": { - "expressionEvaluationOptions": { - "scope": "inner" - }, - "mode": "Incremental", - "parameters": { - "managedClusterName": { - "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, format('rg-{0}', parameters('name'))), 'Microsoft.Resources/deployments', 'aksDeploy'), '2022-09-01').outputs.name.value]" - }, - "userNodes": { - "value": [ - { - "name": "arm64", - "mode": "User", - "vmSize": "Standard_D4pds_v5", - "enableAutoScaling": true, - "scaleDownMode": "Delete", - "minCount": 0, - "maxCount": 2, - "type": "VirtualMachineScaleSets", - "osDiskType": "Ephemeral", - "nodeTaints": "", - "vnetSubnetID": "[if(not(equals(variables('networkPlugin'), 'kubenet')), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, format('rg-{0}', parameters('name'))), 'Microsoft.Resources/deployments', 'vnetDeploy'), '2022-09-01').outputs.subnetId.value, '')]" - } - ] - } - }, - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "18243559256984356460" - } - }, - "parameters": { - "managedClusterName": { - "type": "string" - }, - "userNodes": { - "type": "array" - } - }, - "resources": [ - { - "copy": { - "name": "userNodePools", - "count": "[length(range(0, length(parameters('userNodes'))))]" - }, - "type": "Microsoft.ContainerService/managedClusters/agentPools", - "apiVersion": "2024-02-01", - "name": "[format('{0}/{1}', parameters('managedClusterName'), parameters('userNodes')[range(0, length(parameters('userNodes')))[copyIndex()]].name)]", - "properties": { - "vmSize": "[parameters('userNodes')[range(0, length(parameters('userNodes')))[copyIndex()]].vmSize]", - "mode": "[parameters('userNodes')[range(0, length(parameters('userNodes')))[copyIndex()]].mode]", - "enableAutoScaling": "[parameters('userNodes')[range(0, length(parameters('userNodes')))[copyIndex()]].enableAutoScaling]", - "count": "[if(contains(parameters('userNodes')[range(0, length(parameters('userNodes')))[copyIndex()]], 'maxCount'), parameters('userNodes')[range(0, length(parameters('userNodes')))[copyIndex()]].maxCount, 1)]", - "minCount": "[if(and(parameters('userNodes')[range(0, length(parameters('userNodes')))[copyIndex()]].enableAutoScaling, contains(parameters('userNodes')[range(0, length(parameters('userNodes')))[copyIndex()]], 'minCount')), parameters('userNodes')[range(0, length(parameters('userNodes')))[copyIndex()]].minCount, null())]", - "maxCount": "[if(and(parameters('userNodes')[range(0, length(parameters('userNodes')))[copyIndex()]].enableAutoScaling, contains(parameters('userNodes')[range(0, length(parameters('userNodes')))[copyIndex()]], 'maxCount')), parameters('userNodes')[range(0, length(parameters('userNodes')))[copyIndex()]].maxCount, null())]", - "scaleDownMode": "[if(and(parameters('userNodes')[range(0, length(parameters('userNodes')))[copyIndex()]].enableAutoScaling, contains(parameters('userNodes')[range(0, length(parameters('userNodes')))[copyIndex()]], 'scaleDownMode')), parameters('userNodes')[range(0, length(parameters('userNodes')))[copyIndex()]].scaleDownMode, null())]", - "nodeTaints": "[if(empty(parameters('userNodes')[range(0, length(parameters('userNodes')))[copyIndex()]].nodeTaints), null(), parameters('userNodes')[range(0, length(parameters('userNodes')))[copyIndex()]].nodeTaints)]", - "type": "[parameters('userNodes')[range(0, length(parameters('userNodes')))[copyIndex()]].type]", - "osDiskType": "[parameters('userNodes')[range(0, length(parameters('userNodes')))[copyIndex()]].osDiskType]", - "vnetSubnetID": "[if(empty(parameters('userNodes')[range(0, length(parameters('userNodes')))[copyIndex()]].vnetSubnetID), null(), parameters('userNodes')[range(0, length(parameters('userNodes')))[copyIndex()]].vnetSubnetID)]" - } - } - ] - } - }, - "dependsOn": [ - "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, format('rg-{0}', parameters('name'))), 'Microsoft.Resources/deployments', 'aksDeploy')]", - "[subscriptionResourceId('Microsoft.Resources/resourceGroups', format('rg-{0}', parameters('name')))]", - "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, format('rg-{0}', parameters('name'))), 'Microsoft.Resources/deployments', 'vnetDeploy')]" - ] - } - ] -} \ No newline at end of file diff --git a/cloud-native/aks-bicep-k8s/README.md b/cloud-native/aks-bicep-k8s/README.md deleted file mode 100644 index 9d17e36..0000000 --- a/cloud-native/aks-bicep-k8s/README.md +++ /dev/null @@ -1,61 +0,0 @@ -# Explore Open Source workloads with Azure Kubernetes Service (AKS) and the Bicep extensibility Kubernetes provider - -In this lab you will deploy an Azure Kubernetes Service (AKS) cluster, other Azure services (Container Registry, Managed Identity, Storage Account), and open source workloads, with [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli), [Bicep](https://docs.microsoft.com/en-us/azure/azure-resource-manager/bicep/overview) and the [Bicep extensibility Kubernetes provider (Preview)](https://learn.microsoft.com/azure/azure-resource-manager/bicep/bicep-extensibility-kubernetes-provider). - -## Requirements - -- An **Azure Subscription** (e.g. [Free](https://aka.ms/azure-free-account) or [Student](https://aka.ms/azure-student-account) account) -- The [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli) -- Bash shell (e.g. macOS, Linux, [Windows Subsystem for Linux (WSL)](https://docs.microsoft.com/en-us/windows/wsl/about), [Multipass](https://multipass.run/), [Azure Cloud Shell](https://docs.microsoft.com/en-us/azure/cloud-shell/quickstart), [GitHub Codespaces](https://github.com/features/codespaces), etc) -- [Go](https://go.dev/dl/) (Optional) -- [Mage](https://magefile.org/) (`go install github.com/magefile/mage@latest`) (Optional) - -## Instructions - -Use the [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli) and [Bicep](https://docs.microsoft.com/en-us/azure/azure-resource-manager/bicep/overview) templates to deploy the infrastructure for your application. - -Login to the Azure CLI. - -```bash -az login -``` - -Clone this repository. - -```bash -git clone https://github.com/Azure-Samples/azure-opensource-labs.git -``` - -Change to this directory. - -``` -cd azure-opensource-labs/cloud-native/aks-bicep-k8s -``` - -While you can deploy the Bicep templates ([main.bicep](./main.bicep)) via the Azure CLI or Azure Portal, we have included a Magefile, [magefile.go](./magefile.go), with the following targets to make deployment easier. - -``` -$ mage -Targets: - aksCredentials gets credentials for the AKS cluster - aksKubectl ensures kubectl is installed - deployAKS deploys aks.bicep at the Resource Group scope - deployApp DeployAKS uses aks-deploy-app.bicep to deploy AKS_APP_BICEP(=azure-vote.bicep) - deployMain [experimental] deploys main.bicep::q at the Resource Group scope - empty empties the Azure resource group - emptyNamespace has az invoke kubectl delete all on K8S_NAMESPACE - group creates the Azure resource group - groupDelete deletes the Azure resource group -``` - -### Deployment - -``` -mage group deployAks deployApp -``` - -### Delete resources - -``` -mage empty -``` diff --git a/cloud-native/aks-bicep-k8s/aks-deploy-app.bicep b/cloud-native/aks-bicep-k8s/aks-deploy-app.bicep deleted file mode 100644 index b6aeff1..0000000 --- a/cloud-native/aks-bicep-k8s/aks-deploy-app.bicep +++ /dev/null @@ -1,16 +0,0 @@ -param clusterName string = 'aks1' -param namespace string = 'default' - -resource aksCluster 'Microsoft.ContainerService/managedClusters@2023-05-01' existing = { - name: clusterName -} - -module app './azure-vote.bicep' = { - name: '${resourceGroup().name}-app' - params: { - kubeConfig: aksCluster.listClusterAdminCredential().kubeconfigs[0].value - namespace: namespace - } -} - -output appOutputs object = app.outputs diff --git a/cloud-native/aks-bicep-k8s/aks.bicep b/cloud-native/aks-bicep-k8s/aks.bicep deleted file mode 100644 index 91cc6f1..0000000 --- a/cloud-native/aks-bicep-k8s/aks.bicep +++ /dev/null @@ -1,93 +0,0 @@ -param location string = resourceGroup().location -param clusterName string = 'aks1' -param nodeCount int = 1 -param vmSize string = 'standard_d2s_v5' -param kubernetesVersion string = '1.29' - -var rand = substring(uniqueString(resourceGroup().id), 0, 6) - -resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: '${resourceGroup().name}-identity' - location: location -} - -resource aks 'Microsoft.ContainerService/managedClusters@2021-05-01' = { - name: clusterName - location: location - identity: { - type: 'UserAssigned' - userAssignedIdentities: { - '${managedIdentity.id}': {} - } - } - properties: { - kubernetesVersion: kubernetesVersion - dnsPrefix: clusterName - enableRBAC: true - agentPoolProfiles: [ - { - name: 'nodepool1' - count: nodeCount - vmSize: vmSize - mode: 'System' - } - ] - } -} - -resource containerRegistry 'Microsoft.ContainerRegistry/registries@2019-05-01' = { - name: 'acr${rand}' - location: location - sku: { - name: 'Standard' - } - properties: { - adminUserEnabled: true - } -} - -resource storageAccount 'Microsoft.Storage/storageAccounts@2021-02-01' = { - name: 'storage${rand}' - location: location - kind: 'BlockBlobStorage' - sku: { - name: 'Premium_LRS' - } - properties: { - minimumTlsVersion: 'TLS1_2' - } -} - -// via: https://docs.microsoft.com/en-us/azure/azure-resource-manager/bicep/bicep-functions-resource#subscriptionresourceid-example -var roleDefinitionId = { - Owner: '8e3af657-a8ff-443c-a75c-2fe8c4bcb635' - Contributor: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - Reader: 'acdd72a7-3385-48ef-bd42-f606fba81ae7' - AcrPull: '7f951dda-4ed3-4680-a7ca-43fe172d538d' - StorageBlobDataContributor: 'ba92f5b4-2d11-453d-a403-e96b0029c9fe' - KubernetesServiceClusterUserRole: '4abbcc35-e782-43d8-92c5-2d3f1bd2253f' -} - -// https://github.com/Azure/bicep/discussions/3181 -var roleAssignmentAcrDefinition = 'AcrPull' -resource roleAssignmentAcr 'Microsoft.Authorization/roleAssignments@2020-08-01-preview' = { - name: guid(containerRegistry.id, roleAssignmentAcrDefinition) - scope: containerRegistry - properties: { - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleDefinitionId[roleAssignmentAcrDefinition]) - principalId: aks.properties.identityProfile.kubeletidentity.objectId - } -} - -var roleAssignmentStorageAccountDefinition = 'StorageBlobDataContributor' -resource roleAssignmentStorageAccount 'Microsoft.Authorization/roleAssignments@2020-08-01-preview' = { - name: guid(storageAccount.id, roleAssignmentStorageAccountDefinition) - scope: storageAccount - properties: { - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleDefinitionId[roleAssignmentStorageAccountDefinition]) - principalId: managedIdentity.properties.principalId - } - dependsOn: [ - aks - ] -} diff --git a/cloud-native/aks-bicep-k8s/azure-vote.bicep b/cloud-native/aks-bicep-k8s/azure-vote.bicep deleted file mode 100644 index 5caf885..0000000 --- a/cloud-native/aks-bicep-k8s/azure-vote.bicep +++ /dev/null @@ -1,150 +0,0 @@ -@secure() -param kubeConfig string -param namespace string = 'default' - -import 'kubernetes@1.0.0' with { - namespace: namespace - kubeConfig: kubeConfig -} - -resource appsDeployment_azureVoteBack 'apps/Deployment@v1' = { - metadata: { - name: 'azure-vote-back' - } - spec: { - replicas: 1 - selector: { - matchLabels: { - app: 'azure-vote-back' - } - } - template: { - metadata: { - labels: { - app: 'azure-vote-back' - } - } - spec: { - nodeSelector: { - 'kubernetes.io/os': 'linux' - } - containers: [ - { - name: 'azure-vote-back' - image: 'mcr.microsoft.com/oss/bitnami/redis:6.0.8' - env: [ - { - name: 'ALLOW_EMPTY_PASSWORD' - value: 'yes' - } - ] - resources: { - requests: { - cpu: '100m' - memory: '128Mi' - } - limits: { - cpu: '250m' - memory: '256Mi' - } - } - ports: [ - { - containerPort: 6379 - name: 'redis' - } - ] - } - ] - } - } - } -} - -resource coreService_azureVoteBack 'core/Service@v1' = { - metadata: { - name: 'azure-vote-back' - } - spec: { - ports: [ - { - port: 6379 - } - ] - selector: { - app: 'azure-vote-back' - } - } -} - -resource appsDeployment_azureVoteFront 'apps/Deployment@v1' = { - metadata: { - name: 'azure-vote-front' - } - spec: { - replicas: 1 - selector: { - matchLabels: { - app: 'azure-vote-front' - } - } - template: { - metadata: { - labels: { - app: 'azure-vote-front' - } - } - spec: { - nodeSelector: { - 'kubernetes.io/os': 'linux' - } - containers: [ - { - name: 'azure-vote-front' - image: 'mcr.microsoft.com/azuredocs/azure-vote-front:v1' - resources: { - requests: { - cpu: '100m' - memory: '128Mi' - } - limits: { - cpu: '250m' - memory: '256Mi' - } - } - ports: [ - { - containerPort: 80 - } - ] - env: [ - { - name: 'REDIS' - value: 'azure-vote-back' - } - ] - } - ] - } - } - } -} - -resource coreService_azureVoteFront 'core/Service@v1' = { - metadata: { - name: 'azure-vote-front' - } - spec: { - type: 'LoadBalancer' - ports: [ - { - port: 80 - } - ] - selector: { - app: 'azure-vote-front' - } - } -} - -output frontendIp string = coreService_azureVoteFront.status.loadBalancer.ingress[0].ip diff --git a/cloud-native/aks-bicep-k8s/azure-vote.yaml b/cloud-native/aks-bicep-k8s/azure-vote.yaml deleted file mode 100644 index b071366..0000000 --- a/cloud-native/aks-bicep-k8s/azure-vote.yaml +++ /dev/null @@ -1,85 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: azure-vote-back -spec: - replicas: 1 - selector: - matchLabels: - app: azure-vote-back - template: - metadata: - labels: - app: azure-vote-back - spec: - nodeSelector: - "kubernetes.io/os": linux - containers: - - name: azure-vote-back - image: mcr.microsoft.com/oss/bitnami/redis:6.0.8 - env: - - name: ALLOW_EMPTY_PASSWORD - value: "yes" - resources: - requests: - cpu: 100m - memory: 128Mi - limits: - cpu: 250m - memory: 256Mi - ports: - - containerPort: 6379 - name: redis ---- -apiVersion: v1 -kind: Service -metadata: - name: azure-vote-back -spec: - ports: - - port: 6379 - selector: - app: azure-vote-back ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: azure-vote-front -spec: - replicas: 1 - selector: - matchLabels: - app: azure-vote-front - template: - metadata: - labels: - app: azure-vote-front - spec: - nodeSelector: - "kubernetes.io/os": linux - containers: - - name: azure-vote-front - image: mcr.microsoft.com/azuredocs/azure-vote-front:v1 - resources: - requests: - cpu: 100m - memory: 128Mi - limits: - cpu: 250m - memory: 256Mi - ports: - - containerPort: 80 - env: - - name: REDIS - value: "azure-vote-back" ---- -apiVersion: v1 -kind: Service -metadata: - name: azure-vote-front -spec: - type: LoadBalancer - ports: - - port: 80 - selector: - app: azure-vote-front \ No newline at end of file diff --git a/cloud-native/aks-bicep-k8s/azure-voting-app-rust.bicep b/cloud-native/aks-bicep-k8s/azure-voting-app-rust.bicep deleted file mode 100644 index e94ef75..0000000 --- a/cloud-native/aks-bicep-k8s/azure-voting-app-rust.bicep +++ /dev/null @@ -1,165 +0,0 @@ -@secure() -param kubeConfig string -param namespace string = 'default' - -import 'kubernetes@1.0.0' with { - namespace: namespace - kubeConfig: kubeConfig -} - -resource appsDeployment_postgres 'apps/Deployment@v1' = { - metadata: { - name: 'postgres' - } - spec: { - replicas: 1 - selector: { - matchLabels: { - app: 'postgres' - } - } - template: { - metadata: { - labels: { - app: 'postgres' - } - } - spec: { - nodeSelector: { - 'kubernetes.io/os': 'linux' - } - containers: [ - { - name: 'postgres' - image: 'postgres:15.0-alpine' - env: [ - { - name: 'POSTGRES_PASSWORD' - value: 'mypassword' - } - ] - resources: { - requests: { - cpu: '100m' - memory: '128Mi' - } - limits: { - cpu: '250m' - memory: '256Mi' - } - } - ports: [ - { - containerPort: 5432 - name: 'postgres' - } - ] - } - ] - } - } - } -} - -resource coreService_postgres 'core/Service@v1' = { - metadata: { - name: 'postgres' - } - spec: { - ports: [ - { - port: 5432 - } - ] - selector: { - app: 'postgres' - } - } -} - -resource appsDeployment_azureVotingAppRust 'apps/Deployment@v1' = { - metadata: { - name: 'azure-voting-app-rust' - } - spec: { - replicas: 1 - selector: { - matchLabels: { - app: 'azure-voting-app-rust' - } - } - template: { - metadata: { - labels: { - app: 'azure-voting-app-rust' - } - } - spec: { - nodeSelector: { - 'kubernetes.io/os': 'linux' - } - containers: [ - { - name: 'azure-voting-app-rust' - image: 'ghcr.io/asw101/azure-voting-app-rust:latest' - resources: { - requests: { - cpu: '100m' - memory: '128Mi' - } - limits: { - cpu: '250m' - memory: '256Mi' - } - } - ports: [ - { - containerPort: 8080 - } - ] - env: [ - { - name: 'DATABASE_SERVER' - value: 'postgres' - } - { - name: 'DATABASE_PASSWORD' - value: 'mypassword' - } - { - name: 'FIRST_VALUE' - value: 'Go' - } - { - name: 'SECOND_VALUE' - value: 'Rust' - } - ] - } - ] - } - } - } -} - -resource coreService_azureVotingAppRust 'core/Service@v1' = { - metadata: { - name: 'azure-voting-app-rust' - } - spec: { - type: 'LoadBalancer' - ports: [ - { - protocol: 'TCP' - port: 80 - targetPort: 8080 - } - ] - selector: { - app: 'azure-voting-app-rust' - } - } -} - - -output frontendIp string = coreService_azureVotingAppRust.status.loadBalancer.ingress[0].ip diff --git a/cloud-native/aks-bicep-k8s/azure-voting-app-rust.yaml b/cloud-native/aks-bicep-k8s/azure-voting-app-rust.yaml deleted file mode 100644 index 1578f03..0000000 --- a/cloud-native/aks-bicep-k8s/azure-voting-app-rust.yaml +++ /dev/null @@ -1,93 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: postgres -spec: - replicas: 1 - selector: - matchLabels: - app: postgres - template: - metadata: - labels: - app: postgres - spec: - nodeSelector: - "kubernetes.io/os": linux - containers: - - name: postgres - image: postgres:15.0-alpine - env: - - name: POSTGRES_PASSWORD - value: "mypassword" - resources: - requests: - cpu: 100m - memory: 128Mi - limits: - cpu: 250m - memory: 256Mi - ports: - - containerPort: 5432 - name: postgres ---- -apiVersion: v1 -kind: Service -metadata: - name: postgres -spec: - ports: - - port: 5432 - selector: - app: postgres ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: azure-voting-app-rust -spec: - replicas: 1 - selector: - matchLabels: - app: azure-voting-app-rust - template: - metadata: - labels: - app: azure-voting-app-rust - spec: - nodeSelector: - "kubernetes.io/os": linux - containers: - - name: azure-voting-app-rust - image: ghcr.io/asw101/azure-voting-app-rust:latest - resources: - requests: - cpu: 100m - memory: 128Mi - limits: - cpu: 250m - memory: 256Mi - ports: - - containerPort: 8080 - env: - - name: DATABASE_SERVER - value: "postgres" - - name: DATABASE_PASSWORD - value: "mypassword" - - name: FIRST_VALUE - value: "Go" - - name: SECOND_VALUE - value: "Rust" ---- -apiVersion: v1 -kind: Service -metadata: - name: azure-voting-app-rust -spec: - type: LoadBalancer - ports: - - protocol: TCP - port: 80 - targetPort: 8080 - selector: - app: azure-voting-app-rust diff --git a/cloud-native/aks-bicep-k8s/bicepconfig.json b/cloud-native/aks-bicep-k8s/bicepconfig.json deleted file mode 100644 index b59b79d..0000000 --- a/cloud-native/aks-bicep-k8s/bicepconfig.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - // See https://aka.ms/bicep/config for more information on Bicep configuration options - // Press CTRL+SPACE/CMD+SPACE at any location to see Intellisense suggestions - "analyzers": { - "core": { - "rules": { - "no-unused-params": { - "level": "warning" - } - } - } - }, - "experimentalFeaturesEnabled": { - "extensibility": true - } - } \ No newline at end of file diff --git a/cloud-native/aks-bicep-k8s/dotnet-vue-starter.bicep b/cloud-native/aks-bicep-k8s/dotnet-vue-starter.bicep deleted file mode 100644 index a1cfcf5..0000000 --- a/cloud-native/aks-bicep-k8s/dotnet-vue-starter.bicep +++ /dev/null @@ -1,75 +0,0 @@ -@secure() -param kubeConfig string -param namespace string = 'default' - -import 'kubernetes@1.0.0' with { - namespace: namespace - kubeConfig: kubeConfig -} - -resource appsDeployment_dotnetVueStarter 'apps/Deployment@v1' = { - metadata: { - name: 'dotnet-vue-starter' - } - spec: { - replicas: 1 - selector: { - matchLabels: { - app: 'dotnet-vue-starter' - } - } - template: { - metadata: { - labels: { - app: 'dotnet-vue-starter' - } - } - spec: { - nodeSelector: { - 'kubernetes.io/os': 'linux' - } - containers: [ - { - name: 'dotnet-vue-starter' - image: 'ghcr.io/asw101/dotnet-vue-starter:latest' - resources: { - requests: { - cpu: '100m' - memory: '128Mi' - } - limits: { - cpu: '250m' - memory: '256Mi' - } - } - ports: [ - { - containerPort: 80 - } - ] - } - ] - } - } - } -} - -resource coreService_dotnetVueStarter 'core/Service@v1' = { - metadata: { - name: 'dotnet-vue-starter' - } - spec: { - type: 'LoadBalancer' - ports: [ - { - port: 80 - } - ] - selector: { - app: 'dotnet-vue-starter' - } - } -} - - -output frontendIp string = coreService_dotnetVueStarter.status.loadBalancer.ingress[0].ip diff --git a/cloud-native/aks-bicep-k8s/dotnet-vue-starter.yaml b/cloud-native/aks-bicep-k8s/dotnet-vue-starter.yaml deleted file mode 100644 index ff02e80..0000000 --- a/cloud-native/aks-bicep-k8s/dotnet-vue-starter.yaml +++ /dev/null @@ -1,39 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: dotnet-vue-starter -spec: - replicas: 1 - selector: - matchLabels: - app: dotnet-vue-starter - template: - metadata: - labels: - app: dotnet-vue-starter - spec: - nodeSelector: - "kubernetes.io/os": linux - containers: - - name: dotnet-vue-starter - image: ghcr.io/asw101/dotnet-vue-starter:latest - resources: - requests: - cpu: 100m - memory: 128Mi - limits: - cpu: 250m - memory: 256Mi - ports: - - containerPort: 80 ---- -apiVersion: v1 -kind: Service -metadata: - name: dotnet-vue-starter -spec: - type: LoadBalancer - ports: - - port: 80 - selector: - app: dotnet-vue-starter \ No newline at end of file diff --git a/cloud-native/aks-bicep-k8s/go.mod b/cloud-native/aks-bicep-k8s/go.mod deleted file mode 100644 index 0fd1d2b..0000000 --- a/cloud-native/aks-bicep-k8s/go.mod +++ /dev/null @@ -1,5 +0,0 @@ -module aksbicep - -go 1.19 - -require github.com/magefile/mage v1.14.0 diff --git a/cloud-native/aks-bicep-k8s/go.sum b/cloud-native/aks-bicep-k8s/go.sum deleted file mode 100644 index f8bfb2f..0000000 --- a/cloud-native/aks-bicep-k8s/go.sum +++ /dev/null @@ -1,2 +0,0 @@ -github.com/magefile/mage v1.14.0 h1:6QDX3g6z1YvJ4olPhT1wksUcSa/V0a1B+pJb73fBjyo= -github.com/magefile/mage v1.14.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= diff --git a/cloud-native/aks-bicep-k8s/magefile.go b/cloud-native/aks-bicep-k8s/magefile.go deleted file mode 100644 index dc8116c..0000000 --- a/cloud-native/aks-bicep-k8s/magefile.go +++ /dev/null @@ -1,277 +0,0 @@ -//go:build mage - -package main - -import ( - "errors" - "fmt" - "os" - "strings" - "time" - - "github.com/magefile/mage/sh" -) - -// resourceGroup gets resource group name from the -// RESOURCE_GROUP env var, or provides a default -func resourceGroup() string { - name := os.Getenv("RESOURCE_GROUP") - if name == "" { - name = fmt.Sprintf("%s-aks-bicep", time.Now().Format("060100")) - } - return name -} - -// Group creates the Azure resource group -func Group() error { - name := resourceGroup() - location := os.Getenv("LOCATION") - if location == "" { - location = "eastus" - } - cmd := []string{ - "az", - "group", - "create", - "--name", - name, - "--location", - location, - } - return sh.RunV(cmd[0], cmd[1:]...) -} - -// DeployAKS deploys aks.bicep at the Resource Group scope -func DeployAKS() error { - name := resourceGroup() - location := os.Getenv("LOCATION") - if location == "" { - location = "eastus" - } - - file1 := "aks.bicep" - cmd := []string{ - "az", - "deployment", - "group", - "create", - "--resource-group", - name, - "--template-file", - file1, - "--parameters", - "location=" + location, - } - return sh.RunV(cmd[0], cmd[1:]...) -} - -// DeployAKS uses aks-deploy-app.bicep to deploy AKS_APP_BICEP(=azure-vote.bicep) -func DeployApp() error { - name := resourceGroup() - k8sNamespace := os.Getenv("K8S_NAMESPACE") - if k8sNamespace == "" { - k8sNamespace = "default" - } - appBicep := os.Getenv("AKS_APP_BICEP") - if appBicep == "" { - appBicep = "azure-vote.bicep" - } - fmt.Printf("Deploying AKS_APP_BICEP=%s\n", appBicep) - - // make temporary file - file1 := "aks-deploy-app.bicep" - file2 := "tmp.bicep" - err := sh.Copy(file2, file1) - if err != nil { - return err - } - defer os.RemoveAll(file2) - - replace1 := map[string]string{ - "azure-vote.bicep": appBicep, - } - err = fileReplace(file2, replace1) - if err != nil { - return err - } - - cmd := []string{ - "az", - "deployment", - "group", - "create", - "--resource-group", - name, - "--template-file", - file2, - "--parameters", - "namespace=" + k8sNamespace, - } - err = sh.RunV(cmd[0], cmd[1:]...) - if err != nil { - fmt.Printf("error. retrying once in 20s.\n") - time.Sleep(20 * time.Second) - err = sh.RunV(cmd[0], cmd[1:]...) - } - return err -} - -// DeployMain [experimental] deploys main.bicep at the Resource Group scope -func DeployMain() error { - name := resourceGroup() - location := os.Getenv("LOCATION") - if location == "" { - location = "eastus" - } - aksName := os.Getenv("AKS_NAME") - if aksName == "" { - aksName = "aks1" - } - deployCluster := os.Getenv("DEPLOY_CLUSTER") - if deployCluster == "" { - deployCluster = "true" - } - switch { - case deployCluster == "true" || deployCluster == "false": - default: - return errors.New("DEPLOY_CLUSTER must be true, false, or empty") - } - - file1 := "main.bicep" - cmd := []string{ - "az", - "deployment", - "group", - "create", - "--resource-group", - name, - "--template-file", - file1, - "--parameters", - "location=" + location, - "clusterName=" + aksName, - "deployCluster=" + deployCluster, - } - return sh.RunV(cmd[0], cmd[1:]...) -} - -// EmptyNamespace has az invoke kubectl delete all on K8S_NAMESPACE -func EmptyNamespace() error { - name := resourceGroup() - location := os.Getenv("LOCATION") - if location == "" { - location = "eastus" - } - aksName := os.Getenv("AKS_NAME") - if aksName == "" { - aksName = "aks1" - } - k8sNamespace := os.Getenv("K8S_NAMESPACE") - if k8sNamespace == "" { - k8sNamespace = "default" - } - - kubectlCommand := "kubectl delete all --all -n " + k8sNamespace - cmd := []string{ - "az", - "aks", - "command", - "invoke", - "--resource-group", - name, - "--name", - aksName, - "--command", - kubectlCommand, - } - return sh.RunV(cmd[0], cmd[1:]...) -} - -// AksCredentials gets credentials for the AKS cluster -func AksCredentials() error { - name := resourceGroup() - aksName := os.Getenv("AKS_NAME") - if aksName == "" { - aksName = "aks1" - } - cmd := []string{ - "az", - "aks", - "get-credentials", - "--resource-group", - name, - "--name", - aksName, - "--overwrite-existing", - } - return sh.RunV(cmd[0], cmd[1:]...) -} - -// AksKubectl ensures kubectl is installed -func AksKubectl() error { - cmd := []string{ - "az", - "aks", - "install-cli", - } - return sh.RunV(cmd[0], cmd[1:]...) -} - -// Empty empties the Azure resource group -func Empty() error { - name := resourceGroup() - file1 := "empty.bicep" - f, err := os.Create(file1) - if err != nil { - return err - } - f.Close() - cmd := []string{ - "az", - "deployment", - "group", - "create", - "--resource-group", - name, - "--template-file", - file1, - "--mode", - "Complete", - } - err = sh.RunV(cmd[0], cmd[1:]...) - if err != nil { - return err - } - err = os.RemoveAll(file1) - if err != nil { - return err - } - return nil -} - -// GroupDelete deletes the Azure resource group -func GroupDelete() error { - name := resourceGroup() - cmd := []string{ - "az", - "group", - "delete", - "--name", - name, - "--yes", - } - return sh.RunV(cmd[0], cmd[1:]...) -} - -// fileReplace replaces values in a file using a map -func fileReplace(file string, replace map[string]string) error { - b, err := os.ReadFile(file) - if err != nil { - return err - } - val := string(b) - for k, v := range replace { - val = strings.Replace(val, k, v, -1) - } - return os.WriteFile(file, []byte(val), 0644) -} diff --git a/cloud-native/aks-bicep-k8s/main.bicep b/cloud-native/aks-bicep-k8s/main.bicep deleted file mode 100644 index 67cede8..0000000 --- a/cloud-native/aks-bicep-k8s/main.bicep +++ /dev/null @@ -1,29 +0,0 @@ -param location string = resourceGroup().location -param clusterName string = 'aks1' -param namespace string = 'default' -param deployCluster bool = true - -module aks './aks.bicep' = if(deployCluster) { - name: '${resourceGroup().name}-aks' - params: { - location: location - clusterName: clusterName - } -} - -resource aksCluster 'Microsoft.ContainerService/managedClusters@2023-05-01' existing = { - name: clusterName -} - -module app './azure-vote.bicep' = { - name: '${resourceGroup().name}-app' - params: { - kubeConfig: aksCluster.listClusterAdminCredential().kubeconfigs[0].value - namespace: namespace - } - dependsOn: [ - aks - ] -} - -output lbPublicIp string = app.outputs.frontendIp diff --git a/cloud-native/aks-bicep-k8s/main.json b/cloud-native/aks-bicep-k8s/main.json deleted file mode 100644 index 6b9c65e..0000000 --- a/cloud-native/aks-bicep-k8s/main.json +++ /dev/null @@ -1,424 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "languageVersion": "2.1-experimental", - "contentVersion": "1.0.0.0", - "metadata": { - "_EXPERIMENTAL_WARNING": "This template uses ARM features that are experimental. Experimental features should be enabled for testing purposes only, as there are no guarantees about the quality or stability of these features. Do not enable these settings for any production usage, or your production environment may be subject to breaking.", - "_EXPERIMENTAL_FEATURES_ENABLED": [ - "Extensibility" - ], - "_generator": { - "name": "bicep", - "version": "0.26.170.59819", - "templateHash": "8744504821534446077" - } - }, - "parameters": { - "location": { - "type": "string", - "defaultValue": "[resourceGroup().location]" - }, - "clusterName": { - "type": "string", - "defaultValue": "aks1" - }, - "namespace": { - "type": "string", - "defaultValue": "default" - }, - "deployCluster": { - "type": "bool", - "defaultValue": true - } - }, - "resources": { - "aksCluster": { - "existing": true, - "type": "Microsoft.ContainerService/managedClusters", - "apiVersion": "2023-05-01", - "name": "[parameters('clusterName')]" - }, - "aks": { - "condition": "[parameters('deployCluster')]", - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "[format('{0}-aks', resourceGroup().name)]", - "properties": { - "expressionEvaluationOptions": { - "scope": "inner" - }, - "mode": "Incremental", - "parameters": { - "location": { - "value": "[parameters('location')]" - }, - "clusterName": { - "value": "[parameters('clusterName')]" - } - }, - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "languageVersion": "2.1-experimental", - "contentVersion": "1.0.0.0", - "metadata": { - "_EXPERIMENTAL_WARNING": "This template uses ARM features that are experimental. Experimental features should be enabled for testing purposes only, as there are no guarantees about the quality or stability of these features. Do not enable these settings for any production usage, or your production environment may be subject to breaking.", - "_EXPERIMENTAL_FEATURES_ENABLED": [ - "Extensibility" - ], - "_generator": { - "name": "bicep", - "version": "0.26.170.59819", - "templateHash": "187541002047123827" - } - }, - "parameters": { - "location": { - "type": "string", - "defaultValue": "[resourceGroup().location]" - }, - "clusterName": { - "type": "string", - "defaultValue": "aks1" - }, - "nodeCount": { - "type": "int", - "defaultValue": 1 - }, - "vmSize": { - "type": "string", - "defaultValue": "standard_d2s_v5" - }, - "kubernetesVersion": { - "type": "string", - "defaultValue": "1.29" - } - }, - "variables": { - "rand": "[substring(uniqueString(resourceGroup().id), 0, 6)]", - "roleDefinitionId": { - "Owner": "8e3af657-a8ff-443c-a75c-2fe8c4bcb635", - "Contributor": "b24988ac-6180-42a0-ab88-20f7382dd24c", - "Reader": "acdd72a7-3385-48ef-bd42-f606fba81ae7", - "AcrPull": "7f951dda-4ed3-4680-a7ca-43fe172d538d", - "StorageBlobDataContributor": "ba92f5b4-2d11-453d-a403-e96b0029c9fe", - "KubernetesServiceClusterUserRole": "4abbcc35-e782-43d8-92c5-2d3f1bd2253f" - }, - "roleAssignmentAcrDefinition": "AcrPull", - "roleAssignmentStorageAccountDefinition": "StorageBlobDataContributor" - }, - "resources": { - "managedIdentity": { - "type": "Microsoft.ManagedIdentity/userAssignedIdentities", - "apiVersion": "2018-11-30", - "name": "[format('{0}-identity', resourceGroup().name)]", - "location": "[parameters('location')]" - }, - "aks": { - "type": "Microsoft.ContainerService/managedClusters", - "apiVersion": "2021-05-01", - "name": "[parameters('clusterName')]", - "location": "[parameters('location')]", - "identity": { - "type": "UserAssigned", - "userAssignedIdentities": { - "[format('{0}', resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('{0}-identity', resourceGroup().name)))]": {} - } - }, - "properties": { - "kubernetesVersion": "[parameters('kubernetesVersion')]", - "dnsPrefix": "[parameters('clusterName')]", - "enableRBAC": true, - "agentPoolProfiles": [ - { - "name": "nodepool1", - "count": "[parameters('nodeCount')]", - "vmSize": "[parameters('vmSize')]", - "mode": "System" - } - ] - }, - "dependsOn": [ - "managedIdentity" - ] - }, - "containerRegistry": { - "type": "Microsoft.ContainerRegistry/registries", - "apiVersion": "2019-05-01", - "name": "[format('acr{0}', variables('rand'))]", - "location": "[parameters('location')]", - "sku": { - "name": "Standard" - }, - "properties": { - "adminUserEnabled": true - } - }, - "storageAccount": { - "type": "Microsoft.Storage/storageAccounts", - "apiVersion": "2021-02-01", - "name": "[format('storage{0}', variables('rand'))]", - "location": "[parameters('location')]", - "kind": "BlockBlobStorage", - "sku": { - "name": "Premium_LRS" - } - }, - "roleAssignmentAcr": { - "type": "Microsoft.Authorization/roleAssignments", - "apiVersion": "2020-08-01-preview", - "scope": "[format('Microsoft.ContainerRegistry/registries/{0}', format('acr{0}', variables('rand')))]", - "name": "[guid(resourceId('Microsoft.ContainerRegistry/registries', format('acr{0}', variables('rand'))), variables('roleAssignmentAcrDefinition'))]", - "properties": { - "roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', variables('roleDefinitionId')[variables('roleAssignmentAcrDefinition')])]", - "principalId": "[reference('aks').identityProfile.kubeletidentity.objectId]" - }, - "dependsOn": [ - "aks", - "containerRegistry" - ] - }, - "roleAssignmentStorageAccount": { - "type": "Microsoft.Authorization/roleAssignments", - "apiVersion": "2020-08-01-preview", - "scope": "[format('Microsoft.Storage/storageAccounts/{0}', format('storage{0}', variables('rand')))]", - "name": "[guid(resourceId('Microsoft.Storage/storageAccounts', format('storage{0}', variables('rand'))), variables('roleAssignmentStorageAccountDefinition'))]", - "properties": { - "roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', variables('roleDefinitionId')[variables('roleAssignmentStorageAccountDefinition')])]", - "principalId": "[reference('managedIdentity').principalId]" - }, - "dependsOn": [ - "aks", - "managedIdentity", - "storageAccount" - ] - } - } - } - } - }, - "app": { - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "[format('{0}-app', resourceGroup().name)]", - "properties": { - "expressionEvaluationOptions": { - "scope": "inner" - }, - "mode": "Incremental", - "parameters": { - "kubeConfig": { - "value": "[listClusterAdminCredential(resourceId('Microsoft.ContainerService/managedClusters', parameters('clusterName')), '2023-05-01').kubeconfigs[0].value]" - }, - "namespace": { - "value": "[parameters('namespace')]" - } - }, - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "languageVersion": "2.1-experimental", - "contentVersion": "1.0.0.0", - "metadata": { - "_EXPERIMENTAL_WARNING": "This template uses ARM features that are experimental. Experimental features should be enabled for testing purposes only, as there are no guarantees about the quality or stability of these features. Do not enable these settings for any production usage, or your production environment may be subject to breaking.", - "_EXPERIMENTAL_FEATURES_ENABLED": [ - "Extensibility" - ], - "_generator": { - "name": "bicep", - "version": "0.26.170.59819", - "templateHash": "1578784578022569032" - } - }, - "parameters": { - "kubeConfig": { - "type": "securestring" - }, - "namespace": { - "type": "string", - "defaultValue": "default" - } - }, - "imports": { - "kubernetes": { - "provider": "Kubernetes", - "version": "1.0.0", - "config": { - "namespace": "[parameters('namespace')]", - "kubeConfig": "[parameters('kubeConfig')]" - } - } - }, - "resources": { - "appsDeployment_azureVoteBack": { - "import": "kubernetes", - "type": "apps/Deployment@v1", - "properties": { - "metadata": { - "name": "azure-vote-back" - }, - "spec": { - "replicas": 1, - "selector": { - "matchLabels": { - "app": "azure-vote-back" - } - }, - "template": { - "metadata": { - "labels": { - "app": "azure-vote-back" - } - }, - "spec": { - "nodeSelector": { - "kubernetes.io/os": "linux" - }, - "containers": [ - { - "name": "azure-vote-back", - "image": "mcr.microsoft.com/oss/bitnami/redis:6.0.8", - "env": [ - { - "name": "ALLOW_EMPTY_PASSWORD", - "value": "yes" - } - ], - "resources": { - "requests": { - "cpu": "100m", - "memory": "128Mi" - }, - "limits": { - "cpu": "250m", - "memory": "256Mi" - } - }, - "ports": [ - { - "containerPort": 6379, - "name": "redis" - } - ] - } - ] - } - } - } - } - }, - "coreService_azureVoteBack": { - "import": "kubernetes", - "type": "core/Service@v1", - "properties": { - "metadata": { - "name": "azure-vote-back" - }, - "spec": { - "ports": [ - { - "port": 6379 - } - ], - "selector": { - "app": "azure-vote-back" - } - } - } - }, - "appsDeployment_azureVoteFront": { - "import": "kubernetes", - "type": "apps/Deployment@v1", - "properties": { - "metadata": { - "name": "azure-vote-front" - }, - "spec": { - "replicas": 1, - "selector": { - "matchLabels": { - "app": "azure-vote-front" - } - }, - "template": { - "metadata": { - "labels": { - "app": "azure-vote-front" - } - }, - "spec": { - "nodeSelector": { - "kubernetes.io/os": "linux" - }, - "containers": [ - { - "name": "azure-vote-front", - "image": "mcr.microsoft.com/azuredocs/azure-vote-front:v1", - "resources": { - "requests": { - "cpu": "100m", - "memory": "128Mi" - }, - "limits": { - "cpu": "250m", - "memory": "256Mi" - } - }, - "ports": [ - { - "containerPort": 80 - } - ], - "env": [ - { - "name": "REDIS", - "value": "azure-vote-back" - } - ] - } - ] - } - } - } - } - }, - "coreService_azureVoteFront": { - "import": "kubernetes", - "type": "core/Service@v1", - "properties": { - "metadata": { - "name": "azure-vote-front" - }, - "spec": { - "type": "LoadBalancer", - "ports": [ - { - "port": 80 - } - ], - "selector": { - "app": "azure-vote-front" - } - } - } - } - }, - "outputs": { - "frontendIp": { - "type": "string", - "value": "[reference('coreService_azureVoteFront').status.loadBalancer.ingress[0].ip]" - } - } - } - }, - "dependsOn": [ - "aks", - "aksCluster" - ] - } - }, - "outputs": { - "lbPublicIp": { - "type": "string", - "value": "[reference('app').outputs.frontendIp.value]" - } - } -} \ No newline at end of file diff --git a/cloud-native/aks-bicep-keda/01-aks/README.md b/cloud-native/aks-bicep-keda/01-aks/README.md deleted file mode 100644 index 3fb3e84..0000000 --- a/cloud-native/aks-bicep-keda/01-aks/README.md +++ /dev/null @@ -1,21 +0,0 @@ -# 01-aks/ - -This folder contains bicep templates and scripts to deploy Azure Kubernetes Service (AKS), Managed Identity, Container Registry and related resources. - -## Build ARM (main.json) from Bicep - -```bash -az bicep build --file main.bicep --outfile main.json -``` - -## Deploy ARM (main.json) via Azure Portal - -[Deploy to Azure](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure-Samples%2Fazure-opensource-labs%2Fmain%2Fcloud-native%2Faks-bicep-keda%2F01-aks%2Fmain.json) - -```bash -TEMPLATE_URL='https://raw.githubusercontent.com/Azure-Samples/azure-opensource-labs/main/cloud-native/aks-bicep-keda/01-aks/main.json' -OUTPUT_URL='https://portal.azure.com/#create/Microsoft.Template/uri/'$(printf "$TEMPLATE_URL" | jq -s -R -r @uri ) -echo $OUTPUT_URL - -# https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure-Samples%2Fazure-opensource-labs%2Fmain%2Fcloud-native%2Faks-bicep-keda%2F01-aks%2Fmain.json -``` diff --git a/cloud-native/aks-bicep-keda/01-aks/RESOURCES.md b/cloud-native/aks-bicep-keda/01-aks/RESOURCES.md deleted file mode 100644 index b226a09..0000000 --- a/cloud-native/aks-bicep-keda/01-aks/RESOURCES.md +++ /dev/null @@ -1,5 +0,0 @@ -# RESOURCES - -- Initial AKS templates borrowed from: . -- -- diff --git a/cloud-native/aks-bicep-keda/01-aks/aks.bicep b/cloud-native/aks-bicep-keda/01-aks/aks.bicep deleted file mode 100644 index 245999a..0000000 --- a/cloud-native/aks-bicep-keda/01-aks/aks.bicep +++ /dev/null @@ -1,139 +0,0 @@ -param location string = resourceGroup().location -param clusterName string = '' -param nodeCount int = 1 -param vmSize string = 'standard_d2s_v3' -param kubernetesVersion string = '1.29' - -var rand = substring(uniqueString(resourceGroup().id), 0, 6) -var clusterName_var = clusterName != '' ? clusterName : 'aks1' - -resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: '${resourceGroup().name}-identity' - location: location -} - -resource aks 'Microsoft.ContainerService/managedClusters@2021-05-01' = { - name: clusterName_var - location: location - identity: { - type: 'UserAssigned' - userAssignedIdentities: { - '${managedIdentity.id}': {} - } - } - properties: { - kubernetesVersion: kubernetesVersion - dnsPrefix: clusterName_var - enableRBAC: true - agentPoolProfiles: [ - { - name: 'pool0' - count: nodeCount - vmSize: vmSize - mode: 'System' - } - ] - } -} - -resource containerRegistry 'Microsoft.ContainerRegistry/registries@2019-05-01' = { - name: 'acr${rand}' - location: location - sku: { - name: 'Standard' - } - properties: { - adminUserEnabled: true - } -} - -resource storageAccount 'Microsoft.Storage/storageAccounts@2021-02-01' = { - name: 'storage${rand}' - location: location - kind: 'BlockBlobStorage' - sku: { - name: 'Premium_LRS' - } - properties: { - minimumTlsVersion: 'TLS1_2' - } -} - -resource serviceBus 'Microsoft.ServiceBus/namespaces@2021-06-01-preview' = { - name: 'servicebus${rand}' - location: location - sku: { - capacity: 1 - name: 'Standard' - tier: 'Standard' - } - properties: { - disableLocalAuth: false - } -} - -// via: https://docs.microsoft.com/en-us/azure/azure-resource-manager/bicep/bicep-functions-resource#subscriptionresourceid-example -var roleDefinitionId = { - Owner: '8e3af657-a8ff-443c-a75c-2fe8c4bcb635' - Contributor: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - Reader: 'acdd72a7-3385-48ef-bd42-f606fba81ae7' - AcrPull: '7f951dda-4ed3-4680-a7ca-43fe172d538d' - StorageBlobDataContributor: 'ba92f5b4-2d11-453d-a403-e96b0029c9fe' - ServiceBusDataOwner: '090c5cfd-751d-490a-894a-3ce6f1109419' - KubernetesServiceClusterUserRole: '4abbcc35-e782-43d8-92c5-2d3f1bd2253f' -} - -// https://github.com/Azure/bicep/discussions/3181 -var roleAssignmentAcrDefinition = 'AcrPull' -resource roleAssignmentAcr 'Microsoft.Authorization/roleAssignments@2020-08-01-preview' = { - name: guid(containerRegistry.id, roleAssignmentAcrDefinition) - scope: containerRegistry - properties: { - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleDefinitionId[roleAssignmentAcrDefinition]) - principalId: aks.properties.identityProfile.kubeletidentity.objectId - } -} - -var roleAssignmentStorageAccountDefinition = 'StorageBlobDataContributor' -resource roleAssignmentStorageAccount 'Microsoft.Authorization/roleAssignments@2020-08-01-preview' = { - name: guid(storageAccount.id, roleAssignmentStorageAccountDefinition) - scope: storageAccount - properties: { - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleDefinitionId[roleAssignmentStorageAccountDefinition]) - principalId: managedIdentity.properties.principalId - } - dependsOn: [ - aks - ] -} - -var roleAssignmentServiceBusDefinition = 'ServiceBusDataOwner' -resource roleAssignmentServiceBus 'Microsoft.Authorization/roleAssignments@2020-08-01-preview' = { - name: guid(serviceBus.id, roleAssignmentServiceBusDefinition) - scope: serviceBus - properties: { - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleDefinitionId[roleAssignmentServiceBusDefinition]) - principalId: managedIdentity.properties.principalId - } - dependsOn: [ - aks - ] -} - -resource managedIdentityDeploy 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: '${resourceGroup().name}-identity-deploy' - location: location -} - -var roleAssignmentDeploymentContributorDefinition = 'Contributor' -resource roleAssignmentDeploymentContributor 'Microsoft.Authorization/roleAssignments@2020-08-01-preview' = { - name: guid(managedIdentityDeploy.id, roleAssignmentDeploymentContributorDefinition) - scope: resourceGroup() - properties: { - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleDefinitionId[roleAssignmentDeploymentContributorDefinition]) - principalId: managedIdentityDeploy.properties.principalId - } - dependsOn: [ - aks - ] -} diff --git a/cloud-native/aks-bicep-keda/01-aks/deploy-aks.sh b/cloud-native/aks-bicep-keda/01-aks/deploy-aks.sh deleted file mode 100644 index 4fe8faa..0000000 --- a/cloud-native/aks-bicep-keda/01-aks/deploy-aks.sh +++ /dev/null @@ -1,6 +0,0 @@ -[[ -z "${RESOURCE_GROUP:-}" ]] && RESOURCE_GROUP='220600-keda' - -az deployment group create \ - --resource-group $RESOURCE_GROUP \ - --mode complete \ - --template-file ./aks.bicep diff --git a/cloud-native/aks-bicep-keda/01-aks/deploy-deploy-script.sh b/cloud-native/aks-bicep-keda/01-aks/deploy-deploy-script.sh deleted file mode 100644 index cdb1cee..0000000 --- a/cloud-native/aks-bicep-keda/01-aks/deploy-deploy-script.sh +++ /dev/null @@ -1,9 +0,0 @@ -[[ -z "${RESOURCE_GROUP:-}" ]] && RESOURCE_GROUP='220600-keda' -[[ -z "${LOCATION:-}" ]] && LOCATION='eastus' - -az deployment group create \ - --resource-group $RESOURCE_GROUP \ - --mode incremental \ - --template-file ./deploy-script.bicep \ - --parameters \ - scriptUri='https://raw.githubusercontent.com/Azure-Samples/azure-opensource-labs/main/cloud-native/aks-bicep-keda/01-aks/deploy-script-aks.sh' diff --git a/cloud-native/aks-bicep-keda/01-aks/deploy-empty.sh b/cloud-native/aks-bicep-keda/01-aks/deploy-empty.sh deleted file mode 100644 index dd3f0f3..0000000 --- a/cloud-native/aks-bicep-keda/01-aks/deploy-empty.sh +++ /dev/null @@ -1,6 +0,0 @@ -[[ -z "${RESOURCE_GROUP:-}" ]] && RESOURCE_GROUP='220600-keda' - -az deployment group create \ - --resource-group $RESOURCE_GROUP \ - --mode complete \ - --template-file ./empty.bicep diff --git a/cloud-native/aks-bicep-keda/01-aks/deploy-keyvault.sh b/cloud-native/aks-bicep-keda/01-aks/deploy-keyvault.sh deleted file mode 100644 index f1cf287..0000000 --- a/cloud-native/aks-bicep-keda/01-aks/deploy-keyvault.sh +++ /dev/null @@ -1,6 +0,0 @@ -[[ -z "${RESOURCE_GROUP:-}" ]] && RESOURCE_GROUP='220600-keda' - -az deployment group create \ - --resource-group $RESOURCE_GROUP \ - --mode incremental \ - --template-file ./keyvault.bicep diff --git a/cloud-native/aks-bicep-keda/01-aks/deploy-main.sh b/cloud-native/aks-bicep-keda/01-aks/deploy-main.sh deleted file mode 100644 index 3f07d69..0000000 --- a/cloud-native/aks-bicep-keda/01-aks/deploy-main.sh +++ /dev/null @@ -1,11 +0,0 @@ -[[ -z "${RESOURCE_GROUP:-}" ]] && RESOURCE_GROUP='220600-keda' -[[ -z "${LOCATION:-}" ]] && LOCATION='eastus' -[[ -z "${AKS_NAME:-}" ]] && AKS_NAME='aks1' - -az deployment sub create \ - --location $LOCATION \ - --template-file ./main.bicep \ - --parameters \ - deployScript='true' \ - scriptUri='https://raw.githubusercontent.com/Azure-Samples/azure-opensource-labs/main/cloud-native/aks-bicep-keda/01-aks/deploy-script-keda.sh' \ - resourceGroup=$RESOURCE_GROUP diff --git a/cloud-native/aks-bicep-keda/01-aks/deploy-script-aks.sh b/cloud-native/aks-bicep-keda/01-aks/deploy-script-aks.sh deleted file mode 100644 index 6ed1964..0000000 --- a/cloud-native/aks-bicep-keda/01-aks/deploy-script-aks.sh +++ /dev/null @@ -1,8 +0,0 @@ -[[ -z "${RESOURCE_GROUP:-}" ]] && RESOURCE_GROUP='220600-keda' -[[ -z "${AKS_NAME:-}" ]] && AKS_NAME='aks1' - -echo "az aks command invoke" -az aks command invoke \ - --resource-group $RESOURCE_GROUP \ - --name $AKS_NAME \ - --command 'kubectl run nginx --image=nginx' diff --git a/cloud-native/aks-bicep-keda/01-aks/deploy-script-keda.sh b/cloud-native/aks-bicep-keda/01-aks/deploy-script-keda.sh deleted file mode 100644 index 70cd14b..0000000 --- a/cloud-native/aks-bicep-keda/01-aks/deploy-script-keda.sh +++ /dev/null @@ -1,8 +0,0 @@ -[[ -z "${RESOURCE_GROUP:-}" ]] && RESOURCE_GROUP='220600-keda' -[[ -z "${AKS_NAME:-}" ]] && AKS_NAME='aks1' - -echo "az aks command invoke" -az aks command invoke \ - --resource-group $RESOURCE_GROUP \ - --name $AKS_NAME \ - --command 'kubectl apply -f https://github.com/kedacore/keda/releases/download/v2.7.1/keda-2.7.1.yaml' diff --git a/cloud-native/aks-bicep-keda/01-aks/deploy-script.bicep b/cloud-native/aks-bicep-keda/01-aks/deploy-script.bicep deleted file mode 100644 index df50a7e..0000000 --- a/cloud-native/aks-bicep-keda/01-aks/deploy-script.bicep +++ /dev/null @@ -1,65 +0,0 @@ -param location string = resourceGroup().location -param utcValue string = utcNow() -param resourceGroupName string = resourceGroup().name -// url to deploy-script-*.sh in repo -param scriptUri string = '' - -resource managedIdentityDeploy 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: '${resourceGroup().name}-identity-deploy' - location: location -} - -var roleDefinitionId = { - Owner: '8e3af657-a8ff-443c-a75c-2fe8c4bcb635' - Contributor: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - Reader: 'acdd72a7-3385-48ef-bd42-f606fba81ae7' -} - -// https://github.com/Azure/bicep/discussions/3181 -var roleAssignmentDeploymentContributorDefinition = 'Contributor' -resource roleAssignmentDeploymentContributor 'Microsoft.Authorization/roleAssignments@2020-08-01-preview' = { - name: guid(managedIdentityDeploy.id, roleAssignmentDeploymentContributorDefinition) - scope: resourceGroup() - properties: { - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleDefinitionId[roleAssignmentDeploymentContributorDefinition]) - principalId: managedIdentityDeploy.properties.principalId - } -} - -resource deploymentScript 'Microsoft.Resources/deploymentScripts@2020-10-01' = { - name: 'deploy-script' - location: location - kind: 'AzureCLI' - identity: { - type: 'UserAssigned' - userAssignedIdentities: { - '${managedIdentityDeploy.id}': {} - } - } - properties: { - environmentVariables: [ - { - name: 'RESOURCE_GROUP' - value: resourceGroupName - } - { - name: 'AKS_NAME' - value: 'aks1' - } - { - name: 'NAMESPACE' - value: 'keda-http' - } - ] - forceUpdateTag: utcValue - azCliVersion: '2.28.0' - timeout: 'PT30M' - //arguments: '\'211200-cloud-native\'' - //scriptContent: 'echo "arg1 is: $1"; value=$1; echo \'{}\' | jq --arg value "$value" \'.Result = $value\' | tee $AZ_SCRIPTS_OUTPUT_PATH' - primaryScriptUri: scriptUri - cleanupPreference: 'OnSuccess' - retentionInterval: 'P1D' - } -} - -//output result object = deploymentScript.properties.outputs diff --git a/cloud-native/aks-bicep-keda/01-aks/empty.bicep b/cloud-native/aks-bicep-keda/01-aks/empty.bicep deleted file mode 100644 index 3d70e64..0000000 --- a/cloud-native/aks-bicep-keda/01-aks/empty.bicep +++ /dev/null @@ -1 +0,0 @@ -output group string = resourceGroup().id diff --git a/cloud-native/aks-bicep-keda/01-aks/keyvault.bicep b/cloud-native/aks-bicep-keda/01-aks/keyvault.bicep deleted file mode 100644 index 5aa5280..0000000 --- a/cloud-native/aks-bicep-keda/01-aks/keyvault.bicep +++ /dev/null @@ -1,34 +0,0 @@ -param location string = resourceGroup().location - -var rand = substring(uniqueString(resourceGroup().id), 0, 6) - -resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: '${resourceGroup().name}-identity' - location: location -} - -resource keyVault 'Microsoft.KeyVault/vaults@2019-09-01' = { - name: 'keyvault${rand}' - location: location - properties: { - enabledForDeployment: true - enabledForTemplateDeployment: true - enabledForDiskEncryption: true - tenantId: subscription().tenantId - sku: { - name: 'standard' - family: 'A' - } - accessPolicies: [ - { - objectId: managedIdentity.properties.principalId - permissions: { - secrets: [ - 'all' - ] - } - tenantId: subscription().tenantId - } - ] - } -} diff --git a/cloud-native/aks-bicep-keda/01-aks/main.bicep b/cloud-native/aks-bicep-keda/01-aks/main.bicep deleted file mode 100644 index 2c9f2a8..0000000 --- a/cloud-native/aks-bicep-keda/01-aks/main.bicep +++ /dev/null @@ -1,31 +0,0 @@ -targetScope = 'subscription' - -param resourceGroup string = '220600-keda' -param location string = deployment().location -param deployScript bool = false -param scriptUri string = 'https://raw.githubusercontent.com/Azure-Samples/azure-opensource-labs/main/cloud-native/aks-bicep-keda/01-aks/deploy-script-keda.sh' - -resource rg 'Microsoft.Resources/resourceGroups@2021-04-01' = { - name: resourceGroup - location: location -} - -module aks './aks.bicep' = { - name: '${resourceGroup}-aks' - scope: rg - params: { - location: location - } -} - -module script './deploy-script.bicep' = if(deployScript) { - name: '${resourceGroup}-deployscript' - scope: rg - params: { - location: location - scriptUri: scriptUri - } - dependsOn: [ - aks - ] -} diff --git a/cloud-native/aks-bicep-keda/01-aks/main.json b/cloud-native/aks-bicep-keda/01-aks/main.json deleted file mode 100644 index dd9f658..0000000 --- a/cloud-native/aks-bicep-keda/01-aks/main.json +++ /dev/null @@ -1,365 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "16764085829659056086" - } - }, - "parameters": { - "resourceGroup": { - "type": "string", - "defaultValue": "220600-keda" - }, - "location": { - "type": "string", - "defaultValue": "[deployment().location]" - }, - "deployScript": { - "type": "bool", - "defaultValue": false - }, - "scriptUri": { - "type": "string", - "defaultValue": "https://raw.githubusercontent.com/Azure-Samples/azure-opensource-labs/main/cloud-native/aks-bicep-keda/01-aks/deploy-script-keda.sh" - } - }, - "resources": [ - { - "type": "Microsoft.Resources/resourceGroups", - "apiVersion": "2021-04-01", - "name": "[parameters('resourceGroup')]", - "location": "[parameters('location')]" - }, - { - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "[format('{0}-aks', parameters('resourceGroup'))]", - "resourceGroup": "[parameters('resourceGroup')]", - "properties": { - "expressionEvaluationOptions": { - "scope": "inner" - }, - "mode": "Incremental", - "parameters": { - "location": { - "value": "[parameters('location')]" - } - }, - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "7703729210362399507" - } - }, - "parameters": { - "location": { - "type": "string", - "defaultValue": "[resourceGroup().location]" - }, - "clusterName": { - "type": "string", - "defaultValue": "" - }, - "nodeCount": { - "type": "int", - "defaultValue": 1 - }, - "vmSize": { - "type": "string", - "defaultValue": "standard_d2s_v3" - }, - "kubernetesVersion": { - "type": "string", - "defaultValue": "1.29" - } - }, - "variables": { - "rand": "[substring(uniqueString(resourceGroup().id), 0, 6)]", - "clusterName_var": "[if(not(equals(parameters('clusterName'), '')), parameters('clusterName'), 'aks1')]", - "roleDefinitionId": { - "Owner": "8e3af657-a8ff-443c-a75c-2fe8c4bcb635", - "Contributor": "b24988ac-6180-42a0-ab88-20f7382dd24c", - "Reader": "acdd72a7-3385-48ef-bd42-f606fba81ae7", - "AcrPull": "7f951dda-4ed3-4680-a7ca-43fe172d538d", - "StorageBlobDataContributor": "ba92f5b4-2d11-453d-a403-e96b0029c9fe", - "ServiceBusDataOwner": "090c5cfd-751d-490a-894a-3ce6f1109419", - "KubernetesServiceClusterUserRole": "4abbcc35-e782-43d8-92c5-2d3f1bd2253f" - }, - "roleAssignmentAcrDefinition": "AcrPull", - "roleAssignmentStorageAccountDefinition": "StorageBlobDataContributor", - "roleAssignmentServiceBusDefinition": "ServiceBusDataOwner", - "roleAssignmentDeploymentContributorDefinition": "Contributor" - }, - "resources": [ - { - "type": "Microsoft.ManagedIdentity/userAssignedIdentities", - "apiVersion": "2018-11-30", - "name": "[format('{0}-identity', resourceGroup().name)]", - "location": "[parameters('location')]" - }, - { - "type": "Microsoft.ContainerService/managedClusters", - "apiVersion": "2021-05-01", - "name": "[variables('clusterName_var')]", - "location": "[parameters('location')]", - "identity": { - "type": "UserAssigned", - "userAssignedIdentities": { - "[format('{0}', resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('{0}-identity', resourceGroup().name)))]": {} - } - }, - "properties": { - "kubernetesVersion": "[parameters('kubernetesVersion')]", - "dnsPrefix": "[variables('clusterName_var')]", - "enableRBAC": true, - "agentPoolProfiles": [ - { - "name": "pool0", - "count": "[parameters('nodeCount')]", - "vmSize": "[parameters('vmSize')]", - "mode": "System" - } - ] - }, - "dependsOn": [ - "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('{0}-identity', resourceGroup().name))]" - ] - }, - { - "type": "Microsoft.ContainerRegistry/registries", - "apiVersion": "2019-05-01", - "name": "[format('acr{0}', variables('rand'))]", - "location": "[parameters('location')]", - "sku": { - "name": "Standard" - }, - "properties": { - "adminUserEnabled": true - } - }, - { - "type": "Microsoft.Storage/storageAccounts", - "apiVersion": "2021-02-01", - "name": "[format('storage{0}', variables('rand'))]", - "location": "[parameters('location')]", - "kind": "BlockBlobStorage", - "sku": { - "name": "Premium_LRS" - }, - "properties": { - "minimumTlsVersion": "TLS1_2" - } - }, - { - "type": "Microsoft.ServiceBus/namespaces", - "apiVersion": "2021-06-01-preview", - "name": "[format('servicebus{0}', variables('rand'))]", - "location": "[parameters('location')]", - "sku": { - "capacity": 1, - "name": "Standard", - "tier": "Standard" - }, - "properties": { - "disableLocalAuth": false - } - }, - { - "type": "Microsoft.Authorization/roleAssignments", - "apiVersion": "2020-08-01-preview", - "scope": "[format('Microsoft.ContainerRegistry/registries/{0}', format('acr{0}', variables('rand')))]", - "name": "[guid(resourceId('Microsoft.ContainerRegistry/registries', format('acr{0}', variables('rand'))), variables('roleAssignmentAcrDefinition'))]", - "properties": { - "roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', variables('roleDefinitionId')[variables('roleAssignmentAcrDefinition')])]", - "principalId": "[reference(resourceId('Microsoft.ContainerService/managedClusters', variables('clusterName_var')), '2021-05-01').identityProfile.kubeletidentity.objectId]" - }, - "dependsOn": [ - "[resourceId('Microsoft.ContainerService/managedClusters', variables('clusterName_var'))]", - "[resourceId('Microsoft.ContainerRegistry/registries', format('acr{0}', variables('rand')))]" - ] - }, - { - "type": "Microsoft.Authorization/roleAssignments", - "apiVersion": "2020-08-01-preview", - "scope": "[format('Microsoft.Storage/storageAccounts/{0}', format('storage{0}', variables('rand')))]", - "name": "[guid(resourceId('Microsoft.Storage/storageAccounts', format('storage{0}', variables('rand'))), variables('roleAssignmentStorageAccountDefinition'))]", - "properties": { - "roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', variables('roleDefinitionId')[variables('roleAssignmentStorageAccountDefinition')])]", - "principalId": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('{0}-identity', resourceGroup().name)), '2018-11-30').principalId]" - }, - "dependsOn": [ - "[resourceId('Microsoft.ContainerService/managedClusters', variables('clusterName_var'))]", - "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('{0}-identity', resourceGroup().name))]", - "[resourceId('Microsoft.Storage/storageAccounts', format('storage{0}', variables('rand')))]" - ] - }, - { - "type": "Microsoft.Authorization/roleAssignments", - "apiVersion": "2020-08-01-preview", - "scope": "[format('Microsoft.ServiceBus/namespaces/{0}', format('servicebus{0}', variables('rand')))]", - "name": "[guid(resourceId('Microsoft.ServiceBus/namespaces', format('servicebus{0}', variables('rand'))), variables('roleAssignmentServiceBusDefinition'))]", - "properties": { - "roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', variables('roleDefinitionId')[variables('roleAssignmentServiceBusDefinition')])]", - "principalId": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('{0}-identity', resourceGroup().name)), '2018-11-30').principalId]" - }, - "dependsOn": [ - "[resourceId('Microsoft.ContainerService/managedClusters', variables('clusterName_var'))]", - "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('{0}-identity', resourceGroup().name))]", - "[resourceId('Microsoft.ServiceBus/namespaces', format('servicebus{0}', variables('rand')))]" - ] - }, - { - "type": "Microsoft.ManagedIdentity/userAssignedIdentities", - "apiVersion": "2018-11-30", - "name": "[format('{0}-identity-deploy', resourceGroup().name)]", - "location": "[parameters('location')]" - }, - { - "type": "Microsoft.Authorization/roleAssignments", - "apiVersion": "2020-08-01-preview", - "name": "[guid(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('{0}-identity-deploy', resourceGroup().name)), variables('roleAssignmentDeploymentContributorDefinition'))]", - "properties": { - "roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', variables('roleDefinitionId')[variables('roleAssignmentDeploymentContributorDefinition')])]", - "principalId": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('{0}-identity-deploy', resourceGroup().name)), '2018-11-30').principalId]" - }, - "dependsOn": [ - "[resourceId('Microsoft.ContainerService/managedClusters', variables('clusterName_var'))]", - "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('{0}-identity-deploy', resourceGroup().name))]" - ] - } - ] - } - }, - "dependsOn": [ - "[subscriptionResourceId('Microsoft.Resources/resourceGroups', parameters('resourceGroup'))]" - ] - }, - { - "condition": "[parameters('deployScript')]", - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "[format('{0}-deployscript', parameters('resourceGroup'))]", - "resourceGroup": "[parameters('resourceGroup')]", - "properties": { - "expressionEvaluationOptions": { - "scope": "inner" - }, - "mode": "Incremental", - "parameters": { - "location": { - "value": "[parameters('location')]" - }, - "scriptUri": { - "value": "[parameters('scriptUri')]" - } - }, - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "9861108784878104103" - } - }, - "parameters": { - "location": { - "type": "string", - "defaultValue": "[resourceGroup().location]" - }, - "utcValue": { - "type": "string", - "defaultValue": "[utcNow()]" - }, - "resourceGroupName": { - "type": "string", - "defaultValue": "[resourceGroup().name]" - }, - "scriptUri": { - "type": "string", - "defaultValue": "" - } - }, - "variables": { - "roleDefinitionId": { - "Owner": "8e3af657-a8ff-443c-a75c-2fe8c4bcb635", - "Contributor": "b24988ac-6180-42a0-ab88-20f7382dd24c", - "Reader": "acdd72a7-3385-48ef-bd42-f606fba81ae7" - }, - "roleAssignmentDeploymentContributorDefinition": "Contributor" - }, - "resources": [ - { - "type": "Microsoft.ManagedIdentity/userAssignedIdentities", - "apiVersion": "2018-11-30", - "name": "[format('{0}-identity-deploy', resourceGroup().name)]", - "location": "[parameters('location')]" - }, - { - "type": "Microsoft.Authorization/roleAssignments", - "apiVersion": "2020-08-01-preview", - "name": "[guid(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('{0}-identity-deploy', resourceGroup().name)), variables('roleAssignmentDeploymentContributorDefinition'))]", - "properties": { - "roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', variables('roleDefinitionId')[variables('roleAssignmentDeploymentContributorDefinition')])]", - "principalId": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('{0}-identity-deploy', resourceGroup().name)), '2018-11-30').principalId]" - }, - "dependsOn": [ - "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('{0}-identity-deploy', resourceGroup().name))]" - ] - }, - { - "type": "Microsoft.Resources/deploymentScripts", - "apiVersion": "2020-10-01", - "name": "deploy-script", - "location": "[parameters('location')]", - "kind": "AzureCLI", - "identity": { - "type": "UserAssigned", - "userAssignedIdentities": { - "[format('{0}', resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('{0}-identity-deploy', resourceGroup().name)))]": {} - } - }, - "properties": { - "environmentVariables": [ - { - "name": "RESOURCE_GROUP", - "value": "[parameters('resourceGroupName')]" - }, - { - "name": "AKS_NAME", - "value": "aks1" - }, - { - "name": "NAMESPACE", - "value": "keda-http" - } - ], - "forceUpdateTag": "[parameters('utcValue')]", - "azCliVersion": "2.28.0", - "timeout": "PT30M", - "primaryScriptUri": "[parameters('scriptUri')]", - "cleanupPreference": "OnSuccess", - "retentionInterval": "P1D" - }, - "dependsOn": [ - "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('{0}-identity-deploy', resourceGroup().name))]" - ] - } - ] - } - }, - "dependsOn": [ - "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('resourceGroup')), 'Microsoft.Resources/deployments', format('{0}-aks', parameters('resourceGroup')))]", - "[subscriptionResourceId('Microsoft.Resources/resourceGroups', parameters('resourceGroup'))]" - ] - } - ] -} \ No newline at end of file diff --git a/cloud-native/aks-bicep-keda/02-keda/README.md b/cloud-native/aks-bicep-keda/02-keda/README.md deleted file mode 100644 index 3cbaa29..0000000 --- a/cloud-native/aks-bicep-keda/02-keda/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# 02-keda/ - -This folder contains a folder, `deploy/` with Kubernetes templates to deploy the [asw101/go-blob](https://github.com/asw101/go-blob) sample application to Kubernetes and KEDA. diff --git a/cloud-native/aks-bicep-keda/02-keda/deploy/deployment.yaml b/cloud-native/aks-bicep-keda/02-keda/deploy/deployment.yaml deleted file mode 100644 index ac2708a..0000000 --- a/cloud-native/aks-bicep-keda/02-keda/deploy/deployment.yaml +++ /dev/null @@ -1,34 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: go-blob - labels: - app.kubernetes.io/name: go-blob -spec: - selector: - matchLabels: - app.kubernetes.io/name: go-blob - template: - metadata: - labels: - app.kubernetes.io/name: go-blob - spec: - serviceAccountName: go-blob - containers: - - name: go-blob - image: "ghcr.io/asw101/go-blob:daemon" - imagePullPolicy: Always - env: - - name: AZURE_STORAGE_ACCOUNT_NAME - valueFrom: - secretKeyRef: - name: az-storage-account - key: AZURE_STORAGE_ACCOUNT_NAME - optional: true - - name: AZURE_STORAGE_PRIMARY_ACCOUNT_KEY - valueFrom: - secretKeyRef: - name: az-storage-account - key: AZURE_STORAGE_PRIMARY_ACCOUNT_KEY - optional: true - \ No newline at end of file diff --git a/cloud-native/aks-bicep-keda/02-keda/deploy/keda.yaml b/cloud-native/aks-bicep-keda/02-keda/deploy/keda.yaml deleted file mode 100644 index 64eb9e4..0000000 --- a/cloud-native/aks-bicep-keda/02-keda/deploy/keda.yaml +++ /dev/null @@ -1,45 +0,0 @@ -apiVersion: keda.sh/v1alpha1 -kind: TriggerAuthentication -metadata: - name: azure-blob-auth - namespace: go-blob -spec: - secretTargetRef: - - parameter: connection - name: az-storage-account - key: AZURE_STORAGE_CONNECTION_STRING ---- -apiVersion: keda.sh/v1alpha1 -kind: ScaledObject -metadata: - name: go-blob-scaledobject - namespace: go-blob -spec: - scaleTargetRef: - name: go-blob - pollingInterval: 10 - cooldownPeriod: 10 - idleReplicaCount: 0 - minReplicaCount: 0 - maxReplicaCount: 5 - advanced: - restoreToOriginalReplicaCount: true - horizontalPodAutoscalerConfig: - behavior: - scaleDown: - stabilizationWindowSeconds: 20 - policies: - - type: Percent - value: 100 - periodSeconds: 10 - triggers: - - type: azure-blob - metadata: - blobContainerName: mycontainer - # Optional - blobCount: "1" # default 5 - blobPrefix: "" - blobDelimiter: "/" - cloud: AzurePublicCloud - authenticationRef: - name: azure-blob-auth diff --git a/cloud-native/aks-bicep-keda/02-keda/deploy/kustomization.yaml b/cloud-native/aks-bicep-keda/02-keda/deploy/kustomization.yaml deleted file mode 100644 index a978212..0000000 --- a/cloud-native/aks-bicep-keda/02-keda/deploy/kustomization.yaml +++ /dev/null @@ -1,10 +0,0 @@ -resources: -- namespace.yaml -- deployment.yaml -- serviceaccount.yaml -- keda.yaml - -commonLabels: - app.kubernetes.io/name: go-blob - -namespace: go-blob diff --git a/cloud-native/aks-bicep-keda/02-keda/deploy/namespace.yaml b/cloud-native/aks-bicep-keda/02-keda/deploy/namespace.yaml deleted file mode 100644 index 170b965..0000000 --- a/cloud-native/aks-bicep-keda/02-keda/deploy/namespace.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - name: go-blob - \ No newline at end of file diff --git a/cloud-native/aks-bicep-keda/02-keda/deploy/serviceaccount.yaml b/cloud-native/aks-bicep-keda/02-keda/deploy/serviceaccount.yaml deleted file mode 100644 index 923f9c5..0000000 --- a/cloud-native/aks-bicep-keda/02-keda/deploy/serviceaccount.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: v1 -kind: ServiceAccount -metadata: - name: go-blob - labels: - app.kubernetes.io/name: go-blob - \ No newline at end of file diff --git a/cloud-native/aks-bicep-keda/03-keda-http/README.md b/cloud-native/aks-bicep-keda/03-keda-http/README.md deleted file mode 100644 index c2c673b..0000000 --- a/cloud-native/aks-bicep-keda/03-keda-http/README.md +++ /dev/null @@ -1,67 +0,0 @@ -# KEDA HTTP Add-on - -Install KEDA (via [YAML files](https://keda.sh/docs/2.7/deploy/#yaml)). You can also use [Helm](https://keda.sh/docs/2.7/deploy/#helm) or [Operator Hub](https://keda.sh/docs/2.7/deploy/#operatorhub). It may have been deployed to your cluster already. - -```bash -kubectl apply -f https://github.com/kedacore/keda/releases/download/v2.7.1/keda-2.7.1.yaml -``` - -Install KEDA HTTP Add-on (via [Helm](https://github.com/kedacore/http-add-on/blob/main/docs/install.md#install-via-helm-chart)). It will be installed in `keda-http` namespace. - -```bash -helm upgrade --install http-add-on keda-add-ons-http \ - --repo https://kedacore.github.io/charts \ - --create-namespace \ - --namespace keda-http -``` - -Install the NGINX Ingress Controller (via [Helm](https://kubernetes.github.io/ingress-nginx/deploy/#quick-start)). - -```bash -helm upgrade --install ingress-nginx ingress-nginx \ - --repo https://kubernetes.github.io/ingress-nginx \ - --create-namespace \ - --namespace ingress-nginx -``` - -Get the IP address of the Ingress Controller. - -```bash -SERVICE_IP=$(kubectl get service -n ingress-nginx ingress-nginx-controller --output jsonpath='{.status.loadBalancer.ingress[0].ip}') - -echo $SERVICE_IP -``` - -Clone the [asw101/go-hello](https://github.com/asw101/go-hello) repo locally. - -```bash -git clone https://github.com/asw101/go-hello.git -``` - -Open `go-hello/deploy/kustomization.yaml` and replace the `0.0.0.0` in `hello.0.0.0.0.nip.io` in with the IP address from `$SERVICE_IP` above. - -Deploy the manifests in the [go-hello/deploy](https://github.com/asw101/go-hello/tree/main/deploy) folder using kubectl and [kustomization](https://kubernetes.io/docs/tasks/manage-kubernetes-objects/kustomization/). - -```bash -kubectl apply -k go-hello/deploy -``` - -Output URL and open it in a web browser. - -```bash -echo "http://hello.${SERVICE_IP}.nip.io" -``` - -curl the `/echo` endpoint. - -```bash -curl "http://hello.${SERVICE_IP}.nip.io/echo" -``` - -If you would like to see the pods scale up and down, and/or tail the logs, in real-time, open [k9s](https://github.com/derailed/k9s#installation) in another terminal window and view the `hello` deployment. - -Use [hey](https://github.com/rakyll/hey) to generate load against `/wait?ms=450`, which will wait 450ms before responding. This command will use 250 concurrent workers to send a total of 10,000 requests. - -```bash -hey -c 250 -n 10000 "http://hello.${SERVICE_IP}.nip.io/wait?ms=450" -``` diff --git a/cloud-native/aks-bicep-keda/README.md b/cloud-native/aks-bicep-keda/README.md deleted file mode 100644 index 51608c0..0000000 --- a/cloud-native/aks-bicep-keda/README.md +++ /dev/null @@ -1,94 +0,0 @@ -# Explore KEDA (Kubernetes Event-driven Autoscaling) and the KEDA HTTP Add-on with Azure Kubernetes Service (AKS) and Bicep - -In this lab you will deploy an Azure Kubernetes Service (AKS) cluster and other Azure services (Container Registry, Managed Identity, Storage Account, Service Bus, Key Vault), the open source KEDA (Kubernetes Event-driven Autoscaling) project with [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli) and [Bicep](https://docs.microsoft.com/en-us/azure/azure-resource-manager/bicep/overview). - -## Requirements - -- An **Azure Subscription** (e.g. [Free](https://aka.ms/azure-free-account) or [Student](https://aka.ms/azure-student-account) account) -- The [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli) -- Bash shell (e.g. macOS, Linux, [Windows Subsystem for Linux (WSL)](https://docs.microsoft.com/en-us/windows/wsl/about), [Multipass](https://multipass.run/), [Azure Cloud Shell](https://docs.microsoft.com/en-us/azure/cloud-shell/quickstart), [GitHub Codespaces](https://github.com/features/codespaces), etc) -- A [GitHub Account](https://github.com) - -## 1. Setup - -Use the [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli) and [Bicep](https://docs.microsoft.com/en-us/azure/azure-resource-manager/bicep/overview) templates to deploy the infrastructure for your application. - -Login to the Azure CLI. - -```bash -az login -``` - -Install kubectl using the Azure CLI, if required. - -```bash -az aks install-cli -``` - -Deploy the Bicep template for your Azure Kubernetes Service (AKS) cluster. - -```bash -cd cloud-native/aks-bicep-keda/01-aks -bash deploy-main.sh -``` - -## 2. KEDA - -Set environment variables. - -```bash -RESOURCE_GROUP='220600-keda' -AKS_NAME='aks1' -``` - -Invoke kubectl command on AKS cluster. - -```bash -cd ../02-keda/deploy - -az aks command invoke \ - --resource-group $RESOURCE_GROUP \ - --name $AKS_NAME \ - --file . \ - --command 'kubectl apply -k .' -``` - -Authenticate local kubectl. - -```bash -az aks get-credentials \ - --resource-group $RESOURCE_GROUP \ - --name $AKS_NAME \ - --overwrite-existing -``` - -Create secrets for Azure Blob Storage. - -```bash -export AZURE_STORAGE_ACCOUNT_NAME="$(az storage account list -g $RESOURCE_GROUP --out tsv --query '[0].name')" - -AZURE_STORAGE_PRIMARY_ACCOUNT_KEY=$(az storage account keys list \ - --account-name "$AZURE_STORAGE_ACCOUNT_NAME" \ - --out tsv \ - --query '[0].value') - -AZURE_STORAGE_CONNECTION_STRING=$(az storage account show-connection-string \ - -g $RESOURCE_GROUP \ - --name "$AZURE_STORAGE_ACCOUNT_NAME" \ - --out tsv \ - --query 'connectionString') - -kubectl delete -k . - -kubectl apply -k . - -kubectl create secret generic az-storage-account \ - --namespace go-blob \ - --from-literal=AZURE_STORAGE_ACCOUNT_NAME="${AZURE_STORAGE_ACCOUNT_NAME}" \ - --from-literal=AZURE_STORAGE_PRIMARY_ACCOUNT_KEY="${AZURE_STORAGE_PRIMARY_ACCOUNT_KEY}" \ - --from-literal=AZURE_STORAGE_CONNECTION_STRING="${AZURE_STORAGE_CONNECTION_STRING}" -``` - -## 3. KEDA HTTP Add-on - -Follow the steps in [03-keda-http](./03-keda-http/) to install the [HTTP Add-on](https://github.com/kedacore/http-add-on) and deploy the [asw101/go-hello](https://github.com/asw101/go-hello) application to it. diff --git a/cloud-native/aks-bicep/01-aks/README.md b/cloud-native/aks-bicep/01-aks/README.md deleted file mode 100644 index 08d3038..0000000 --- a/cloud-native/aks-bicep/01-aks/README.md +++ /dev/null @@ -1,21 +0,0 @@ -# 01-aks/ - -This folder contains bicep templates and scripts to deploy Azure Kubernetes Service (AKS), Managed Identity, Container Registry and related resources. - -## Build ARM (main.json) from Bicep - -```bash -az bicep build --file main.bicep --outfile main.json -``` - -## Deploy ARM (main.json) via Azure Portal - -[Deploy to Azure](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure-Samples%2Fazure-opensource-labs%2Faks-bicep%2Fcloud-native%2Faks-bicep%2F01-aks%2Fmain.json) - -```bash -TEMPLATE_URL='https://raw.githubusercontent.com/Azure-Samples/azure-opensource-labs/aks-bicep/cloud-native/aks-bicep/01-aks/main.json' -OUTPUT_URL='https://portal.azure.com/#create/Microsoft.Template/uri/'$(printf "$TEMPLATE_URL" | jq -s -R -r @uri ) -echo $OUTPUT_URL - -# https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure-Samples%2Fazure-opensource-labs%2Faks-bicep%2Fcloud-native%2Faks-bicep%2F01-aks%2Fmain.json -``` diff --git a/cloud-native/aks-bicep/01-aks/RESOURCES.md b/cloud-native/aks-bicep/01-aks/RESOURCES.md deleted file mode 100644 index b226a09..0000000 --- a/cloud-native/aks-bicep/01-aks/RESOURCES.md +++ /dev/null @@ -1,5 +0,0 @@ -# RESOURCES - -- Initial AKS templates borrowed from: . -- -- diff --git a/cloud-native/aks-bicep/01-aks/aks.bicep b/cloud-native/aks-bicep/01-aks/aks.bicep deleted file mode 100644 index 245999a..0000000 --- a/cloud-native/aks-bicep/01-aks/aks.bicep +++ /dev/null @@ -1,139 +0,0 @@ -param location string = resourceGroup().location -param clusterName string = '' -param nodeCount int = 1 -param vmSize string = 'standard_d2s_v3' -param kubernetesVersion string = '1.29' - -var rand = substring(uniqueString(resourceGroup().id), 0, 6) -var clusterName_var = clusterName != '' ? clusterName : 'aks1' - -resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: '${resourceGroup().name}-identity' - location: location -} - -resource aks 'Microsoft.ContainerService/managedClusters@2021-05-01' = { - name: clusterName_var - location: location - identity: { - type: 'UserAssigned' - userAssignedIdentities: { - '${managedIdentity.id}': {} - } - } - properties: { - kubernetesVersion: kubernetesVersion - dnsPrefix: clusterName_var - enableRBAC: true - agentPoolProfiles: [ - { - name: 'pool0' - count: nodeCount - vmSize: vmSize - mode: 'System' - } - ] - } -} - -resource containerRegistry 'Microsoft.ContainerRegistry/registries@2019-05-01' = { - name: 'acr${rand}' - location: location - sku: { - name: 'Standard' - } - properties: { - adminUserEnabled: true - } -} - -resource storageAccount 'Microsoft.Storage/storageAccounts@2021-02-01' = { - name: 'storage${rand}' - location: location - kind: 'BlockBlobStorage' - sku: { - name: 'Premium_LRS' - } - properties: { - minimumTlsVersion: 'TLS1_2' - } -} - -resource serviceBus 'Microsoft.ServiceBus/namespaces@2021-06-01-preview' = { - name: 'servicebus${rand}' - location: location - sku: { - capacity: 1 - name: 'Standard' - tier: 'Standard' - } - properties: { - disableLocalAuth: false - } -} - -// via: https://docs.microsoft.com/en-us/azure/azure-resource-manager/bicep/bicep-functions-resource#subscriptionresourceid-example -var roleDefinitionId = { - Owner: '8e3af657-a8ff-443c-a75c-2fe8c4bcb635' - Contributor: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - Reader: 'acdd72a7-3385-48ef-bd42-f606fba81ae7' - AcrPull: '7f951dda-4ed3-4680-a7ca-43fe172d538d' - StorageBlobDataContributor: 'ba92f5b4-2d11-453d-a403-e96b0029c9fe' - ServiceBusDataOwner: '090c5cfd-751d-490a-894a-3ce6f1109419' - KubernetesServiceClusterUserRole: '4abbcc35-e782-43d8-92c5-2d3f1bd2253f' -} - -// https://github.com/Azure/bicep/discussions/3181 -var roleAssignmentAcrDefinition = 'AcrPull' -resource roleAssignmentAcr 'Microsoft.Authorization/roleAssignments@2020-08-01-preview' = { - name: guid(containerRegistry.id, roleAssignmentAcrDefinition) - scope: containerRegistry - properties: { - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleDefinitionId[roleAssignmentAcrDefinition]) - principalId: aks.properties.identityProfile.kubeletidentity.objectId - } -} - -var roleAssignmentStorageAccountDefinition = 'StorageBlobDataContributor' -resource roleAssignmentStorageAccount 'Microsoft.Authorization/roleAssignments@2020-08-01-preview' = { - name: guid(storageAccount.id, roleAssignmentStorageAccountDefinition) - scope: storageAccount - properties: { - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleDefinitionId[roleAssignmentStorageAccountDefinition]) - principalId: managedIdentity.properties.principalId - } - dependsOn: [ - aks - ] -} - -var roleAssignmentServiceBusDefinition = 'ServiceBusDataOwner' -resource roleAssignmentServiceBus 'Microsoft.Authorization/roleAssignments@2020-08-01-preview' = { - name: guid(serviceBus.id, roleAssignmentServiceBusDefinition) - scope: serviceBus - properties: { - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleDefinitionId[roleAssignmentServiceBusDefinition]) - principalId: managedIdentity.properties.principalId - } - dependsOn: [ - aks - ] -} - -resource managedIdentityDeploy 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: '${resourceGroup().name}-identity-deploy' - location: location -} - -var roleAssignmentDeploymentContributorDefinition = 'Contributor' -resource roleAssignmentDeploymentContributor 'Microsoft.Authorization/roleAssignments@2020-08-01-preview' = { - name: guid(managedIdentityDeploy.id, roleAssignmentDeploymentContributorDefinition) - scope: resourceGroup() - properties: { - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleDefinitionId[roleAssignmentDeploymentContributorDefinition]) - principalId: managedIdentityDeploy.properties.principalId - } - dependsOn: [ - aks - ] -} diff --git a/cloud-native/aks-bicep/01-aks/deploy-aks.sh b/cloud-native/aks-bicep/01-aks/deploy-aks.sh deleted file mode 100644 index 4fe8faa..0000000 --- a/cloud-native/aks-bicep/01-aks/deploy-aks.sh +++ /dev/null @@ -1,6 +0,0 @@ -[[ -z "${RESOURCE_GROUP:-}" ]] && RESOURCE_GROUP='220600-keda' - -az deployment group create \ - --resource-group $RESOURCE_GROUP \ - --mode complete \ - --template-file ./aks.bicep diff --git a/cloud-native/aks-bicep/01-aks/deploy-deploy-script.sh b/cloud-native/aks-bicep/01-aks/deploy-deploy-script.sh deleted file mode 100644 index ddea718..0000000 --- a/cloud-native/aks-bicep/01-aks/deploy-deploy-script.sh +++ /dev/null @@ -1,9 +0,0 @@ -[[ -z "${RESOURCE_GROUP:-}" ]] && RESOURCE_GROUP='220600-keda' -[[ -z "${LOCATION:-}" ]] && LOCATION='eastus' - -az deployment group create \ - --resource-group $RESOURCE_GROUP \ - --mode incremental \ - --template-file ./deploy-script.bicep \ - --parameters \ - scriptUri='https://raw.githubusercontent.com/Azure-Samples/azure-opensource-labs/aks-bicep/cloud-native/aks-bicep/01-aks/deploy-script-aks.sh' diff --git a/cloud-native/aks-bicep/01-aks/deploy-empty.sh b/cloud-native/aks-bicep/01-aks/deploy-empty.sh deleted file mode 100644 index dd3f0f3..0000000 --- a/cloud-native/aks-bicep/01-aks/deploy-empty.sh +++ /dev/null @@ -1,6 +0,0 @@ -[[ -z "${RESOURCE_GROUP:-}" ]] && RESOURCE_GROUP='220600-keda' - -az deployment group create \ - --resource-group $RESOURCE_GROUP \ - --mode complete \ - --template-file ./empty.bicep diff --git a/cloud-native/aks-bicep/01-aks/deploy-keyvault.sh b/cloud-native/aks-bicep/01-aks/deploy-keyvault.sh deleted file mode 100644 index f1cf287..0000000 --- a/cloud-native/aks-bicep/01-aks/deploy-keyvault.sh +++ /dev/null @@ -1,6 +0,0 @@ -[[ -z "${RESOURCE_GROUP:-}" ]] && RESOURCE_GROUP='220600-keda' - -az deployment group create \ - --resource-group $RESOURCE_GROUP \ - --mode incremental \ - --template-file ./keyvault.bicep diff --git a/cloud-native/aks-bicep/01-aks/deploy-main.sh b/cloud-native/aks-bicep/01-aks/deploy-main.sh deleted file mode 100644 index 053a941..0000000 --- a/cloud-native/aks-bicep/01-aks/deploy-main.sh +++ /dev/null @@ -1,11 +0,0 @@ -[[ -z "${RESOURCE_GROUP:-}" ]] && RESOURCE_GROUP='220600-keda' -[[ -z "${LOCATION:-}" ]] && LOCATION='eastus' -[[ -z "${AKS_NAME:-}" ]] && AKS_NAME='aks1' - -az deployment sub create \ - --location $LOCATION \ - --template-file ./main.bicep \ - --parameters \ - deployScript='true' \ - scriptUri='https://raw.githubusercontent.com/Azure-Samples/azure-opensource-labs/aks-bicep/cloud-native/aks-bicep/01-aks/deploy-script-keda.sh' \ - resourceGroup=$RESOURCE_GROUP diff --git a/cloud-native/aks-bicep/01-aks/deploy-script-aks.sh b/cloud-native/aks-bicep/01-aks/deploy-script-aks.sh deleted file mode 100644 index 6ed1964..0000000 --- a/cloud-native/aks-bicep/01-aks/deploy-script-aks.sh +++ /dev/null @@ -1,8 +0,0 @@ -[[ -z "${RESOURCE_GROUP:-}" ]] && RESOURCE_GROUP='220600-keda' -[[ -z "${AKS_NAME:-}" ]] && AKS_NAME='aks1' - -echo "az aks command invoke" -az aks command invoke \ - --resource-group $RESOURCE_GROUP \ - --name $AKS_NAME \ - --command 'kubectl run nginx --image=nginx' diff --git a/cloud-native/aks-bicep/01-aks/deploy-script-keda.sh b/cloud-native/aks-bicep/01-aks/deploy-script-keda.sh deleted file mode 100644 index 70cd14b..0000000 --- a/cloud-native/aks-bicep/01-aks/deploy-script-keda.sh +++ /dev/null @@ -1,8 +0,0 @@ -[[ -z "${RESOURCE_GROUP:-}" ]] && RESOURCE_GROUP='220600-keda' -[[ -z "${AKS_NAME:-}" ]] && AKS_NAME='aks1' - -echo "az aks command invoke" -az aks command invoke \ - --resource-group $RESOURCE_GROUP \ - --name $AKS_NAME \ - --command 'kubectl apply -f https://github.com/kedacore/keda/releases/download/v2.7.1/keda-2.7.1.yaml' diff --git a/cloud-native/aks-bicep/01-aks/deploy-script.bicep b/cloud-native/aks-bicep/01-aks/deploy-script.bicep deleted file mode 100644 index df50a7e..0000000 --- a/cloud-native/aks-bicep/01-aks/deploy-script.bicep +++ /dev/null @@ -1,65 +0,0 @@ -param location string = resourceGroup().location -param utcValue string = utcNow() -param resourceGroupName string = resourceGroup().name -// url to deploy-script-*.sh in repo -param scriptUri string = '' - -resource managedIdentityDeploy 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: '${resourceGroup().name}-identity-deploy' - location: location -} - -var roleDefinitionId = { - Owner: '8e3af657-a8ff-443c-a75c-2fe8c4bcb635' - Contributor: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - Reader: 'acdd72a7-3385-48ef-bd42-f606fba81ae7' -} - -// https://github.com/Azure/bicep/discussions/3181 -var roleAssignmentDeploymentContributorDefinition = 'Contributor' -resource roleAssignmentDeploymentContributor 'Microsoft.Authorization/roleAssignments@2020-08-01-preview' = { - name: guid(managedIdentityDeploy.id, roleAssignmentDeploymentContributorDefinition) - scope: resourceGroup() - properties: { - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleDefinitionId[roleAssignmentDeploymentContributorDefinition]) - principalId: managedIdentityDeploy.properties.principalId - } -} - -resource deploymentScript 'Microsoft.Resources/deploymentScripts@2020-10-01' = { - name: 'deploy-script' - location: location - kind: 'AzureCLI' - identity: { - type: 'UserAssigned' - userAssignedIdentities: { - '${managedIdentityDeploy.id}': {} - } - } - properties: { - environmentVariables: [ - { - name: 'RESOURCE_GROUP' - value: resourceGroupName - } - { - name: 'AKS_NAME' - value: 'aks1' - } - { - name: 'NAMESPACE' - value: 'keda-http' - } - ] - forceUpdateTag: utcValue - azCliVersion: '2.28.0' - timeout: 'PT30M' - //arguments: '\'211200-cloud-native\'' - //scriptContent: 'echo "arg1 is: $1"; value=$1; echo \'{}\' | jq --arg value "$value" \'.Result = $value\' | tee $AZ_SCRIPTS_OUTPUT_PATH' - primaryScriptUri: scriptUri - cleanupPreference: 'OnSuccess' - retentionInterval: 'P1D' - } -} - -//output result object = deploymentScript.properties.outputs diff --git a/cloud-native/aks-bicep/01-aks/empty.bicep b/cloud-native/aks-bicep/01-aks/empty.bicep deleted file mode 100644 index 3d70e64..0000000 --- a/cloud-native/aks-bicep/01-aks/empty.bicep +++ /dev/null @@ -1 +0,0 @@ -output group string = resourceGroup().id diff --git a/cloud-native/aks-bicep/01-aks/keyvault.bicep b/cloud-native/aks-bicep/01-aks/keyvault.bicep deleted file mode 100644 index 5aa5280..0000000 --- a/cloud-native/aks-bicep/01-aks/keyvault.bicep +++ /dev/null @@ -1,34 +0,0 @@ -param location string = resourceGroup().location - -var rand = substring(uniqueString(resourceGroup().id), 0, 6) - -resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: '${resourceGroup().name}-identity' - location: location -} - -resource keyVault 'Microsoft.KeyVault/vaults@2019-09-01' = { - name: 'keyvault${rand}' - location: location - properties: { - enabledForDeployment: true - enabledForTemplateDeployment: true - enabledForDiskEncryption: true - tenantId: subscription().tenantId - sku: { - name: 'standard' - family: 'A' - } - accessPolicies: [ - { - objectId: managedIdentity.properties.principalId - permissions: { - secrets: [ - 'all' - ] - } - tenantId: subscription().tenantId - } - ] - } -} diff --git a/cloud-native/aks-bicep/01-aks/main.bicep b/cloud-native/aks-bicep/01-aks/main.bicep deleted file mode 100644 index c384033..0000000 --- a/cloud-native/aks-bicep/01-aks/main.bicep +++ /dev/null @@ -1,31 +0,0 @@ -targetScope = 'subscription' - -param resourceGroup string = '220600-keda' -param location string = deployment().location -param deployScript bool = false -param scriptUri string = 'https://raw.githubusercontent.com/Azure-Samples/azure-opensource-labs/aks-bicep/cloud-native/aks-bicep/01-aks/deploy-script-keda.sh' - -resource rg 'Microsoft.Resources/resourceGroups@2021-04-01' = { - name: resourceGroup - location: location -} - -module aks './aks.bicep' = { - name: '${resourceGroup}-aks' - scope: rg - params: { - location: location - } -} - -module script './deploy-script.bicep' = if(deployScript) { - name: '${resourceGroup}-deployscript' - scope: rg - params: { - location: location - scriptUri: scriptUri - } - dependsOn: [ - aks - ] -} diff --git a/cloud-native/aks-bicep/01-aks/main.json b/cloud-native/aks-bicep/01-aks/main.json deleted file mode 100644 index 656d80f..0000000 --- a/cloud-native/aks-bicep/01-aks/main.json +++ /dev/null @@ -1,365 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "9190321452261239824" - } - }, - "parameters": { - "resourceGroup": { - "type": "string", - "defaultValue": "220600-keda" - }, - "location": { - "type": "string", - "defaultValue": "[deployment().location]" - }, - "deployScript": { - "type": "bool", - "defaultValue": false - }, - "scriptUri": { - "type": "string", - "defaultValue": "https://raw.githubusercontent.com/Azure-Samples/azure-opensource-labs/aks-bicep/cloud-native/aks-bicep/01-aks/deploy-script-keda.sh" - } - }, - "resources": [ - { - "type": "Microsoft.Resources/resourceGroups", - "apiVersion": "2021-04-01", - "name": "[parameters('resourceGroup')]", - "location": "[parameters('location')]" - }, - { - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "[format('{0}-aks', parameters('resourceGroup'))]", - "resourceGroup": "[parameters('resourceGroup')]", - "properties": { - "expressionEvaluationOptions": { - "scope": "inner" - }, - "mode": "Incremental", - "parameters": { - "location": { - "value": "[parameters('location')]" - } - }, - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "7703729210362399507" - } - }, - "parameters": { - "location": { - "type": "string", - "defaultValue": "[resourceGroup().location]" - }, - "clusterName": { - "type": "string", - "defaultValue": "" - }, - "nodeCount": { - "type": "int", - "defaultValue": 1 - }, - "vmSize": { - "type": "string", - "defaultValue": "standard_d2s_v3" - }, - "kubernetesVersion": { - "type": "string", - "defaultValue": "1.29" - } - }, - "variables": { - "rand": "[substring(uniqueString(resourceGroup().id), 0, 6)]", - "clusterName_var": "[if(not(equals(parameters('clusterName'), '')), parameters('clusterName'), 'aks1')]", - "roleDefinitionId": { - "Owner": "8e3af657-a8ff-443c-a75c-2fe8c4bcb635", - "Contributor": "b24988ac-6180-42a0-ab88-20f7382dd24c", - "Reader": "acdd72a7-3385-48ef-bd42-f606fba81ae7", - "AcrPull": "7f951dda-4ed3-4680-a7ca-43fe172d538d", - "StorageBlobDataContributor": "ba92f5b4-2d11-453d-a403-e96b0029c9fe", - "ServiceBusDataOwner": "090c5cfd-751d-490a-894a-3ce6f1109419", - "KubernetesServiceClusterUserRole": "4abbcc35-e782-43d8-92c5-2d3f1bd2253f" - }, - "roleAssignmentAcrDefinition": "AcrPull", - "roleAssignmentStorageAccountDefinition": "StorageBlobDataContributor", - "roleAssignmentServiceBusDefinition": "ServiceBusDataOwner", - "roleAssignmentDeploymentContributorDefinition": "Contributor" - }, - "resources": [ - { - "type": "Microsoft.ManagedIdentity/userAssignedIdentities", - "apiVersion": "2018-11-30", - "name": "[format('{0}-identity', resourceGroup().name)]", - "location": "[parameters('location')]" - }, - { - "type": "Microsoft.ContainerService/managedClusters", - "apiVersion": "2021-05-01", - "name": "[variables('clusterName_var')]", - "location": "[parameters('location')]", - "identity": { - "type": "UserAssigned", - "userAssignedIdentities": { - "[format('{0}', resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('{0}-identity', resourceGroup().name)))]": {} - } - }, - "properties": { - "kubernetesVersion": "[parameters('kubernetesVersion')]", - "dnsPrefix": "[variables('clusterName_var')]", - "enableRBAC": true, - "agentPoolProfiles": [ - { - "name": "pool0", - "count": "[parameters('nodeCount')]", - "vmSize": "[parameters('vmSize')]", - "mode": "System" - } - ] - }, - "dependsOn": [ - "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('{0}-identity', resourceGroup().name))]" - ] - }, - { - "type": "Microsoft.ContainerRegistry/registries", - "apiVersion": "2019-05-01", - "name": "[format('acr{0}', variables('rand'))]", - "location": "[parameters('location')]", - "sku": { - "name": "Standard" - }, - "properties": { - "adminUserEnabled": true - } - }, - { - "type": "Microsoft.Storage/storageAccounts", - "apiVersion": "2021-02-01", - "name": "[format('storage{0}', variables('rand'))]", - "location": "[parameters('location')]", - "kind": "BlockBlobStorage", - "sku": { - "name": "Premium_LRS" - }, - "properties": { - "minimumTlsVersion": "TLS1_2" - } - }, - { - "type": "Microsoft.ServiceBus/namespaces", - "apiVersion": "2021-06-01-preview", - "name": "[format('servicebus{0}', variables('rand'))]", - "location": "[parameters('location')]", - "sku": { - "capacity": 1, - "name": "Standard", - "tier": "Standard" - }, - "properties": { - "disableLocalAuth": false - } - }, - { - "type": "Microsoft.Authorization/roleAssignments", - "apiVersion": "2020-08-01-preview", - "scope": "[format('Microsoft.ContainerRegistry/registries/{0}', format('acr{0}', variables('rand')))]", - "name": "[guid(resourceId('Microsoft.ContainerRegistry/registries', format('acr{0}', variables('rand'))), variables('roleAssignmentAcrDefinition'))]", - "properties": { - "roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', variables('roleDefinitionId')[variables('roleAssignmentAcrDefinition')])]", - "principalId": "[reference(resourceId('Microsoft.ContainerService/managedClusters', variables('clusterName_var')), '2021-05-01').identityProfile.kubeletidentity.objectId]" - }, - "dependsOn": [ - "[resourceId('Microsoft.ContainerService/managedClusters', variables('clusterName_var'))]", - "[resourceId('Microsoft.ContainerRegistry/registries', format('acr{0}', variables('rand')))]" - ] - }, - { - "type": "Microsoft.Authorization/roleAssignments", - "apiVersion": "2020-08-01-preview", - "scope": "[format('Microsoft.Storage/storageAccounts/{0}', format('storage{0}', variables('rand')))]", - "name": "[guid(resourceId('Microsoft.Storage/storageAccounts', format('storage{0}', variables('rand'))), variables('roleAssignmentStorageAccountDefinition'))]", - "properties": { - "roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', variables('roleDefinitionId')[variables('roleAssignmentStorageAccountDefinition')])]", - "principalId": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('{0}-identity', resourceGroup().name)), '2018-11-30').principalId]" - }, - "dependsOn": [ - "[resourceId('Microsoft.ContainerService/managedClusters', variables('clusterName_var'))]", - "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('{0}-identity', resourceGroup().name))]", - "[resourceId('Microsoft.Storage/storageAccounts', format('storage{0}', variables('rand')))]" - ] - }, - { - "type": "Microsoft.Authorization/roleAssignments", - "apiVersion": "2020-08-01-preview", - "scope": "[format('Microsoft.ServiceBus/namespaces/{0}', format('servicebus{0}', variables('rand')))]", - "name": "[guid(resourceId('Microsoft.ServiceBus/namespaces', format('servicebus{0}', variables('rand'))), variables('roleAssignmentServiceBusDefinition'))]", - "properties": { - "roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', variables('roleDefinitionId')[variables('roleAssignmentServiceBusDefinition')])]", - "principalId": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('{0}-identity', resourceGroup().name)), '2018-11-30').principalId]" - }, - "dependsOn": [ - "[resourceId('Microsoft.ContainerService/managedClusters', variables('clusterName_var'))]", - "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('{0}-identity', resourceGroup().name))]", - "[resourceId('Microsoft.ServiceBus/namespaces', format('servicebus{0}', variables('rand')))]" - ] - }, - { - "type": "Microsoft.ManagedIdentity/userAssignedIdentities", - "apiVersion": "2018-11-30", - "name": "[format('{0}-identity-deploy', resourceGroup().name)]", - "location": "[parameters('location')]" - }, - { - "type": "Microsoft.Authorization/roleAssignments", - "apiVersion": "2020-08-01-preview", - "name": "[guid(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('{0}-identity-deploy', resourceGroup().name)), variables('roleAssignmentDeploymentContributorDefinition'))]", - "properties": { - "roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', variables('roleDefinitionId')[variables('roleAssignmentDeploymentContributorDefinition')])]", - "principalId": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('{0}-identity-deploy', resourceGroup().name)), '2018-11-30').principalId]" - }, - "dependsOn": [ - "[resourceId('Microsoft.ContainerService/managedClusters', variables('clusterName_var'))]", - "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('{0}-identity-deploy', resourceGroup().name))]" - ] - } - ] - } - }, - "dependsOn": [ - "[subscriptionResourceId('Microsoft.Resources/resourceGroups', parameters('resourceGroup'))]" - ] - }, - { - "condition": "[parameters('deployScript')]", - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "[format('{0}-deployscript', parameters('resourceGroup'))]", - "resourceGroup": "[parameters('resourceGroup')]", - "properties": { - "expressionEvaluationOptions": { - "scope": "inner" - }, - "mode": "Incremental", - "parameters": { - "location": { - "value": "[parameters('location')]" - }, - "scriptUri": { - "value": "[parameters('scriptUri')]" - } - }, - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "9861108784878104103" - } - }, - "parameters": { - "location": { - "type": "string", - "defaultValue": "[resourceGroup().location]" - }, - "utcValue": { - "type": "string", - "defaultValue": "[utcNow()]" - }, - "resourceGroupName": { - "type": "string", - "defaultValue": "[resourceGroup().name]" - }, - "scriptUri": { - "type": "string", - "defaultValue": "" - } - }, - "variables": { - "roleDefinitionId": { - "Owner": "8e3af657-a8ff-443c-a75c-2fe8c4bcb635", - "Contributor": "b24988ac-6180-42a0-ab88-20f7382dd24c", - "Reader": "acdd72a7-3385-48ef-bd42-f606fba81ae7" - }, - "roleAssignmentDeploymentContributorDefinition": "Contributor" - }, - "resources": [ - { - "type": "Microsoft.ManagedIdentity/userAssignedIdentities", - "apiVersion": "2018-11-30", - "name": "[format('{0}-identity-deploy', resourceGroup().name)]", - "location": "[parameters('location')]" - }, - { - "type": "Microsoft.Authorization/roleAssignments", - "apiVersion": "2020-08-01-preview", - "name": "[guid(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('{0}-identity-deploy', resourceGroup().name)), variables('roleAssignmentDeploymentContributorDefinition'))]", - "properties": { - "roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', variables('roleDefinitionId')[variables('roleAssignmentDeploymentContributorDefinition')])]", - "principalId": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('{0}-identity-deploy', resourceGroup().name)), '2018-11-30').principalId]" - }, - "dependsOn": [ - "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('{0}-identity-deploy', resourceGroup().name))]" - ] - }, - { - "type": "Microsoft.Resources/deploymentScripts", - "apiVersion": "2020-10-01", - "name": "deploy-script", - "location": "[parameters('location')]", - "kind": "AzureCLI", - "identity": { - "type": "UserAssigned", - "userAssignedIdentities": { - "[format('{0}', resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('{0}-identity-deploy', resourceGroup().name)))]": {} - } - }, - "properties": { - "environmentVariables": [ - { - "name": "RESOURCE_GROUP", - "value": "[parameters('resourceGroupName')]" - }, - { - "name": "AKS_NAME", - "value": "aks1" - }, - { - "name": "NAMESPACE", - "value": "keda-http" - } - ], - "forceUpdateTag": "[parameters('utcValue')]", - "azCliVersion": "2.28.0", - "timeout": "PT30M", - "primaryScriptUri": "[parameters('scriptUri')]", - "cleanupPreference": "OnSuccess", - "retentionInterval": "P1D" - }, - "dependsOn": [ - "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('{0}-identity-deploy', resourceGroup().name))]" - ] - } - ] - } - }, - "dependsOn": [ - "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('resourceGroup')), 'Microsoft.Resources/deployments', format('{0}-aks', parameters('resourceGroup')))]", - "[subscriptionResourceId('Microsoft.Resources/resourceGroups', parameters('resourceGroup'))]" - ] - } - ] -} \ No newline at end of file diff --git a/cloud-native/aks-bicep/README.md b/cloud-native/aks-bicep/README.md deleted file mode 100644 index 9e355df..0000000 --- a/cloud-native/aks-bicep/README.md +++ /dev/null @@ -1,45 +0,0 @@ -# Explore Open Source workloads with Azure Kubernetes Service (AKS) and Bicep - -In this lab you will deploy an Azure Kubernetes Service (AKS) cluster and other Azure services (Container Registry, Managed Identity, Storage Account, Service Bus, Key Vault), the open source KEDA (Kubernetes Event-driven Autoscaling) project with [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli) and [Bicep](https://docs.microsoft.com/en-us/azure/azure-resource-manager/bicep/overview). - -## Requirements - -- An **Azure Subscription** (e.g. [Free](https://aka.ms/azure-free-account) or [Student](https://aka.ms/azure-student-account) account) -- The [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli) -- Bash shell (e.g. macOS, Linux, [Windows Subsystem for Linux (WSL)](https://docs.microsoft.com/en-us/windows/wsl/about), [Multipass](https://multipass.run/), [Azure Cloud Shell](https://docs.microsoft.com/en-us/azure/cloud-shell/quickstart), [GitHub Codespaces](https://github.com/features/codespaces), etc) -- A [GitHub Account](https://github.com) - -## Instructions - -Use the [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli) and [Bicep](https://docs.microsoft.com/en-us/azure/azure-resource-manager/bicep/overview) templates to deploy the infrastructure for your application. - -Login to the Azure CLI. - -```bash -az login -``` - -Install kubectl using the Azure CLI, if required. - -```bash -az aks install-cli -``` - -Deploy the Bicep template for your Azure Kubernetes Service (AKS) cluster. - -```bash -cd cloud-native/aks-bicep/01-aks -bash deploy-main.sh -``` - -Invoke kubectl command on AKS cluster. - -```bash -RESOURCE_GROUP='220600-keda' -AKS_NAME='aks1' - -az aks command invoke \ - --resource-group $RESOURCE_GROUP \ - --name $AKS_NAME \ - --command 'kubectl run nginx --image=nginx' -``` diff --git a/cloud-native/aks-open-service-mesh/02-deploying-bookstore-app/README.md b/cloud-native/aks-open-service-mesh/02-deploying-bookstore-app/README.md deleted file mode 100644 index f83aa18..0000000 --- a/cloud-native/aks-open-service-mesh/02-deploying-bookstore-app/README.md +++ /dev/null @@ -1,225 +0,0 @@ -# Part 2: Bookstore application deployment - -With an AKS cluster deployed, let's focus on deploying an application and configuring it to work with OSM and NGINX ingress. - -The sample app deployed here is the same application demonstrated in [OSM's Getting Started guide](https://release-v1-2.docs.openservicemesh.io/docs/getting_started/install_apps/). The getting started guide uses [port-forwarding for exposing the application](https://release-v1-2.docs.openservicemesh.io/docs/getting_started/install_apps/#view-the-application-uis), but you will use the managed NGINX ingress controller instead. You will also need to deploy OSM `IngressBackend` configurations to route NGINX-managed ingress traffic to OSM-managed service backends. - -## Application overview - -Here is a simple diagram of the application pods that will be deployed into the cluster. - -![Bookstore Application Diagram](./bookstore_app.png) - -The `mysql` database pod is where book transactions are recorded. The `bookwarehouse` pod is responsible for reading/writing data to the database and should only be reachable from the `bookstore` pod. The `bookbuyer` and `bookthief` pods act as clients of the `bookstore` app. As the names suggest, one buys books from the bookstore while the other steals books. - -The intent of this part of the lab is to just get the application up an running and demonstrate a working service mesh in permissive mode (the default). - -Please ensure you have completed the steps in [Part 1](../README.md) before you proceed. - -Make sure you are in the correct working directory (`cloud-native/aks-open-service-mesh/02-deploying-bookstore-app`) - -```bash -cd 02-deploying-bookstore-app -``` - -## Deploy the namespaces to Kubernetes - -As mentioned in Part 1, you need to add namespaces to OSM so that it can start managing traffic for them. - -Run the following commands to create the application namespaces. - -```bash -kubectl create namespace bookstore -kubectl create namespace bookbuyer -kubectl create namespace bookthief -kubectl create namespace bookwarehouse -``` - -Onboard the applications to OSM by adding the namespaces to OSM. - -```bash -osm namespace add bookstore bookbuyer bookthief bookwarehouse -``` - -You should see output similar to the following: - -```text -Namespace [bookstore] successfully added to mesh [osm] -Namespace [bookbuyer] successfully added to mesh [osm] -Namespace [bookthief] successfully added to mesh [osm] -Namespace [bookwarehouse] successfully added to mesh [osm] -``` - -Let's take a look at the labels that have been added to these namespaces. - -```bash -kubectl get namespace -A --show-labels | grep book -``` - -The namespaces have also been annotated by OSM to specify whether or not the control plane should be injecting data plane side cars into pods. You can see the annotation for each with these commands. - -```bash -kubectl get namespace bookstore -o jsonpath='{.metadata.annotations}' -kubectl get namespace bookbuyer -o jsonpath='{.metadata.annotations}' -kubectl get namespace bookthief -o jsonpath='{.metadata.annotations}' -kubectl get namespace bookwarehouse -o jsonpath='{.metadata.annotations}' -``` - -You can also verify using the OSM CLI. - -```bash -osm namespace list -``` - -## Deploy the application to Kubernetes - -The deployment manifests are hosted in the [OSM docs repo](https://github.com/openservicemesh/osm-docs/tree/main/manifests/apps), so you can deploy them directly from there. - -Run the following commands to deploy the applications. - -```bash -kubectl apply -f https://raw.githubusercontent.com/openservicemesh/osm-docs/release-v1.2/manifests/apps/bookbuyer.yaml -kubectl apply -f https://raw.githubusercontent.com/openservicemesh/osm-docs/release-v1.2/manifests/apps/bookthief.yaml -kubectl apply -f https://raw.githubusercontent.com/openservicemesh/osm-docs/release-v1.2/manifests/apps/bookstore.yaml -kubectl apply -f https://raw.githubusercontent.com/openservicemesh/osm-docs/release-v1.2/manifests/apps/bookwarehouse.yaml -kubectl apply -f https://raw.githubusercontent.com/openservicemesh/osm-docs/release-v1.2/manifests/apps/mysql.yaml -``` - -## Exploring the `bookbuyer` pod and viewing `osm` configuration - -Check on the `bookbuyer` pods - -```bash -kubectl get pod -n bookbuyer -``` - -You should see an output similar to this: - -```text -NAME READY STATUS RESTARTS AGE -bookbuyer-6c759555b8-n4m7c 2/2 Running 0 112s -``` - -Do you notice the `READY` column reporting `2/2`? This means OSM sidecar injector has done its job. If you inspect the `bookbuyer` pod, you will see some event logs that indicate OSM was in there initializing itself and injecting the Envoy Proxy sidecar. - -```bash -kubectl describe pod -l app=bookbuyer -n bookbuyer -``` - -## Exposing the `bookbuyer`, `bookthief` and `bookstore` web applications - -Let's make use of the NGINX ingress and expose the `bookbuyer`, `bookthief` and `bookstore` web applications so that we can connect to them from a web browser. - -> These web applications are setup to auto-refresh with a running counter indicating how many books were purchased, stolen, and the version of bookstore that was running at the time of transaction. - -Expose the `bookbuyer` app by deploying a service and ingress. - -```bash -kubectl apply -f ./bookbuyer-ui.yaml -``` - -Check the status of the ingress. - -```bash -kubectl get ingress -n bookbuyer -``` - -You should see output similar to this: - -```text -NAME CLASS HOSTS ADDRESS PORTS AGE -bookbuyer webapprouting.kubernetes.azure.com * 4.236.214.31 80 51s -``` - -A public IP address has been assigned to the ingress; however, the site will not work yet. The `bookstore` namespace is participating in the service mesh, so an `IngressBackend` resource is required to allow HTTP communication between the ingress and the backend service. - -Deploy the `IngressBackend` for `bookbuyer` with the following command: - -```bash -kubectl apply -f ./bookbuyer-ui-ingressbackend.yaml -``` - -Check the status of the ingress backend. - -```bash -kubectl get ingressbackend -n bookbuyer -``` - -You should see output similar to this: - -```text -NAME STATUS -bookbuyer committed -``` - -> Once you see a `STATUS` of `committed`, your application should be accessible to the internet. - -Repeat the steps above for `bookthief` and `bookstore` apps. - -```bash -kubectl apply -f ./bookthief-ui.yaml -kubectl apply -f ./bookstore-ui.yaml -kubectl apply -f ./bookthief-ui-ingressbackend.yaml -kubectl apply -f ./bookstore-ui-ingressbackend.yaml -``` - -Run the following command again to view the status of the `IngressBackends`. - -```bash -kubectl get ingressbackend -A -``` - -You should see output similar to this: - -```text -NAMESPACE NAME STATUS -bookbuyer bookbuyer committed -bookstore bookstore committed -bookthief bookthief committed -``` - -Now you should be able to access all of the sites. Issue the commands below and click each link to open the site in a web browser. - -```bash -nginx_ingress_host="$(kubectl -n app-routing-system get service nginx -o jsonpath='{.status.loadBalancer.ingress[0].ip}')" - -# these are the urls you should open in your browser -echo http://$nginx_ingress_host/bookbuyer -echo http://$nginx_ingress_host/bookthief -echo http://$nginx_ingress_host/bookstore -``` - -You should see each application auto-incrementing its sales, thefts, and books sold counters. - -### Bookbuyer - -![bookbuyer](./bookbuyer.png) - -### Bookthief - -![bookthief](./bookthief.png) - -### Bookstore v1 - -![bookstore-v1](./bookstore-v1.png) - -## Next steps - -We've successfully deployed the `bookbuyer`, `bookthief`, and `bookstore` applications and exposed their frontend UIs via ingress and configured OSM to allow traffic between the ingress endpoints and backend services. By default, OSM is configured in permissive traffic policy mode and we've enabled traffic to flow between ingress and backend service pods. - -Now, head over to [Part 3: Applying Zero-Trust to the Bookstore application](../03-applying-zero-trust/README.md) to apply some Zero-Trust principles! - -## Resources - -* [Bookstore Sample Application][osm_bookstore_sample] -* [OSM and NGINX Ingress Controller Configuration][osm_nginx_ing] -* [OSM Permissive Traffic Policy][osm_permissive_traffic_policy] -* [Kubernetes: Service][k8s_svc] -* [Kubernetes: Ingress][k8s_ing] - - -[osm_bookstore_sample]:https://release-v1-2.docs.openservicemesh.io/docs/getting_started/install_apps/ -[osm_nginx_ing]:https://release-v1-2.docs.openservicemesh.io/docs/demos/ingress_k8s_nginx/ -[osm_permissive_traffic_policy]:https://release-v1-2.docs.openservicemesh.io/docs/guides/traffic_management/permissive_mode/ -[k8s_svc]:https://kubernetes.io/docs/concepts/services-networking/service/ -[k8s_ing]:https://kubernetes.io/docs/concepts/services-networking/ingress/ diff --git a/cloud-native/aks-open-service-mesh/02-deploying-bookstore-app/bookbuyer-ui-ingressbackend.yaml b/cloud-native/aks-open-service-mesh/02-deploying-bookstore-app/bookbuyer-ui-ingressbackend.yaml deleted file mode 100644 index 2073fd2..0000000 --- a/cloud-native/aks-open-service-mesh/02-deploying-bookstore-app/bookbuyer-ui-ingressbackend.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: policy.openservicemesh.io/v1alpha1 -kind: IngressBackend -metadata: - name: bookbuyer - namespace: bookbuyer -spec: - backends: - - name: bookbuyer - port: - number: 14001 # targetPort of bookbuyer service - protocol: http - sources: - - kind: Service - namespace: app-routing-system - name: nginx \ No newline at end of file diff --git a/cloud-native/aks-open-service-mesh/02-deploying-bookstore-app/bookbuyer-ui.yaml b/cloud-native/aks-open-service-mesh/02-deploying-bookstore-app/bookbuyer-ui.yaml deleted file mode 100644 index 24a6f7f..0000000 --- a/cloud-native/aks-open-service-mesh/02-deploying-bookstore-app/bookbuyer-ui.yaml +++ /dev/null @@ -1,35 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: bookbuyer - namespace: bookbuyer - labels: - app: bookbuyer - service: bookbuyer -spec: - ports: - - name: http - port: 14001 - selector: - app: bookbuyer - version: v1 ---- -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: bookbuyer - namespace: bookbuyer - annotations: - nginx.ingress.kubernetes.io/rewrite-target: / -spec: - ingressClassName: webapprouting.kubernetes.azure.com # managed nginx ingress class name - rules: - - http: - paths: - - path: /bookbuyer - pathType: Prefix - backend: - service: - name: bookbuyer - port: - number: 14001 \ No newline at end of file diff --git a/cloud-native/aks-open-service-mesh/02-deploying-bookstore-app/bookbuyer.png b/cloud-native/aks-open-service-mesh/02-deploying-bookstore-app/bookbuyer.png deleted file mode 100644 index 5babaaf..0000000 Binary files a/cloud-native/aks-open-service-mesh/02-deploying-bookstore-app/bookbuyer.png and /dev/null differ diff --git a/cloud-native/aks-open-service-mesh/02-deploying-bookstore-app/bookstore-ui-ingressbackend.yaml b/cloud-native/aks-open-service-mesh/02-deploying-bookstore-app/bookstore-ui-ingressbackend.yaml deleted file mode 100644 index cfd4740..0000000 --- a/cloud-native/aks-open-service-mesh/02-deploying-bookstore-app/bookstore-ui-ingressbackend.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: policy.openservicemesh.io/v1alpha1 -kind: IngressBackend -metadata: - name: bookstore - namespace: bookstore -spec: - backends: - - name: bookstore - port: - number: 14001 # targetPort of bookstore service - protocol: http - sources: - - kind: Service - namespace: app-routing-system - name: nginx \ No newline at end of file diff --git a/cloud-native/aks-open-service-mesh/02-deploying-bookstore-app/bookstore-ui.yaml b/cloud-native/aks-open-service-mesh/02-deploying-bookstore-app/bookstore-ui.yaml deleted file mode 100644 index 86d94b5..0000000 --- a/cloud-native/aks-open-service-mesh/02-deploying-bookstore-app/bookstore-ui.yaml +++ /dev/null @@ -1,35 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: bookstore - namespace: bookstore - labels: - app: bookstore - service: bookstore -spec: - ports: - - name: http - port: 14001 - selector: - app: bookstore - version: v1 ---- -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: bookstore - namespace: bookstore - annotations: - nginx.ingress.kubernetes.io/rewrite-target: / -spec: - ingressClassName: webapprouting.kubernetes.azure.com # managed nginx ingress class name - rules: - - http: - paths: - - path: /bookstore - pathType: Prefix - backend: - service: - name: bookstore - port: - number: 14001 diff --git a/cloud-native/aks-open-service-mesh/02-deploying-bookstore-app/bookstore-v1.png b/cloud-native/aks-open-service-mesh/02-deploying-bookstore-app/bookstore-v1.png deleted file mode 100644 index 206be72..0000000 Binary files a/cloud-native/aks-open-service-mesh/02-deploying-bookstore-app/bookstore-v1.png and /dev/null differ diff --git a/cloud-native/aks-open-service-mesh/02-deploying-bookstore-app/bookstore_app.png b/cloud-native/aks-open-service-mesh/02-deploying-bookstore-app/bookstore_app.png deleted file mode 100644 index 3a857b0..0000000 Binary files a/cloud-native/aks-open-service-mesh/02-deploying-bookstore-app/bookstore_app.png and /dev/null differ diff --git a/cloud-native/aks-open-service-mesh/02-deploying-bookstore-app/bookthief-ui-ingressbackend.yaml b/cloud-native/aks-open-service-mesh/02-deploying-bookstore-app/bookthief-ui-ingressbackend.yaml deleted file mode 100644 index 3c991c6..0000000 --- a/cloud-native/aks-open-service-mesh/02-deploying-bookstore-app/bookthief-ui-ingressbackend.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: policy.openservicemesh.io/v1alpha1 -kind: IngressBackend -metadata: - name: bookthief - namespace: bookthief -spec: - backends: - - name: bookthief - port: - number: 14001 # targetPort of bookthief service - protocol: http - sources: - - kind: Service - namespace: app-routing-system - name: nginx \ No newline at end of file diff --git a/cloud-native/aks-open-service-mesh/02-deploying-bookstore-app/bookthief-ui.yaml b/cloud-native/aks-open-service-mesh/02-deploying-bookstore-app/bookthief-ui.yaml deleted file mode 100644 index a36d71a..0000000 --- a/cloud-native/aks-open-service-mesh/02-deploying-bookstore-app/bookthief-ui.yaml +++ /dev/null @@ -1,34 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: bookthief - namespace: bookthief - labels: - app: bookthief - service: bookthief -spec: - ports: - - name: http - port: 14001 - selector: - app: bookthief ---- -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: bookthief - namespace: bookthief - annotations: - nginx.ingress.kubernetes.io/rewrite-target: / -spec: - ingressClassName: webapprouting.kubernetes.azure.com # managed nginx ingress class name - rules: - - http: - paths: - - path: /bookthief - pathType: Prefix - backend: - service: - name: bookthief - port: - number: 14001 diff --git a/cloud-native/aks-open-service-mesh/02-deploying-bookstore-app/bookthief.png b/cloud-native/aks-open-service-mesh/02-deploying-bookstore-app/bookthief.png deleted file mode 100644 index dc0f75e..0000000 Binary files a/cloud-native/aks-open-service-mesh/02-deploying-bookstore-app/bookthief.png and /dev/null differ diff --git a/cloud-native/aks-open-service-mesh/03-applying-zero-trust/README.md b/cloud-native/aks-open-service-mesh/03-applying-zero-trust/README.md deleted file mode 100644 index 643782a..0000000 --- a/cloud-native/aks-open-service-mesh/03-applying-zero-trust/README.md +++ /dev/null @@ -1,226 +0,0 @@ -# Part 3: Applying Zero-Trust to the Bookstore application - -So far you have deployed and exposed the Bookstore app via managed NGINX ingress controller and onboarded the Bookstore namespaces to OSM. Communication between pods within the service mesh is wide-open with the **permissive traffic policy** enabled and books are being stolen by the `bookthief` app. You need to lock things down and ensure `bookthief` is no longer able to communicate with `bookstore` and steal any more books. You will also ensure you have end-to-end encryption in place for internal communication between the ingress and backend services using mutual TLS (mTLS). - -Please ensure you have completed the steps in [Part 2: Bookstore application deployment](../02-deploying-bookstore-app/README.md) before you proceed. - -Make sure you are in the right working directory (this command assumes you are currently in the `cloud-native/aks-open-service-mesh/02-deploying-bookstore-app/` directory). - -```bash -cd ../03-applying-zero-trust -``` - -## Securing communications between ingress and backend services - -You will start by enforcing mTLS between the NGINX ingress controller. In order to secure communications between our managed ingress controller and OSM, you will need to update the `Ingress` manifests to include NGINX controller-specific [`annotations`][nginx_annotations] and update our [`IngressBackend`][osm_ingressbackend_api] manifest to enforce HTTPS traffic using TLS certificates which have been created by OSM. - -### Updating `Ingress` manifests - -To secure communications, NGINX it will need to present a certificate to OSM. The following NGINX-specific `annotations` need to be added to the `Ingress` manifests: - -* [`nginx.ingress.kubernetes.io/backend-protocol`][nginx_annotations_backend_protocol] tells NGINX how to communicate with the backend service. In our case, this will be set to `HTTPS` -* [`nginx.ingress.kubernetes.io/configuration-snippet`][nginx_annotations_configuration_snippet] to pass in additional configuration information for OSM. In our case, this will be set to `proxy_ssl_name "bookbuyer.bookbuyer.cluster.local";` -* [`nginx.ingress.kubernetes.io/proxy-ssl-secret`][nginx_annotations_proxy_ssl_secret] is the secret name formatted as `namespace/secretName` where the client certificate is stored. This certificate is used by NGINX to proxy HTTPS connects to TLS backends. In our case, this will be set to `kube-system/osm-ingress-client-cert` -* [`nginx.ingress.kubernetes.io/proxy-ssl-verify`][nginx_annotations_proxy_ssl_verify] enables or disables verification of proxied HTTPS server certificate. In our case, this will be set to `on` - -Typically you would need to manually [edit the OSM `meshconfig` resource](https://release-v1-2.docs.openservicemesh.io/docs/demos/ingress_k8s_nginx/#https-ingress-mtls-and-tls) so that OSM can issue and store certificates within a [Kubernetes secret][k8s_secret]. With managed-OSM, this configuration is done for you. - -To retrieve the details of the certificate for ingress gateway, you can run the following command: - -```bash -kubectl get meshconfig osm-mesh-config -n kube-system -o yaml -``` - -In the output, you should see `certificate` details. Here is the snippet of code you should look for. - -```yaml -... -certificate: - certKeyBitSize: 2048 - ingressGateway: - secret: - name: osm-ingress-client-cert - namespace: kube-system - subjectAltNames: - - ingress-nginx.ingress.cluster.local - validityDuration: 24h - serviceCertValidityDuration: 24h -... -``` - -The truncated output above lists the certificate details which will be used by the ingress; it includes the secret's `name`, `namespace`, and the `subjectAltNames` (SAN) of the TLS certificate. - -### Updating `IngressBackend` manifests - -You will need to update the `IngressBackend` manifests using the certificate information listed above. - -First, you need to update the [`IngressBackendSpec`][osm_ingressbackendspec] and change the `PortSpec` from `http` to `https`. Then you will need to add a `TLSSpec` element and set the `skipClientCertValidation` to `false`. - -From there, you need to update the [`IngressSourceSpec`][osm_ingresssourcespec] and add a new source with the `kind` attribute being set to `AuthenticatedPrincipal` and set the `name` attribute to `ingress-nginx.ingress.cluster.local`. This tells OSM to expect traffic from the NGINX ingress controller. - -OSM provisioned a client certificate for the NGINX ingress service with the Subject ALternative Name (SAN) `ingress-nginx.ingress.cluster.local`, so the `IngressBackend` configuration needs to reference the same SAN for mTLS authentication (between the Nginx ingress service and the backend services). - -The name of the `subjectAltNames` object can also be pulled from the OSM `meshconfig` resource. You can view it with the following command. - -```bash -kubectl get meshconfig osm-mesh-config -n kube-system -o jsonpath='{.spec.certificate.ingressGateway}' | jq -r .subjectAltNames | jq -r '.[0]' -``` - -Here is an example of what the new `IngressBackend` looks like for the `bookbuyer` app: - -![bookbuyer](./bookbuyer.png) - -### Apply the updated ingress configurations - -The `Ingress` and `IngressBackend` manifests have been updated for you so you can simply apply the configuration to lock down the ingress to backend service traffic with OSM. - -Let's re-deploy `Ingress` and `IngressBackend` resources for `bookbuyer`, `bookthief`, and `bookstore` using the following commands. - -```bash -kubectl apply -f bookbuyer-ui-secure-ingress.yaml -kubectl apply -f bookthief-ui-secure-ingress.yaml -kubectl apply -f bookstore-ui-secure-ingress.yaml -``` - -> Whenever changes are made to Ingress resources, IngressBackend resources are re-synced. - -Confirm the `IngressBackend` statuses show as "committed". - -```bash -kubectl get ingressbackend -A -``` - -If you still have your apps open in a browser, you might need to refresh the pages to confirm the app is still running. - -If you need the site URLs again, run the following commands: - -```bash -nginx_ingress_host="$(kubectl -n app-routing-system get service nginx -o jsonpath='{.status.loadBalancer.ingress[0].ip}')" - -# these are the urls you should open in your browser -echo http://$nginx_ingress_host/bookbuyer -echo http://$nginx_ingress_host/bookthief -echo http://$nginx_ingress_host/bookstore -``` - -## Configure SMI traffic policies - -OSM is running in permissive mode, which means all resources enrolled in the mesh can talk freely with each other. One of the main reasons why you would want to implement a service mesh is to enforce end-to-end encryption of network communications. This is one of the key features of OSM and you can enabled it using [SMI traffic policies][osm_smi_traffic_policy]. - -### Disable permissive traffic policies - -Run this command to disable permissive traffic policy mode. - -```bash -kubectl patch meshconfig osm-mesh-config -n kube-system -p '{"spec":{"traffic":{"enablePermissiveTrafficPolicyMode":false}}}' --type=merge -``` - -### Enable SMI traffic policies - -With the permissive traffic policy mode disabled, the application pods can no longer communicate with each other. If you have the **bookbuyer**, **bookthief**, and **bookstore** applications still open in your web browser, you will see the counters have stopped incrementing. - -Communication within the service mesh has gone from default allow, to default deny. OSM now requires [SMI access control policies][osm_smi_access_control_policy] (e.g., `TrafficTarget`, `HTTPRouteGroup`, and `TCPRoute` CRDs) to enable traffic flow. - -Here's an overview of each resource: - -**[`TrafficTarget`][smi_traffictarget]**: Used to associate a set of traffic definitions (rules) with a service identity. Access control is based on [service identity][k8s_serviceaccount] which can be allocated to groups of pods. - -**[`HTTPRouteGroup`][smi_httproutegroup]**: Describes the HTTP/1 and HTTP/2 traffic characteristics to filter on in `TrafficTarget` rule definitions. Filters can be applied to combinations of HTTP headers, paths using Regex, and methods. - -**[`TCPRoute`][smi_tcproute]**: Describes the L4 TCP traffic to filter on in `TrafficTarget` rule definitions. - -**[`UDPRoute`][smi_udproute]**: Describes the L4 UDP traffic to filter on in `TrafficTarget` rule definitions. - -Using the `HTTPRouteGroup` resource, you can define a traffic filter for GET requests that are made to the `/books-bought` path with specific header information like this. - -```yaml -apiVersion: specs.smi-spec.io/v1alpha4 -kind: HTTPRouteGroup -metadata: - name: bookstore-service-routes - namespace: bookstore -spec: - matches: - - name: books-bought - pathRegex: /books-bought - methods: - - GET - headers: - - "user-agent": ".*-http-client/*.*" - - "client-app": "bookbuyer" - - name: buy-a-book - pathRegex: ".*a-book.*new" - methods: - - GET -``` - -The manifest above will filter network requests and can be used to define rules for allowing traffic flow. Using the `TrafficTarget` resource, you can apply the filter to specific source/destination pairs. - -```yaml -kind: TrafficTarget -apiVersion: access.smi-spec.io/v1alpha3 -metadata: - name: bookstore - namespace: bookstore -spec: - destination: - kind: ServiceAccount - name: bookstore - namespace: bookstore - rules: - - kind: HTTPRouteGroup - name: bookstore-service-routes - matches: - - buy-a-book - - books-bought - sources: - - kind: ServiceAccount - name: bookbuyer - namespace: bookbuyer -``` - -The manifest above will create a new access policy that filters traffic based on the `HTTPRouteGroup` named `bookstore-service-routes` and allow pods that are running as the `bookbuyer` service account to communicate with pods running as the `bookstore` service account. - -> Note that OSM uses `ServiceAccounts` to identify groups of resources. - -Run the command below to deploy the SMI traffic access policies. - -```bash -kubectl apply -f smi-traffic-to-mysql.yaml -kubectl apply -f smi-traffic-to-bookwarehouse.yaml -kubectl apply -f smi-traffic-to-bookstore.yaml -``` - -Now if you re-visit the **bookbuyer** and **bookstore** web applications, you'll see the counters are incrementing again. However, the **bookthief** application was not given access to communicate to **bookstore** and therefore, the counter remains idle. - -## Next steps - -Congratulations, you have successfully blocked the **bookthief** application from stealing books 🎉 - -Next, head over to [Part 4: Traffic splitting with OSM](../04-osm-traffic-splitting/README.md) where you will deploy a new version of the **bookstore** app and take a canary approach to release **bookstore v2**. - -## Resources - -* [IngressBackend API][osm_ingressbackend_api] -* [Traffic Access Control][smi_traffictarget] -* [Traffic Specs][smi_trafficspecs] -* [NGINX Ingress Controller Annotations][nginx_annotations] - - -[osm_smi_traffic_policy]:https://release-v1-2.docs.openservicemesh.io/docs/getting_started/traffic_policies/#smi-traffic-policy-mode -[osm_smi_access_control_policy]:https://release-v1-2.docs.openservicemesh.io/docs/getting_started/traffic_policies/#deploy-smi-access-control-policies -[osm_ingressbackend_api]:https://release-v1-2.docs.openservicemesh.io/docs/guides/traffic_management/ingress -[osm_ingressbackendspec]:https://release-v1-2.docs.openservicemesh.io/docs/api_reference/policy/v1alpha1/#policy.openservicemesh.io/v1alpha1.BackendSpec -[osm_ingresssourcespec]:https://release-v1-2.docs.openservicemesh.io/docs/api_reference/policy/v1alpha1/#policy.openservicemesh.io/v1alpha1.IngressSourceSpec -[smi_trafficspecs]:https://github.com/servicemeshinterface/smi-spec/blob/v0.6.0/apis/traffic-specs/v1alpha4/traffic-specs.md -[smi_traffictarget]:https://github.com/servicemeshinterface/smi-spec/blob/v0.6.0/apis/traffic-access/v1alpha2/traffic-access.md#traffictarget -[smi_httproutegroup]:https://github.com/servicemeshinterface/smi-spec/blob/v0.6.0/apis/traffic-specs/v1alpha4/traffic-specs.md#httproutegroup -[smi_tcproute]:https://github.com/servicemeshinterface/smi-spec/blob/v0.6.0/apis/traffic-specs/v1alpha4/traffic-specs.md#tcproute -[smi_udproute]:https://github.com/servicemeshinterface/smi-spec/blob/v0.6.0/apis/traffic-specs/v1alpha4/traffic-specs.md#udproute -[nginx_annotations]:https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations -[nginx_annotations_backend_protocol]:https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#backend-protocol -[nginx_annotations_configuration_snippet]:https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#configuration-snippet -[nginx_annotations_proxy_ssl_secret]:https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#backend-certificate-authentication -[nginx_annotations_proxy_ssl_verify]:https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#backend-certificate-authentication -[k8s_secret]:https://kubernetes.io/docs/concepts/configuration/secret -[k8s_serviceaccount]:https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account diff --git a/cloud-native/aks-open-service-mesh/03-applying-zero-trust/bookbuyer-ui-secure-ingress.yaml b/cloud-native/aks-open-service-mesh/03-applying-zero-trust/bookbuyer-ui-secure-ingress.yaml deleted file mode 100644 index 4b7045e..0000000 --- a/cloud-native/aks-open-service-mesh/03-applying-zero-trust/bookbuyer-ui-secure-ingress.yaml +++ /dev/null @@ -1,45 +0,0 @@ -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: bookbuyer - namespace: bookbuyer - annotations: - nginx.ingress.kubernetes.io/rewrite-target: / - nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" - # proxy_ssl_name for a service is of the form ..cluster.local - nginx.ingress.kubernetes.io/configuration-snippet: | - proxy_ssl_name "bookbuyer.bookbuyer.cluster.local"; - nginx.ingress.kubernetes.io/proxy-ssl-secret: "kube-system/osm-ingress-client-cert" - nginx.ingress.kubernetes.io/proxy-ssl-verify: "on" -spec: - ingressClassName: webapprouting.kubernetes.azure.com - rules: - - http: - paths: - - path: /bookbuyer - pathType: Prefix - backend: - service: - name: bookbuyer - port: - number: 14001 ---- -apiVersion: policy.openservicemesh.io/v1alpha1 -kind: IngressBackend -metadata: - name: bookbuyer - namespace: bookbuyer -spec: - backends: - - name: bookbuyer - port: - number: 14001 # targetPort of bookbuyer service - protocol: https - tls: - skipClientCertValidation: false - sources: - - kind: Service - namespace: app-routing-system - name: nginx - - kind: AuthenticatedPrincipal - name: ingress-nginx.ingress.cluster.local \ No newline at end of file diff --git a/cloud-native/aks-open-service-mesh/03-applying-zero-trust/bookbuyer.png b/cloud-native/aks-open-service-mesh/03-applying-zero-trust/bookbuyer.png deleted file mode 100644 index d585042..0000000 Binary files a/cloud-native/aks-open-service-mesh/03-applying-zero-trust/bookbuyer.png and /dev/null differ diff --git a/cloud-native/aks-open-service-mesh/03-applying-zero-trust/bookstore-ui-secure-ingress.yaml b/cloud-native/aks-open-service-mesh/03-applying-zero-trust/bookstore-ui-secure-ingress.yaml deleted file mode 100644 index 7a6ac11..0000000 --- a/cloud-native/aks-open-service-mesh/03-applying-zero-trust/bookstore-ui-secure-ingress.yaml +++ /dev/null @@ -1,45 +0,0 @@ -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: bookstore - namespace: bookstore - annotations: - nginx.ingress.kubernetes.io/rewrite-target: / - nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" - # proxy_ssl_name for a service is of the form ..cluster.local - nginx.ingress.kubernetes.io/configuration-snippet: | - proxy_ssl_name "bookstore.bookstore.cluster.local"; - nginx.ingress.kubernetes.io/proxy-ssl-secret: "kube-system/osm-ingress-client-cert" - nginx.ingress.kubernetes.io/proxy-ssl-verify: "on" -spec: - ingressClassName: webapprouting.kubernetes.azure.com - rules: - - http: - paths: - - path: /bookstore - pathType: Prefix - backend: - service: - name: bookstore - port: - number: 14001 ---- -apiVersion: policy.openservicemesh.io/v1alpha1 -kind: IngressBackend -metadata: - name: bookstore - namespace: bookstore -spec: - backends: - - name: bookstore - port: - number: 14001 # targetPort of bookstore service - protocol: https - tls: - skipClientCertValidation: false - sources: - - kind: Service - namespace: app-routing-system - name: nginx - - kind: AuthenticatedPrincipal - name: ingress-nginx.ingress.cluster.local \ No newline at end of file diff --git a/cloud-native/aks-open-service-mesh/03-applying-zero-trust/bookthief-ui-secure-ingress.yaml b/cloud-native/aks-open-service-mesh/03-applying-zero-trust/bookthief-ui-secure-ingress.yaml deleted file mode 100644 index f7d97a4..0000000 --- a/cloud-native/aks-open-service-mesh/03-applying-zero-trust/bookthief-ui-secure-ingress.yaml +++ /dev/null @@ -1,45 +0,0 @@ -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: bookthief - namespace: bookthief - annotations: - nginx.ingress.kubernetes.io/rewrite-target: / - nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" - # proxy_ssl_name for a service is of the form ..cluster.local - nginx.ingress.kubernetes.io/configuration-snippet: | - proxy_ssl_name "bookthief.bookthief.cluster.local"; - nginx.ingress.kubernetes.io/proxy-ssl-secret: "kube-system/osm-ingress-client-cert" - nginx.ingress.kubernetes.io/proxy-ssl-verify: "on" -spec: - ingressClassName: webapprouting.kubernetes.azure.com - rules: - - http: - paths: - - path: /bookthief - pathType: Prefix - backend: - service: - name: bookthief - port: - number: 14001 ---- -apiVersion: policy.openservicemesh.io/v1alpha1 -kind: IngressBackend -metadata: - name: bookthief - namespace: bookthief -spec: - backends: - - name: bookthief - port: - number: 14001 # targetPort of bookthief service - protocol: https - tls: - skipClientCertValidation: false - sources: - - kind: Service - namespace: app-routing-system - name: nginx - - kind: AuthenticatedPrincipal - name: ingress-nginx.ingress.cluster.local \ No newline at end of file diff --git a/cloud-native/aks-open-service-mesh/03-applying-zero-trust/smi-traffic-to-bookstore.yaml b/cloud-native/aks-open-service-mesh/03-applying-zero-trust/smi-traffic-to-bookstore.yaml deleted file mode 100644 index 74d1d99..0000000 --- a/cloud-native/aks-open-service-mesh/03-applying-zero-trust/smi-traffic-to-bookstore.yaml +++ /dev/null @@ -1,39 +0,0 @@ -kind: TrafficTarget -apiVersion: access.smi-spec.io/v1alpha3 -metadata: - name: bookstore - namespace: bookstore -spec: - destination: - kind: ServiceAccount - name: bookstore - namespace: bookstore - rules: - - kind: HTTPRouteGroup - name: bookstore-service-routes - matches: - - buy-a-book - - books-bought - sources: - - kind: ServiceAccount - name: bookbuyer - namespace: bookbuyer ---- -apiVersion: specs.smi-spec.io/v1alpha4 -kind: HTTPRouteGroup -metadata: - name: bookstore-service-routes - namespace: bookstore -spec: - matches: - - name: books-bought - pathRegex: /books-bought - methods: - - GET - headers: - - "user-agent": ".*-http-client/*.*" - - "client-app": "bookbuyer" - - name: buy-a-book - pathRegex: ".*a-book.*new" - methods: - - GET diff --git a/cloud-native/aks-open-service-mesh/03-applying-zero-trust/smi-traffic-to-bookwarehouse.yaml b/cloud-native/aks-open-service-mesh/03-applying-zero-trust/smi-traffic-to-bookwarehouse.yaml deleted file mode 100644 index 20ddaba..0000000 --- a/cloud-native/aks-open-service-mesh/03-applying-zero-trust/smi-traffic-to-bookwarehouse.yaml +++ /dev/null @@ -1,31 +0,0 @@ ---- -kind: TrafficTarget -apiVersion: access.smi-spec.io/v1alpha3 -metadata: - name: bookstore-access-bookwarehouse - namespace: bookwarehouse -spec: - destination: - kind: ServiceAccount - name: bookwarehouse - namespace: bookwarehouse - rules: - - kind: HTTPRouteGroup - name: bookwarehouse-service-routes - matches: - - restock-books - sources: - - kind: ServiceAccount - name: bookstore - namespace: bookstore ---- -apiVersion: specs.smi-spec.io/v1alpha4 -kind: HTTPRouteGroup -metadata: - name: bookwarehouse-service-routes - namespace: bookwarehouse -spec: - matches: - - name: restock-books - methods: - - POST \ No newline at end of file diff --git a/cloud-native/aks-open-service-mesh/03-applying-zero-trust/smi-traffic-to-mysql.yaml b/cloud-native/aks-open-service-mesh/03-applying-zero-trust/smi-traffic-to-mysql.yaml deleted file mode 100644 index 6996b3e..0000000 --- a/cloud-native/aks-open-service-mesh/03-applying-zero-trust/smi-traffic-to-mysql.yaml +++ /dev/null @@ -1,27 +0,0 @@ -kind: TrafficTarget -apiVersion: access.smi-spec.io/v1alpha3 -metadata: - name: mysql - namespace: bookwarehouse -spec: - destination: - kind: ServiceAccount - name: mysql - namespace: bookwarehouse - rules: - - kind: TCPRoute - name: mysql - sources: - - kind: ServiceAccount - name: bookwarehouse - namespace: bookwarehouse ---- -apiVersion: specs.smi-spec.io/v1alpha4 -kind: TCPRoute -metadata: - name: mysql - namespace: bookwarehouse -spec: - matches: - ports: - - 3306 diff --git a/cloud-native/aks-open-service-mesh/04-osm-traffic-splitting/README.md b/cloud-native/aks-open-service-mesh/04-osm-traffic-splitting/README.md deleted file mode 100644 index cc6921d..0000000 --- a/cloud-native/aks-open-service-mesh/04-osm-traffic-splitting/README.md +++ /dev/null @@ -1,134 +0,0 @@ -# Part 4: Traffic splitting with OSM - -Another core component of OSM is [traffic splitting][osm_traffic_splitting] which allows you to implement a/b testing, blue-green deployment, or canary deployment practices. - -Please ensure you have completed the steps in [Part 3: Applying Zero-Trust to the Bookstore application](../03-applying-zero-trust/README.md) before you proceed. - -Make sure you are in the right working directory (this command assumes you are currently in the `cloud-native/aks-open-service-mesh/03-applying-zero-trust/` directory).: - -```bash -cd ../04-osm-traffic-splitting -``` - -Deploy a new version of bookstore (`bookstore-v2`). - -```bash -kubectl apply -f https://raw.githubusercontent.com/openservicemesh/osm-docs/release-v1.2/manifests/apps/bookstore-v2.yaml -``` - -Inspect the resources within `bookstore` namespace to see what is new. - -```bash -kubectl get all -n bookstore -``` - -You should see output similar to the following: - -```text -NAME READY STATUS RESTARTS AGE -pod/bookstore-97956675d-dfrlq 2/2 Running 0 84m -pod/bookstore-v2-6ccc9b8746-cqxn6 2/2 Running 0 45s - -NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE -service/bookstore ClusterIP 10.0.132.170 14001/TCP 84m -service/bookstore-v1 ClusterIP 10.0.181.65 14001/TCP 84m -service/bookstore-v2 ClusterIP 10.0.117.98 14001/TCP 46s - -NAME READY UP-TO-DATE AVAILABLE AGE -deployment.apps/bookstore 1/1 1 1 84m -deployment.apps/bookstore-v2 1/1 1 1 45s - -NAME DESIRED CURRENT READY AGE -replicaset.apps/bookstore-97956675d 1 1 1 84m -replicaset.apps/bookstore-v2-6ccc9b8746 1 1 1 45s -``` - -With the new version of `bookstore` running, we can use the `TrafficSplit` CRD to split traffic evenly between `bookstore-v1` and `bookstore-v2` backend services. - -```yml -apiVersion: split.smi-spec.io/v1alpha2 -kind: TrafficSplit -metadata: - name: bookstore-split - namespace: bookstore -spec: - service: bookstore.bookstore # . - backends: - - service: bookstore-v1 # matches app:bookstore,version:v1 - weight: 50 - - service: bookstore-v2 # matches app:bookstore,version:v2 - weight: 50 -``` - -Run the following command to evenly split the traffic. - -```bash -kubectl apply -f https://raw.githubusercontent.com/openservicemesh/osm-docs/release-v1.2/manifests/split/traffic-split-50-50.yaml -``` - -If you take a look at our **bookbuyer** web page again, you will see both versions of the **bookstore** are selling books. - -> If you do not have the **bookbuyer** app, run the following commands to retrieve the URL and open in a web browser - -```bash -nginx_ingress_host="$(kubectl -n app-routing-system get service nginx -o jsonpath='{.status.loadBalancer.ingress[0].ip}')" - -# these are the urls you should open in your browser -echo http://$nginx_ingress_host/bookbuyer -echo http://$nginx_ingress_host/bookthief -echo http://$nginx_ingress_host/bookstore -``` - -![bookstore split](./bookstore-split.png) - -After some testing you are now ready to cutover all traffic from v1 to v2. Run the following command up distribute 100% of the traffic to v2. - -```bash -kubectl apply -f https://raw.githubusercontent.com/openservicemesh/osm-docs/release-v1.2/manifests/split/traffic-split-v2.yaml -``` - -If you take a look at our **bookbuyer** web page again, we can see only **bookstore-v2** is selling books. - -With **bookstore-v1** no longer taking any requests, lets redeploy the `service`, `ingress`, and `ingressbackend` and point them all to **bookstore-v2**. - -```bash -kubectl apply -f bookstore-ui-v2.yaml -``` - -Navigate back to the **bookstore** app in your web browser and you will now see `bookstore-v2` with an incrementing counter. - -> You might need to refresh the **bookstore** app. - -![bookstore-v2](./bookstore-v2.png) - -## Wrap up and next steps - -In this multi-part lab, we deployed an AKS cluster using Bicep and enabled the Web Application Routing and Open Service Mesh add-ons. These open-source components can be installed in your cluster manually; however, when you enable them as add-ons, they are managed by the Azure platform and are fully supported. - -There's more to OSM than what we explored in this lab. We only controlled traffic from an ingress perspective but with OSM, you can also control [egress traffic][osm_egress]. You can also implement patterns and practices to help with application resiliency using techniques like [rate limiting][osm_rate_limiting], [retry][osm_retry], and [circuit breakers][osm_circuit_breaker]. I encourage you to visit the links in the resources section below to learn and implement more. - -Once you have finished exploring, you should delete the deployment to avoid any further charges. - -```bash -az group delete --name rg-${name} --yes -``` - -If you found this lab helpful, please give the repo a ⭐️ or let us know your questions or feedback by filing a [new issue](https://github.com/Azure-Samples/azure-opensource-labs/issues/new), or joining the Discord in the [README](https://github.com/Azure-Samples/azure-opensource-labs#azure-open-source-labs). - -Cheers! - -## Resources - -* [Traffic Splitting][osm_traffic_splitting] -* [Canary Rollouts using SMI Traffic Split][osm_canary_rollouts] -* [Rate Limiting][osm_rate_limiting] -* [Retry][osm_retry] -* [Circuit Breaking][osm_circuit_breaker] - - -[osm_traffic_splitting]:https://release-v1-2.docs.openservicemesh.io/docs/guides/traffic_management/traffic_split -[osm_canary_rollouts]:https://release-v1-2.docs.openservicemesh.io/docs/demos/canary_rollout -[osm_egress]:https://release-v1-2.docs.openservicemesh.io/docs/guides/traffic_management/egress/ -[osm_circuit_breaker]:https://release-v1-2.docs.openservicemesh.io/docs/guides/traffic_management/circuit_breaking/ -[osm_retry]:https://release-v1-2.docs.openservicemesh.io/docs/guides/traffic_management/retry_policy/ -[osm_rate_limiting]:https://release-v1-2.docs.openservicemesh.io/docs/guides/traffic_management/rate_limiting/ \ No newline at end of file diff --git a/cloud-native/aks-open-service-mesh/04-osm-traffic-splitting/bookstore-split.png b/cloud-native/aks-open-service-mesh/04-osm-traffic-splitting/bookstore-split.png deleted file mode 100644 index 16ed14d..0000000 Binary files a/cloud-native/aks-open-service-mesh/04-osm-traffic-splitting/bookstore-split.png and /dev/null differ diff --git a/cloud-native/aks-open-service-mesh/04-osm-traffic-splitting/bookstore-ui-v2.yaml b/cloud-native/aks-open-service-mesh/04-osm-traffic-splitting/bookstore-ui-v2.yaml deleted file mode 100644 index 26851ec..0000000 --- a/cloud-native/aks-open-service-mesh/04-osm-traffic-splitting/bookstore-ui-v2.yaml +++ /dev/null @@ -1,51 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: bookstore - namespace: bookstore - labels: - app: bookstore - service: bookstore -spec: - ports: - - name: http - port: 14001 - selector: - app: bookstore - version: v2 ---- -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: bookstore - namespace: bookstore - annotations: - nginx.ingress.kubernetes.io/rewrite-target: / -spec: - ingressClassName: webapprouting.kubernetes.azure.com # managed nginx ingress class name - rules: - - http: - paths: - - path: /bookstore - pathType: Prefix - backend: - service: - name: bookstore - port: - number: 14001 ---- -apiVersion: policy.openservicemesh.io/v1alpha1 -kind: IngressBackend -metadata: - name: bookstore - namespace: bookstore -spec: - backends: - - name: bookstore - port: - number: 14001 # targetPort of bookstore service - protocol: http - sources: - - kind: Service - namespace: app-routing-system - name: nginx \ No newline at end of file diff --git a/cloud-native/aks-open-service-mesh/04-osm-traffic-splitting/bookstore-v2.png b/cloud-native/aks-open-service-mesh/04-osm-traffic-splitting/bookstore-v2.png deleted file mode 100644 index c4293ed..0000000 Binary files a/cloud-native/aks-open-service-mesh/04-osm-traffic-splitting/bookstore-v2.png and /dev/null differ diff --git a/cloud-native/aks-open-service-mesh/README.md b/cloud-native/aks-open-service-mesh/README.md deleted file mode 100644 index 9982324..0000000 --- a/cloud-native/aks-open-service-mesh/README.md +++ /dev/null @@ -1,275 +0,0 @@ -# Azure Kubernetes Service with Open Service Mesh - -In this multi-part lab, you will deploy an [AKS][aks] cluster with the [Web Application Routing (Preview)][aks_addon_web_app_routing] and [Open Service Mesh (OSM)][aks_addon_osm] add-ons enabled. These add-ons are open-source components that are installed and managed by the AKS platform. OSM can be installed on any Kubernetes cluster (see [guide](https://release-v1-2.docs.openservicemesh.io/docs/getting_started/install_apps/)); however, in this lab, you will explore the AKS-managed version and demonstrate how it integrates with other components. - -We'll start by deploying the [OSM Bookstore sample application][osm_bookstore_sample] to the AKS cluster, expose the web applications via the managed ingress controller then configure OSM to secure traffic between the ingress controller and backend services (as well as inter-mesh communications). - -## Requirements - -* An Azure Subscription (e.g. [Free](https://aka.ms/azure-free-account) or [Student](https://aka.ms/azure-student-account) account) -* The [Azure CLI](https://docs.microsoft.com/cli/azure/install-azure-cli) with [Bicep](https://learn.microsoft.com/azure/azure-resource-manager/bicep/install#azure-cli) installed -* A [GitHub](https://github.com/) account -* The [`kubectl` CLI](https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/) -* Bash shell (e.g. macOS, Linux, [Windows Subsystem for Linux (WSL)](https://docs.microsoft.com/windows/wsl/about), [Multipass](https://multipass.run/), [Azure Cloud Shell](https://docs.microsoft.com/azure/cloud-shell/quickstart), [GitHub Codespaces](https://github.com/features/codespaces), etc) -* The [`osm` CLI](https://learn.microsoft.com/azure/aks/open-service-mesh-binary?pivots=client-operating-system-linux) - -## Deploy Azure Resources - -[![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure-Samples%2Fazure-opensource-labs%2Fmain%2Fcloud-native%2Faks-open-service-mesh%2Fmain.json) - -> Use the button above if you'd like to deploy using the Azure Portal instead of Azure CLI commands. - -Clone this repo and drop into the `aks-open-service-mesh` directory. - -```bash -git clone https://github.com/Azure-Samples/azure-opensource-labs.git -cd azure-opensource-labs/cloud-native/aks-open-service-mesh -``` - -Before you proceed, ensure you have the `Microsoft.ContainerService` and `Microsoft.Insights` providers registered. - -```bash -az provider register --namespace Microsoft.ContainerService -az provider register --namespace Microsoft.Insights -``` - -Open a terminal and initialize the following variables which will be passed into the deployment. - -```bash -# azure region where resources will be deployed to -location=eastus -# random name that will be used for azure resources -name=books$RANDOM -# get the latest (n-1) version of kubernetes -kubernetesVersion=$(az aks get-versions -l $location --out tsv --query 'orchestrators[-1].orchestratorVersion') -# kubernetes node count -systemNodeCount=3 -# azure vm size for nodes -systemNodeSize=Standard_D4s_v5 -# get your user name -userName=$(az account show --out tsv --query user.name) -# get your user principal id -userObjectId=$(az ad user show --id $userName --out tsv --query id) -``` - -Deploy Azure infrastructure with the Bicep template. - -> Take a look at this [blog post](https://dev.to/azure/sharing-bicep-modules-with-azure-container-registry-4mo0) to see how the Bicep modules are put together. - -```bash -az deployment sub create \ - --name "$name-deploy" \ - --location $location \ - --template-file main.bicep \ - --parameters \ - name=$name \ - location=$location \ - kubernetesVersion=$kubernetesVersion \ - systemNodeCount=$systemNodeCount \ - systemNodeSize=$systemNodeSize \ - userObjectId=$userObjectId -``` - -The template will deploy the following resources into your subscription: - -* [Azure Resource Group][rg] to deploy resources into -* [Azure Log Analytics Workspace][law] to serve as a data store for the monitoring add-on -* [Azure Kubernetes Service][aks] your managed Kubernetes cluster with [`kubenet`][kubenet] as the container network plugin, [`calico`][calico] for network policy, and the following [AKS add-ons][aks_addons] - * [`azure-keyvault-secrets-provider`](https://learn.microsoft.com/azure/aks/csi-secrets-store-driver) - * [`monitoring`](https://learn.microsoft.com/azure/azure-monitor/containers/container-insights-overview) - * [`open-service-mesh`](https://learn.microsoft.com/azure/aks/open-service-mesh-about) - * [`web_application_routing`](https://learn.microsoft.com/azure/aks/web-app-routing?tabs=with-osm) - -## Validate the Azure deployment - -View a list of resources deployed in your resource group by running the following command or view from the [Azure Portal](https://portal.azure.com): - -```bash -az resource list \ - --resource-group rg-${name} \ - --out table -``` - -To view the AKS add-ons that have been installed and its configurations, run the command below: - -```bash -az aks show \ - --resource-group rg-${name} \ - --name aks-${name} \ - --query "addonProfiles" -``` - -## Validate access to the Kubernetes cluster - -Before you pull down credentials from AKS make sure you have `kubectl` CLI locally. - -> If you do not have `kubectl` installed yet, run the `az aks install-cli` to install it using Azure CLI. - -Authenticate `kubectl` against the AKS cluster. - -```bash -az aks get-credentials \ - --resource-group rg-${name} \ - --name aks-${name} -``` - -Verify you have access to the cluster. - -```bash -kubectl cluster-info -``` - -## Validate OSM resources and configurations - -Now let's check the OSM add-on is enabled by running the following command and ensure `openServiceMesh` has the `enabled` property set to `true`. - -```bash -az aks show \ - --resource-group rg-${name} \ - --name aks-${name} \ - --query "addonProfiles.openServiceMesh" -``` - -Next, run the following command to check the OSM resources have been deployed into your cluster successfully. - -```bash -kubectl api-resources | grep openservicemesh -``` - -You should see output similar to the following: - -```text -meshconfigs meshconfig config.openservicemesh.io/v1alpha2 true MeshConfig -meshrootcertificates mrc config.openservicemesh.io/v1alpha2 true MeshRootCertificate -egresses egress policy.openservicemesh.io/v1alpha1 true Egress -ingressbackends ingressbackend policy.openservicemesh.io/v1alpha1 true IngressBackend -retries retry policy.openservicemesh.io/v1alpha1 true Retry -upstreamtrafficsettings upstreamtrafficsetting policy.openservicemesh.io/v1alpha1 true UpstreamTrafficSetting -``` - -OSM installs several new [Custom Resource Definitions (CRDs)](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/) as part of its implementation. - -Let's view OSM deployments by querying for deployments that start with `osm`. - -```bash -kubectl get deploy -A | grep osm -``` - -You should see output similar to this: - -```text -kube-system osm-bootstrap 1/1 1 1 132m -kube-system osm-controller 2/2 2 2 132m -kube-system osm-injector 2/2 2 2 132m -``` - -Here is a high-level overview of the [OSM components][osm] that are installed: - -* `osm-bootstrap` runs on a single node and is responsible for installing itself in the cluster and installing CRDs -* `osm-controller` runs on all nodes and is the control plane of the service mesh -* `osm-injecter` runs on all nodes and is responsible for injecting data plane components (i.e., Envoy proxy sidecars) into application pods - -These resources are typically [installed manually using the OSM CLI command `osm install`](https://release-v1-2.docs.openservicemesh.io/docs/getting_started/setup_osm/#installing-osm-on-kubernetes). However, with the AKS add-on, the installation and configuration is done for you. When OSM is deployed with the Web Application Routing add-on, Azure automatically adds additional configuration to allow NGINX and OSM to work together. - -> With open-source OSM, you have an option on the namespace where `osm` is installed (normally in the `osm-system` namespace), but since this is managed by AKS, it has been installed in the `kube-system` namespace for you. - -To view the default configuration for OSM, you can run the following command. - -```bash -kubectl get meshconfig osm-mesh-config -n kube-system -o yaml -``` - -Pay special attention to the `traffic` configuration; a snippet has been included below. - -```text -... -traffic: - enableEgress: true - enablePermissiveTrafficPolicyMode: true - inboundExternalAuthorization: - enable: false - failureModeAllow: false - statPrefix: inboundExtAuthz - timeout: 1s -... -``` - -The `enablePermissiveTrafficPolicyMode` has been set to `true`. This is the default configuration and when set to `true`, pods enrolled in the service mesh communicate freely. For more info on this see: [Permissive Traffic Policy Mode][osm_permissive_traffic_policy] - -### Namespaces are vital to OSM - -Applications are added to OSM based on namespaces. By binding to [Kubernetes namespaces](https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/), the OSM controller labels and annotates these resources so that it can discover and manage data plane components of the mesh. - -Run this command to view the services meshes deployed withing OSM. - -```bash -osm mesh list -``` - -You should see output similar to the following: - -```text -MESH NAME MESH NAMESPACE VERSION ADDED NAMESPACES -osm kube-system v1.2.1 app-routing-system - -MESH NAME MESH NAMESPACE SMI SUPPORTED -osm kube-system HTTPRouteGroup:v1alpha4,TCPRoute:v1alpha4,TrafficSplit:v1alpha2,TrafficTarget:v1alpha3 - -To list the OSM controller pods for a mesh, please run the following command passing in the mesh's namespace - kubectl get pods -n -l app=osm-controller -``` - -> Note the Service Mesh Interface (SMI) specs that are supported by OSM. These may be subject to change with the ongoing dialog on the [GAMMA Initiative](https://gateway-api.sigs.k8s.io/contributing/gamma/) within the community. - -As suggested in the output above, let's get a list of OSM controller pods. - -```bash -kubectl get pods -n kube-system -l app=osm-controller -``` - -Run this command to view the namespaces OSM is currently monitoring: - -```bash -osm namespace list -``` - -You should see output similar to the following: - -```text -NAMESPACE MESH SIDECAR-INJECTION -app-routing-system osm disabled -``` - -As mentioned above, you have added both the `web_application_routing` and `open-service-mesh` add-ons and Azure has automatically configured OSM to monitor the NGINX ingress controller's namespace 🎉 - -One important thing to note in the output above is that `SIDECAR-INJECTION` has been set to `disabled`. OSM integration with NGINX requires monitoring of the ingress controller's namespace for service discovery and management of ingress endpoints to backend services. However, OSM should not inject sidecars into the NGINX pods to function properly. - -Now, let's inspect the namespace labels added by OSM. - -```bash -kubectl get namespace --show-labels | grep openservicemesh.io/monitored-by=osm -``` - -## Next steps - -You have successfully deployed the AKS cluster and inspected how the Web Application Routing and OSM add-ons are deployed and configured in the cluster. The cluster is now ready for application deployments. - -Head over to [Part 2: Bookstore application deployment](./02-deploying-bookstore-app/README.md) to deploy our first app. - -## Resources - -* [AKS Add-On: Web Application Routing (Preview)][aks_addon_web_app_routing] -* [AKS Add-On: Open Service Mesh][aks_addon_osm] - - -[aks_addons]:https://learn.microsoft.com/azure/aks/integrations#available-add-ons -[aks_addon_osm]:https://learn.microsoft.com/azure/aks/open-service-mesh-about -[aks_addon_web_app_routing]:https://learn.microsoft.com/azure/aks/web-app-routing?tabs=with-osm -[osm]:https://release-v1-2.docs.openservicemesh.io/docs/overview/about/ -[osm_bookstore_sample]:https://release-v1-2.docs.openservicemesh.io/docs/getting_started/install_apps/ -[osm_permissive_traffic_policy]:https://release-v1-2.docs.openservicemesh.io/docs/guides/traffic_management/permissive_mode/ -[kubenet]:https://learn.microsoft.com/azure/aks/configure-kubenet -[calico]:https://projectcalico.docs.tigera.io/security/kubernetes-policy -[rg]:https://learn.microsoft.com/azure/azure-resource-manager/management/manage-resource-groups-portal#what-is-a-resource-group -[law]:https://learn.microsoft.com/azure/azure-monitor/logs/log-analytics-workspace-overview -[aks]:https://learn.microsoft.com/azure/aks/intro-kubernetes diff --git a/cloud-native/aks-open-service-mesh/bicepconfig.json b/cloud-native/aks-open-service-mesh/bicepconfig.json deleted file mode 100644 index 91b4f8a..0000000 --- a/cloud-native/aks-open-service-mesh/bicepconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "moduleAliases": { - "ts": {}, - "br": { - "oss-labs": { - "registry": "cloudnativeadvocates.azurecr.io" - } - } - } -} \ No newline at end of file diff --git a/cloud-native/aks-open-service-mesh/main.bicep b/cloud-native/aks-open-service-mesh/main.bicep deleted file mode 100644 index cbb3f5c..0000000 --- a/cloud-native/aks-open-service-mesh/main.bicep +++ /dev/null @@ -1,142 +0,0 @@ -targetScope = 'subscription' - -param name string -param location string -param tags object = {} - -param kubernetesVersion string = '1.29' -param systemNodeCount int = 3 -param systemNodeSize string = 'Standard_D4s_v5' - -param userObjectId string -// param dnsName string - -var networkPlugin = 'kubenet' -var networkPolicy = 'calico' - -// Set up the resource group -resource rg 'Microsoft.Resources/resourceGroups@2021-04-01' = { - name: 'rg-${name}' - location: location - tags: tags -} - -module kv '../../bicep/modules/azure-key-vault/main.bicep' = { - scope: rg - name: 'akvDeploy' - params: { - location: location - name: 'akv-${name}' - sku: 'standard' - tags: tags - userObjectId: userObjectId - tenantId: tenant().tenantId - } -} - -// Setup the log analytics workspace -module law '../../bicep/modules/azure-log-analytics-workspace/main.bicep' = { - scope: rg - name: 'lawDeploy' - params: { - name: 'law-${name}' - location: location - tags: tags - } -} - -// Setup the Kubernetes cluster -module aks '../../bicep/modules/azure-kubernetes-service/main.bicep' = { - scope: rg - name: 'aksDeploy' - params: { - name: 'aks-${name}' - location: location - tags: tags - slaTier: 'Free' - managedIdentityType: 'SystemAssigned' - kubernetesVersion: kubernetesVersion - networkPlugin: networkPlugin - networkPolicy: networkPolicy - loadBalancerSku: 'Standard' - outboundType: 'loadBalancer' - dnsServiceIP: '10.0.0.10' - podCidrs: [ - '10.244.0.0/16' - ] - serviceCidrs: [ - '10.0.0.0/16' - ] - ipFamilies: [ - 'IPv4' - ] - defenderEnabled: false - imageCleanerEnabled: false - systemNodeCount: systemNodeCount - systemNodeVmSize: systemNodeSize - // registryName: acr.outputs.name - addonProfiles: { - omsagent: { - config: { - logAnalyticsWorkspaceResourceID: law.outputs.id - } - enabled: true - } - } - } -} - -// Deploy the key vault secrets provider add-on -module aksAddonKv '../../bicep/modules/azure-kubernetes-service-addons/main.bicep' = { - scope: rg - name: 'aksAddonKvDeploy' - params: { - location: location - clusterId: aks.outputs.id - addonProfiles: { - azureKeyvaultSecretsProvider: { - config: { - enableSecretRotation: 'true' - rotationPollInterval: '2m' - } - enabled: true - } - } - } - dependsOn: [ - aks - kv - ] -} - -// Deploy the web app routing add-on -module aksAddonIng '../../bicep/modules/azure-kubernetes-service-ingress/main.bicep' = { - scope: rg - name: 'aksAddonIngDeploy' - params: { - location: location - clusterId: aks.outputs.id - } - dependsOn: [ - aksAddonKv - ] -} - -// Deploy the open service mesh add-on -module aksAddonOsm '../../bicep/modules/azure-kubernetes-service-addons/main.bicep' = { - scope: rg - name: 'aksAddonOsmDeploy' - params: { - location: location - clusterId: aks.outputs.id - addonProfiles: { - openServiceMesh: { - config: {} - enabled: true - } - } - } - dependsOn: [ - aksAddonIng - ] -} diff --git a/cloud-native/aks-open-service-mesh/main.json b/cloud-native/aks-open-service-mesh/main.json deleted file mode 100644 index d27dc41..0000000 --- a/cloud-native/aks-open-service-mesh/main.json +++ /dev/null @@ -1,874 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "10734555654774304097" - } - }, - "parameters": { - "name": { - "type": "string" - }, - "location": { - "type": "string" - }, - "tags": { - "type": "object", - "defaultValue": {} - }, - "kubernetesVersion": { - "type": "string", - "defaultValue": "1.29" - }, - "systemNodeCount": { - "type": "int", - "defaultValue": 3 - }, - "systemNodeSize": { - "type": "string", - "defaultValue": "Standard_D4s_v5" - }, - "userObjectId": { - "type": "string" - } - }, - "variables": { - "networkPlugin": "kubenet", - "networkPolicy": "calico" - }, - "resources": [ - { - "type": "Microsoft.Resources/resourceGroups", - "apiVersion": "2021-04-01", - "name": "[format('rg-{0}', parameters('name'))]", - "location": "[parameters('location')]", - "tags": "[parameters('tags')]" - }, - { - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "akvDeploy", - "resourceGroup": "[format('rg-{0}', parameters('name'))]", - "properties": { - "expressionEvaluationOptions": { - "scope": "inner" - }, - "mode": "Incremental", - "parameters": { - "location": { - "value": "[parameters('location')]" - }, - "name": { - "value": "[format('akv-{0}', parameters('name'))]" - }, - "sku": { - "value": "standard" - }, - "tags": { - "value": "[parameters('tags')]" - }, - "userObjectId": { - "value": "[parameters('userObjectId')]" - }, - "tenantId": { - "value": "[tenant().tenantId]" - } - }, - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "6723983789050081110" - } - }, - "parameters": { - "name": { - "type": "string" - }, - "location": { - "type": "string" - }, - "tags": { - "type": "object" - }, - "sku": { - "type": "string", - "defaultValue": "standard", - "allowedValues": [ - "premium", - "standard" - ] - }, - "userObjectId": { - "type": "string", - "metadata": { - "description": "The object ID of a user, service principal or security group in AAD tenant." - } - }, - "tenantId": { - "type": "string" - }, - "accessPolicies": { - "type": "array", - "defaultValue": [], - "metadata": { - "description": "List of AccessPolicyEntry which is used when granting additional permissions for other users or managed identities" - } - } - }, - "resources": [ - { - "type": "Microsoft.KeyVault/vaults", - "apiVersion": "2022-07-01", - "name": "[parameters('name')]", - "location": "[parameters('location')]", - "tags": "[parameters('tags')]", - "properties": { - "accessPolicies": [ - { - "objectId": "[parameters('userObjectId')]", - "permissions": { - "certificates": [ - "all" - ], - "keys": [ - "all" - ], - "secrets": [ - "all" - ], - "storage": [ - "all" - ] - }, - "tenantId": "[parameters('tenantId')]" - } - ], - "sku": { - "family": "A", - "name": "[parameters('sku')]" - }, - "tenantId": "[parameters('tenantId')]" - } - }, - { - "condition": "[not(empty(parameters('accessPolicies')))]", - "type": "Microsoft.KeyVault/vaults/accessPolicies", - "apiVersion": "2022-07-01", - "name": "[format('{0}/{1}', parameters('name'), 'add')]", - "properties": { - "accessPolicies": "[parameters('accessPolicies')]" - }, - "dependsOn": [ - "[resourceId('Microsoft.KeyVault/vaults', parameters('name'))]" - ] - } - ] - } - }, - "dependsOn": [ - "[subscriptionResourceId('Microsoft.Resources/resourceGroups', format('rg-{0}', parameters('name')))]" - ] - }, - { - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "lawDeploy", - "resourceGroup": "[format('rg-{0}', parameters('name'))]", - "properties": { - "expressionEvaluationOptions": { - "scope": "inner" - }, - "mode": "Incremental", - "parameters": { - "name": { - "value": "[format('law-{0}', parameters('name'))]" - }, - "location": { - "value": "[parameters('location')]" - }, - "tags": { - "value": "[parameters('tags')]" - } - }, - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "4630854867665059244" - } - }, - "parameters": { - "name": { - "type": "string" - }, - "location": { - "type": "string" - }, - "tags": { - "type": "object" - } - }, - "resources": [ - { - "type": "Microsoft.OperationalInsights/workspaces", - "apiVersion": "2021-12-01-preview", - "name": "[parameters('name')]", - "location": "[parameters('location')]", - "tags": "[parameters('tags')]", - "properties": { - "retentionInDays": 30, - "sku": { - "name": "PerGB2018" - } - } - } - ], - "outputs": { - "id": { - "type": "string", - "value": "[resourceId('Microsoft.OperationalInsights/workspaces', parameters('name'))]" - } - } - } - }, - "dependsOn": [ - "[subscriptionResourceId('Microsoft.Resources/resourceGroups', format('rg-{0}', parameters('name')))]" - ] - }, - { - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "aksDeploy", - "resourceGroup": "[format('rg-{0}', parameters('name'))]", - "properties": { - "expressionEvaluationOptions": { - "scope": "inner" - }, - "mode": "Incremental", - "parameters": { - "name": { - "value": "[format('aks-{0}', parameters('name'))]" - }, - "location": { - "value": "[parameters('location')]" - }, - "tags": { - "value": "[parameters('tags')]" - }, - "slaTier": { - "value": "Free" - }, - "managedIdentityType": { - "value": "SystemAssigned" - }, - "kubernetesVersion": { - "value": "[parameters('kubernetesVersion')]" - }, - "networkPlugin": { - "value": "[variables('networkPlugin')]" - }, - "networkPolicy": { - "value": "[variables('networkPolicy')]" - }, - "loadBalancerSku": { - "value": "Standard" - }, - "outboundType": { - "value": "loadBalancer" - }, - "dnsServiceIP": { - "value": "10.0.0.10" - }, - "podCidrs": { - "value": [ - "10.244.0.0/16" - ] - }, - "serviceCidrs": { - "value": [ - "10.0.0.0/16" - ] - }, - "ipFamilies": { - "value": [ - "IPv4" - ] - }, - "defenderEnabled": { - "value": false - }, - "imageCleanerEnabled": { - "value": false - }, - "systemNodeCount": { - "value": "[parameters('systemNodeCount')]" - }, - "systemNodeVmSize": { - "value": "[parameters('systemNodeSize')]" - }, - "addonProfiles": { - "value": { - "omsagent": { - "config": { - "logAnalyticsWorkspaceResourceID": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, format('rg-{0}', parameters('name'))), 'Microsoft.Resources/deployments', 'lawDeploy'), '2022-09-01').outputs.id.value]" - }, - "enabled": true - } - } - } - }, - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "5599997474738078815" - } - }, - "parameters": { - "name": { - "type": "string" - }, - "location": { - "type": "string" - }, - "tags": { - "type": "object" - }, - "slaTier": { - "type": "string", - "defaultValue": "Free", - "allowedValues": [ - "Free", - "Paid" - ], - "metadata": { - "description": "Defaults to Free tier" - } - }, - "managedIdentityType": { - "type": "string", - "defaultValue": "SystemAssigned", - "allowedValues": [ - "SystemAssigned", - "UserAssigned" - ], - "metadata": { - "description": "Two options are available: SystemAssigned or UserAssigned" - } - }, - "userAssignedIdentities": { - "type": "object", - "defaultValue": {}, - "metadata": { - "description": "Required when managed identity type is set to UserAssigned" - } - }, - "kubernetesVersion": { - "type": "string", - "defaultValue": "1.29", - "metadata": { - "description": "Default is 1.29" - } - }, - "defenderEnabled": { - "type": "bool", - "defaultValue": false - }, - "imageCleanerEnabled": { - "type": "bool", - "defaultValue": false - }, - "imageCleanerIntervalHours": { - "type": "int", - "defaultValue": 12 - }, - "systemNodeCount": { - "type": "int", - "defaultValue": 3 - }, - "systemNodeVmSize": { - "type": "string", - "defaultValue": "Standard_D2s_v5", - "metadata": { - "description": "Default system node pool size is Standard_D2s_v5" - } - }, - "registryName": { - "type": "string", - "defaultValue": "", - "metadata": { - "description": "Optional parameter to attach AKS cluster to an existing ACR" - } - }, - "networkPlugin": { - "type": "string", - "defaultValue": "kubenet", - "allowedValues": [ - "kubenet", - "azure", - "none" - ], - "metadata": { - "description": "Network plugin used for building the Kubernetes network." - } - }, - "networkPolicy": { - "type": "string", - "defaultValue": "calico", - "allowedValues": [ - "calico", - "azure" - ], - "metadata": { - "description": "Network policy used for building the Kubernetes network." - } - }, - "loadBalancerSku": { - "type": "string", - "defaultValue": "Standard", - "allowedValues": [ - "Standard", - "Basic" - ], - "metadata": { - "description": "The default is standard." - } - }, - "dnsServiceIP": { - "type": "string", - "defaultValue": "10.0.0.10", - "metadata": { - "description": "An IP address assigned to the Kubernetes DNS service. It must be within the Kubernetes service address range specified in serviceCidr." - } - }, - "dockerBridgeCidr": { - "type": "string", - "defaultValue": "172.17.0.1/16", - "metadata": { - "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." - } - }, - "logAnalyticsWorkspaceResourceId": { - "type": "string", - "defaultValue": "", - "metadata": { - "description": "Resource ID of log analytics workspace for auditing" - } - }, - "outboundType": { - "type": "string", - "defaultValue": "loadBalancer", - "allowedValues": [ - "loadBalancer", - "managedNATGateway", - "userAssignedNATGateway", - "userDefinedRouting" - ], - "metadata": { - "description": "This can only be set at cluster creation time and cannot be changed later." - } - }, - "podCidrs": { - "type": "array", - "defaultValue": [ - "10.244.0.0/16" - ], - "metadata": { - "description": "One IPv4 CIDR is expected for single-stack networking. Two CIDRs, one for each IP family (IPv4/IPv6), is expected for dual-stack networking." - } - }, - "serviceCidrs": { - "type": "array", - "defaultValue": [ - "10.0.0.0/16" - ], - "metadata": { - "description": "One IPv4 CIDR is expected for single-stack networking. Two CIDRs, one for each IP family (IPv4/IPv6), is expected for dual-stack networking. They must not overlap with any Subnet IP ranges." - } - }, - "ipFamilies": { - "type": "array", - "defaultValue": [ - "IPv4" - ], - "allowedValues": [ - "IPv4", - "IPv6" - ] - }, - "vnetSubnetID": { - "type": "string", - "defaultValue": "", - "metadata": { - "description": "If the cluster is using azure network plugin, then you can pass in the subnet resource ID like this `vnet.outputs.subnetId`; otherwise, leave it empty" - } - }, - "nodeTaints": { - "type": "array", - "defaultValue": [], - "metadata": { - "description": "Enable nodeTaints on the system node pool (e.g., ['CriticalAddonsOnly=true:NoSchedule'])" - } - }, - "addonProfiles": { - "type": "object", - "defaultValue": {}, - "metadata": { - "description": "AKS addons to enable" - } - }, - "enablePrometheusMetrics": { - "type": "bool", - "defaultValue": false - }, - "prometheusMetricLabelsAllowlist": { - "type": "string", - "defaultValue": "" - }, - "prometheusMetricAnnotationsAllowList": { - "type": "string", - "defaultValue": "" - } - }, - "resources": [ - { - "type": "Microsoft.ContainerService/managedClusters", - "apiVersion": "2022-08-03-preview", - "name": "[parameters('name')]", - "location": "[parameters('location')]", - "tags": "[parameters('tags')]", - "sku": { - "name": "Basic", - "tier": "[parameters('slaTier')]" - }, - "identity": { - "type": "[parameters('managedIdentityType')]", - "userAssignedIdentities": "[if(equals(parameters('managedIdentityType'), 'UserAssigned'), parameters('userAssignedIdentities'), null())]" - }, - "properties": { - "kubernetesVersion": "[parameters('kubernetesVersion')]", - "dnsPrefix": "[parameters('name')]", - "azureMonitorProfile": "[if(parameters('enablePrometheusMetrics'), createObject('metrics', createObject('enabled', true(), 'kubeStateMetrics', createObject('metricLabelsAllowlist', parameters('prometheusMetricLabelsAllowlist'), 'metricAnnotationsAllowList', parameters('prometheusMetricAnnotationsAllowList')))), null())]", - "networkProfile": { - "networkPlugin": "[parameters('networkPlugin')]", - "networkPolicy": "[parameters('networkPolicy')]", - "loadBalancerSku": "[parameters('loadBalancerSku')]", - "dnsServiceIP": "[parameters('dnsServiceIP')]", - "dockerBridgeCidr": "[parameters('dockerBridgeCidr')]", - "outboundType": "[parameters('outboundType')]", - "podCidrs": "[parameters('podCidrs')]", - "serviceCidrs": "[parameters('serviceCidrs')]", - "ipFamilies": "[parameters('ipFamilies')]" - }, - "agentPoolProfiles": [ - { - "name": "system", - "count": "[parameters('systemNodeCount')]", - "vmSize": "[parameters('systemNodeVmSize')]", - "mode": "System", - "vnetSubnetID": "[if(empty(parameters('vnetSubnetID')), null(), parameters('vnetSubnetID'))]", - "nodeTaints": "[if(empty(parameters('nodeTaints')), null(), parameters('nodeTaints'))]" - } - ], - "securityProfile": { - "defender": { - "securityMonitoring": { - "enabled": "[parameters('defenderEnabled')]" - } - }, - "imageCleaner": { - "enabled": "[parameters('imageCleanerEnabled')]", - "intervalHours": "[parameters('imageCleanerIntervalHours')]" - } - }, - "addonProfiles": "[parameters('addonProfiles')]" - } - }, - { - "condition": "[not(equals(parameters('registryName'), ''))]", - "type": "Microsoft.Authorization/roleAssignments", - "apiVersion": "2022-04-01", - "scope": "[format('Microsoft.ContainerRegistry/registries/{0}', parameters('registryName'))]", - "name": "[guid(resourceId('Microsoft.ContainerService/managedClusters', parameters('name')), parameters('registryName'))]", - "properties": { - "principalId": "[reference(resourceId('Microsoft.ContainerService/managedClusters', parameters('name')), '2022-08-03-preview').identityProfile.kubeletidentity.objectId]", - "roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')]" - }, - "dependsOn": [ - "[resourceId('Microsoft.ContainerService/managedClusters', parameters('name'))]" - ] - }, - { - "type": "Microsoft.Authorization/roleAssignments", - "apiVersion": "2022-04-01", - "name": "[guid(resourceId('Microsoft.ContainerService/managedClusters', parameters('name')), resourceGroup().id)]", - "properties": { - "principalId": "[reference(resourceId('Microsoft.ContainerService/managedClusters', parameters('name')), '2022-08-03-preview', 'full').identity.principalId]", - "roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]" - }, - "dependsOn": [ - "[resourceId('Microsoft.ContainerService/managedClusters', parameters('name'))]" - ] - } - ], - "outputs": { - "name": { - "type": "string", - "value": "[parameters('name')]" - }, - "id": { - "type": "string", - "value": "[resourceId('Microsoft.ContainerService/managedClusters', parameters('name'))]" - }, - "kubeletIdentityObjectId": { - "type": "string", - "value": "[reference(resourceId('Microsoft.ContainerService/managedClusters', parameters('name')), '2022-08-03-preview').identityProfile.kubeletidentity.objectId]" - }, - "nodeResourceGroupName": { - "type": "string", - "value": "[reference(resourceId('Microsoft.ContainerService/managedClusters', parameters('name')), '2022-08-03-preview').nodeResourceGroup]" - } - } - } - }, - "dependsOn": [ - "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, format('rg-{0}', parameters('name'))), 'Microsoft.Resources/deployments', 'lawDeploy')]", - "[subscriptionResourceId('Microsoft.Resources/resourceGroups', format('rg-{0}', parameters('name')))]" - ] - }, - { - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "aksAddonKvDeploy", - "resourceGroup": "[format('rg-{0}', parameters('name'))]", - "properties": { - "expressionEvaluationOptions": { - "scope": "inner" - }, - "mode": "Incremental", - "parameters": { - "location": { - "value": "[parameters('location')]" - }, - "clusterId": { - "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, format('rg-{0}', parameters('name'))), 'Microsoft.Resources/deployments', 'aksDeploy'), '2022-09-01').outputs.id.value]" - }, - "addonProfiles": { - "value": { - "azureKeyvaultSecretsProvider": { - "config": { - "enableSecretRotation": "true", - "rotationPollInterval": "2m" - }, - "enabled": true - } - } - } - }, - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "15950648950143392136" - } - }, - "parameters": { - "location": { - "type": "string" - }, - "clusterId": { - "type": "string" - }, - "addonProfiles": { - "type": "object", - "metadata": { - "description": "AKS addons to enable" - } - } - }, - "variables": { - "clusterName": "[split(parameters('clusterId'), '/')[8]]" - }, - "resources": [ - { - "type": "Microsoft.ContainerService/managedClusters", - "apiVersion": "2022-08-03-preview", - "name": "[variables('clusterName')]", - "location": "[parameters('location')]", - "properties": { - "mode": "Incremental", - "id": "[parameters('clusterId')]", - "addonProfiles": "[parameters('addonProfiles')]" - } - } - ] - } - }, - "dependsOn": [ - "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, format('rg-{0}', parameters('name'))), 'Microsoft.Resources/deployments', 'aksDeploy')]", - "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, format('rg-{0}', parameters('name'))), 'Microsoft.Resources/deployments', 'akvDeploy')]", - "[subscriptionResourceId('Microsoft.Resources/resourceGroups', format('rg-{0}', parameters('name')))]" - ] - }, - { - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "aksAddonIngDeploy", - "resourceGroup": "[format('rg-{0}', parameters('name'))]", - "properties": { - "expressionEvaluationOptions": { - "scope": "inner" - }, - "mode": "Incremental", - "parameters": { - "location": { - "value": "[parameters('location')]" - }, - "clusterId": { - "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, format('rg-{0}', parameters('name'))), 'Microsoft.Resources/deployments', 'aksDeploy'), '2022-09-01').outputs.id.value]" - } - }, - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "2186650111419086884" - } - }, - "parameters": { - "location": { - "type": "string" - }, - "clusterId": { - "type": "string" - }, - "dnsZoneResourceId": { - "type": "string", - "defaultValue": "" - } - }, - "variables": { - "clusterName": "[split(parameters('clusterId'), '/')[8]]", - "attachDnsZone": "[not(equals(parameters('dnsZoneResourceId'), ''))]" - }, - "resources": [ - { - "type": "Microsoft.ContainerService/managedClusters", - "apiVersion": "2022-08-03-preview", - "name": "[variables('clusterName')]", - "location": "[parameters('location')]", - "properties": { - "mode": "Incremental", - "id": "[parameters('clusterId')]", - "ingressProfile": { - "webAppRouting": { - "dnsZoneResourceId": "[if(variables('attachDnsZone'), parameters('dnsZoneResourceId'), null())]", - "enabled": true - } - } - } - } - ] - } - }, - "dependsOn": [ - "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, format('rg-{0}', parameters('name'))), 'Microsoft.Resources/deployments', 'aksDeploy')]", - "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, format('rg-{0}', parameters('name'))), 'Microsoft.Resources/deployments', 'aksAddonKvDeploy')]", - "[subscriptionResourceId('Microsoft.Resources/resourceGroups', format('rg-{0}', parameters('name')))]" - ] - }, - { - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "aksAddonOsmDeploy", - "resourceGroup": "[format('rg-{0}', parameters('name'))]", - "properties": { - "expressionEvaluationOptions": { - "scope": "inner" - }, - "mode": "Incremental", - "parameters": { - "location": { - "value": "[parameters('location')]" - }, - "clusterId": { - "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, format('rg-{0}', parameters('name'))), 'Microsoft.Resources/deployments', 'aksDeploy'), '2022-09-01').outputs.id.value]" - }, - "addonProfiles": { - "value": { - "openServiceMesh": { - "config": {}, - "enabled": true - } - } - } - }, - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "15950648950143392136" - } - }, - "parameters": { - "location": { - "type": "string" - }, - "clusterId": { - "type": "string" - }, - "addonProfiles": { - "type": "object", - "metadata": { - "description": "AKS addons to enable" - } - } - }, - "variables": { - "clusterName": "[split(parameters('clusterId'), '/')[8]]" - }, - "resources": [ - { - "type": "Microsoft.ContainerService/managedClusters", - "apiVersion": "2022-08-03-preview", - "name": "[variables('clusterName')]", - "location": "[parameters('location')]", - "properties": { - "mode": "Incremental", - "id": "[parameters('clusterId')]", - "addonProfiles": "[parameters('addonProfiles')]" - } - } - ] - } - }, - "dependsOn": [ - "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, format('rg-{0}', parameters('name'))), 'Microsoft.Resources/deployments', 'aksDeploy')]", - "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, format('rg-{0}', parameters('name'))), 'Microsoft.Resources/deployments', 'aksAddonIngDeploy')]", - "[subscriptionResourceId('Microsoft.Resources/resourceGroups', format('rg-{0}', parameters('name')))]" - ] - } - ] -} \ No newline at end of file diff --git a/cloud-native/aks-webapp-routing/README.md b/cloud-native/aks-webapp-routing/README.md deleted file mode 100644 index 4e0bcf2..0000000 --- a/cloud-native/aks-webapp-routing/README.md +++ /dev/null @@ -1,404 +0,0 @@ -# Web Application Routing with Azure Kubernetes Service - -In this lab, you will deploy an [AKS][aks] cluster and enable the [Web Application Routing (Preview)][aks_addon_web_app_routing] add-on. This add-on deploys a fully-managed Open-Source NGINX ingress controller into your cluster. We will explore the components that get installed then deploy and expose the [Azure Voting App](https://github.com/pauldotyu/azure-voting-app). - -## Requirements - -Before you get started, make sure you have the following: - -* An Azure Subscription (e.g. [Free](https://aka.ms/azure-free-account) or [Student](https://aka.ms/azure-student-account) account) -* The [Azure CLI](https://docs.microsoft.com/cli/azure/install-azure-cli) with [Azure Bicep](https://learn.microsoft.com/azure/azure-resource-manager/bicep/install#azure-cli) installed -* The [Git CLI](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) -* The [`kubectl` CLI](https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/) -* Bash shell (e.g. macOS, Linux, [Windows Subsystem for Linux (WSL)](https://docs.microsoft.com/windows/wsl/about), [Multipass](https://multipass.run/), [Azure Cloud Shell](https://docs.microsoft.com/azure/cloud-shell/quickstart), [GitHub Codespaces](https://github.com/features/codespaces), etc) -* Domain registered through a [ICANN-Accredited Registrar](https://www.icann.org/registrar-reports/accredited-list.html) - -> **IMPORTANT** -> -> You will need to [delegate your DNS zone with Azure DNS](https://learn.microsoft.com/azure/dns/dns-domain-delegation) for the **Web App Routing** and **Azure DNS** integration to work properly. See this [link](https://learn.microsoft.com/azure/dns/dns-delegate-domain-azure-dns) for more info. - -Make sure you have all requisite providers registered and the `aks-preview` extension installed: - -```bash -# install provider for aks -az provider register --namespace Microsoft.ContainerService -# install aks-preview extension -az extension add --name aks-preview -``` - -[![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure-Samples%2Fazure-opensource-labs%2Fmain%2Fcloud-native%2Faks-webapp-routing%2Fmain.json) - -> Use the button above if you'd like to deploy using the Azure Portal instead of Azure CLI commands. - -## Deploy Azure Resources - -Clone this repo and drop into the `aks-webapp-routing` directory. - -```bash -git clone https://github.com/Azure-Samples/azure-opensource-labs.git -cd azure-opensource-labs/cloud-native/aks-webapp-routing -``` - -Open a terminal and initialize the following variables which will be passed into the deployment. - -```bash -# azure region where resources will be deployed to -location=eastus - -# random name that will be used for azure resources -name=vote$RANDOM - -# get the latest (n-1) version of kubernetes -kubernetesVersion=$(az aks get-versions -l $location -o table | head -4 | tail -n 1 | cut -f 1 -d ' ') - -# kubernetes node count -systemNodeCount=3 - -# azure vm size for nodes -systemNodeSize=Standard_D4ds_v5 - -# get your user name -userName=$(az account show --query user.name -o tsv) - -# get your user principal id -userObjectId=$(az ad user show --id $userName --query id -o tsv) - -# a domain name you wish to use with the web_app_routing add-on -dnsName=contoso.work -``` - -Deploy Azure infrastructure with the Azure Bicep template. - -```bash -az deployment sub create \ - --name "$name-deploy" \ - --location $location \ - --template-file ./main.bicep \ - --parameters name=$name \ - location=$location \ - kubernetesVersion=$kubernetesVersion \ - systemNodeCount=$systemNodeCount \ - systemNodeSize=$systemNodeSize \ - userObjectId=$userObjectId \ - dnsName=$dnsName -``` - -> The deployment should take ~11 mins to complete - -The template will deploy the following resources into your subscription: - -* [Azure Resource Group][rg] to deploy resources into -* [Azure Kubernetes Service][aks] your managed Kubernetes cluster with [`kubenet`][kubenet] as the container network plugin and [`calico`][calico] for network policy and include the following [AKS add-ons][aks_addons] - * [`monitoring`](https://learn.microsoft.com/azure/azure-monitor/containers/container-insights-overview) - * [`azure-keyvault-secrets-provider`](https://learn.microsoft.com/azure/aks/csi-secrets-store-driver) - * [`web_application_routing`](https://learn.microsoft.com/azure/aks/web-app-routing?tabs=without-osm) -* [Azure Key Vault][kv] to store your TLS certificates -* [Azure DNS][dns] will be integrated with the `web_application_routing` add-on and manage your domain names - -> If you are curious to know how these Bicep modules are deployed to Azure Container Registry, take a look at this [blog post](https://dev.to/azure/sharing-bicep-modules-with-azure-container-registry-4mo0). - -## Validate the Azure deployment - -View a list of resources deployed in your resource group by running the following command or view from the [Azure Portal](https://portal.azure.com): - -```bash -az resource list --resource-group rg-$name -o table -``` - -To view the AKS add-ons that have been installed, run the command below: - -```bash -az aks show --resource-group rg-${name} --name aks-${name} --query addonProfiles -``` - -You'll notice that the AKS `web_app_routing` add-on is not included in the `addonProfiles` result. The metadata for this add-on is actually kept in the `ingressProfile` object. Run the command below to view the `web_app_routing` configuration: - -```bash -az aks show --resource-group rg-${name} --name aks-${name} --query ingressProfile -``` - -One last step to complete the `web_app_routing` integration with Azure DNS. We need to grant the user assigned managed identity resource the proper permissions to manage record sets for the DNS zone. Run the following commands to grant access. - -```bash -# Retrieve user managed identity object ID for the add-on -SUBSCRIPTION_ID=$(az account show --query id --output tsv) -MANAGEDIDENTITYNAME="webapprouting-aks-${name}" -MCRGNAME=$(az aks show -g rg-${name} -n aks-${name} --query nodeResourceGroup -o tsv) -USERMANAGEDIDENTITY_RESOURCEID="/subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${MCRGNAME}/providers/Microsoft.ManagedIdentity/userAssignedIdentities/${MANAGEDIDENTITYNAME}" -MANAGEDIDENTITY_OBJECTID=$(az resource show --id $USERMANAGEDIDENTITY_RESOURCEID --query properties.principalId -o tsv | tr -d '[:space:]') -# Configure the add-on to use Azure DNS to manage creating DNS zones -ZONEID=$(az network dns zone show -g rg-${name} -n $dnsName --query id --output tsv) -az role assignment create --role "DNS Zone Contributor" --assignee $MANAGEDIDENTITY_OBJECTID --scope $ZONEID -``` - -## Delegate DNS to Azure DNS - -Now is a good time to log into your domain name registrar's management portal and [delegate your DNS zone to Azure DNS](https://learn.microsoft.com/azure/dns/dns-delegate-domain-azure-dns#delegate-the-domain). - -Run this command to view the nameservers for your DNS zone in Azure DNS: - -```bash -az network dns record-set list -g rg-${name} -z $dnsName --query "[0].nsRecords[].nsdname" -``` - -> **NOTE** -> -> Azure will return nameservers that end with a dot (.). Some DNS registrars like GoDaddy will not accept the dot at the end so you will need to omit it. - -If you do not have a domain registered with an [ICANN-Accredited Registrar](https://www.icann.org/registrar-reports/accredited-list.html), you can still continue the lab. Your website will not be routable over the public internet but you can use host file entries to manually point to a public IP. - -## Validate access to the Kubernetes cluster - -Before we pull down credentials from AKS make sure you have `kubectl` CLI locally. - -> If you do not have `kubectl` installed yet, you can run the following command to install it using Azure CLI command: `az aks install-cli` - -Run the following command to download credential for `kubectl` CLI: - -```bash -az aks get-credentials --resource-group rg-${name} --name aks-${name} -``` - -Run the following command to see the namespaces that are installed so far: - -```bash -kubectl get namespaces -``` - -You should see an output similar to this: - -```output -NAME STATUS AGE -app-routing-system Active 16m -calico-system Active 25m -default Active 25m -kube-node-lease Active 25m -kube-public Active 25m -kube-system Active 25m -tigera-operator Active 25m -``` - -The `web_application_routing` add-on deploys a managed [OSS NGINX controller](https://kubernetes.github.io/ingress-nginx/). Check all the resources that it installed in the cluster with the following command: - -```bash -kubectl get all --namespace app-routing-system -``` - -You should see output similar to this: - -```output -NAME READY STATUS RESTARTS AGE -pod/external-dns-7989f85cbb-jhmng 1/1 Running 0 19m -pod/nginx-687969b887-g48cf 1/1 Running 0 18m -pod/nginx-687969b887-qtjmp 1/1 Running 0 19m - -NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE -service/nginx LoadBalancer 10.0.102.60 20.120.120.189 80:30282/TCP,443:30079/TCP 19m - -NAME READY UP-TO-DATE AVAILABLE AGE -deployment.apps/external-dns 1/1 1 1 19m -deployment.apps/nginx 2/2 2 2 19m - -NAME DESIRED CURRENT READY AGE -replicaset.apps/external-dns-7989f85cbb 1 1 1 19m -replicaset.apps/nginx-687969b887 2 2 2 19m - -NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE -horizontalpodautoscaler.autoscaling/nginx Deployment/nginx 0%/90% 2 100 2 19m -``` - -> The OSS NGINX ingress controller can be [installed manually via Helm chart](https://learn.microsoft.com/en-us/azure/aks/ingress-basic?tabs=azure-cli#create-an-ingress-controller), but with this being a managed NGINX controller, the installation is taken care of for you 🎉 - -Inspect the NGINX deployment: - -```bash -kubectl get deployment nginx --namespace app-routing-system --output yaml -``` - -One important thing to note is the ingress controller is deployed with an ingress class name of `webapprouting.kubernetes.azure.com`. We'll need this later in the lab as you configure your `Ingress` resources. If you run the following command, you will see the class name of the ingress controller: - -```bash -kubectl get ingressclasses -``` - -You should see output similar to this: - -```output -NAME CONTROLLER PARAMETERS AGE -webapprouting.kubernetes.azure.com k8s.io/ingress-nginx 21m -``` - -Optionally, inspect the managed NGINX controller pods that have been deployed: - -```bash -# get the name of the first running pod in the list -pod=$(kubectl get po -n app-routing-system --no-headers=true | grep nginx | grep Running | head -1 | cut -f 1 -d ' ') -kubectl get po -n app-routing-system $pod -o yaml -``` - -### Wait... what is this `external-dns` deployment that I saw? - -You may have noticed in the output above when you performed the `kubectl get all` command that there is a pod name that starts with `external-dns` and a deployment named `external-dns`. Run the following command to inspect its deployment details. - -```bash -kubectl get deployment external-dns --namespace app-routing-system --output yaml -``` - -As the name suggests, this pod is responsible for managing DNS records in your Azure DNS zone which was provisioned as part of our Bicep deployment. - -As part of our deployment process, we took the user-assigned managed identity that is created by the `web_application_routing` add-on deployment and granted it the **DNS Zone Contributor** role so that the pod can write entries for your zone. So this pod will essentially take care of writing DNS entries for you as you deploy `Ingress` resources to your cluster. - -## Application Deployment - -Make a copy of the [`deployment.yaml`](./deployment.yaml) file and name it `azure-vote-deployment.yaml`. We will need to update this manifest for our deployment. - -### Create a self-signed certificate - -When deploying an `Ingress` resource with a HTTPS-based hostname, you will need to include a SSL certificate. The `web_application_routing` add-on will be able to inject the certificate directly from Azure Key Vault. - -If you have a valid certificate for your custom domain name, you are welcome to [upload that to Azure Key Vault](https://learn.microsoft.com/azure/key-vault/certificates/tutorial-import-certificate?tabs=azure-portal). - -If you do not have a certificate for your custom domain name, we can create a self-signed certificate using the following commands: - -```bash -# Create a self-signed SSL certificate -# NOTE: The can be a subdomain (e.g. vote.contoso.work) -openssl req -new -x509 -nodes -out aks-ingress-tls.crt -keyout aks-ingress-tls.key -subj "/CN=" -addext "subjectAltName=DNS:" - -# Export the SSL certificate -# NOTE: You must skip the password prompt (i.e. leave it blank) -openssl pkcs12 -export -in aks-ingress-tls.crt -inkey aks-ingress-tls.key -out aks-ingress-tls.pfx -``` - -### Import the certificate to Azure Key Vault - -```bash -az keyvault certificate import --vault-name akv-$name -n azure-vote -f aks-ingress-tls.pfx -``` - -The command above will output a large JSON object to the terminal. You will need the certificate URI for the next step. This value can be found in within the `id` attribute for the resource. - -If you want to be sure you are retrieving the correct certificate URI, you can run the following command: - -```bash -az keyvault certificate show --vault-name akv-$name -n azure-vote --query id --output tsv -``` - -Copy the value to your clipboard as you will need to add this to your deployment manifest. - -### Update the `azure-vote-deployment.yaml` manifest - -Open the `azure-vote-deployment.yaml` manifest using your favorite text editor, and replace the `` with your DNS zone name and the `` with certificate URI from Azure Key Vault. - -Here is an example of what the new file should look like: - -![Updated manifest](./azure-vote-deployment.png) - -> `secretName` is the name of the secret that going to be generated to store the certificate. This is the certificate that's going to be presented in the browser. - -### Deploy the `azure-vote-deployment.yaml` manifest - -Run the following command to deploy the manifest - -```bash -kubectl apply -f azure-vote-deployment.yaml -``` - -Confirm the deployment by running this command. - -```bash -kubectl get ingress -``` - -After about a minute, you should see the `ADDRESS` column populated with a public IP address within a minute or two and the output will look similar to this: - -```output -NAME CLASS HOSTS ADDRESS PORTS AGE -azure-vote-front webapprouting.kubernetes.azure.com vote.contoso.work 20.246.231.104 80, 443 45s -``` - -You can also check your DNS zone for updated A records that points to your ingress' IP using the following command: - -```bash -az network dns record-set list -g rg-${name} -z $dnsName --query "[?type=='Microsoft.Network/dnszones/A']" -``` - -Your output will look similar to this: - -```output -[ - { - "aRecords": [ - { - "ipv4Address": "20.246.231.104" - } - ], - "aaaaRecords": null, - "caaRecords": null, - "cnameRecord": null, - "etag": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "fqdn": "vote.contoso.work.", - "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/rg-vote24543/providers/Microsoft.Network/dnszones/contoso.work/A/hello", - "metadata": null, - "mxRecords": null, - "name": "hello", - "nsRecords": null, - "provisioningState": "Succeeded", - "ptrRecords": null, - "resourceGroup": "rg-vote6045", - "soaRecord": null, - "srvRecords": null, - "targetResource": { - "id": null - }, - "ttl": 300, - "txtRecords": null, - "type": "Microsoft.Network/dnszones/A" - } -] -``` - -You can also view the `external-dns` pod logs to see it making changes to your DNS zone using the following command: - -```bash -pod=$(kubectl get po -n app-routing-system --no-headers=true | grep external-dns | grep Running | head -1 | cut -f 1 -d ' ') -kubectl logs $pod -n app-routing-system -``` - -Finally, validate the deployment by opening a web browser and navigating to your custom domain name. - -> If you have not [delegated your DNS zone to Azure DNS](https://learn.microsoft.com/azure/dns/dns-delegate-domain-azure-dns#delegate-the-domain) at your registrar's DNS management tool, you could setup an [entry in your local host file](https://www.howtogeek.com/howto/27350/beginner-geek-how-to-edit-your-hosts-file/) to point your custom domain to the public ingress IP. - -![Deployment validation](./azure-vote-deployment-validation.png) - -> Some browsers may not let you view websites that are secured using self-signed certificates. In this case you may need to update your browser configuration. - -## Wrap up - -In lab, we deployed an AKS cluster using Bicep templates and enabled the Web Application Routing add-on. - -We then examined the resources that been deployed into our cluster and uncovered how the integrations work. This add-on includes integrations with Azure Key Vault and Azure DNS which enables you to easily expose applications to the internet. Using annotations on the NGINX ingress controller, we can simply bind the `Ingress` resource to a TLS certificate in Azure Key Vault to secure our website. - -Also, with Azure DNS integrated with the add-on, we observed that it deployed an `external-dns` controller and we gave the add-on proper permissions to manipulate DNS records. As you expose additional sites (as subdomains) you will have additional DNS entries which should save you a bit of time. - -Best part of the add-on is that it is a OSS component that is fully-managed and fully-supported by Microsoft 🥳 - -Once you have finished exploring, you should delete the deployment to avoid any further charges. - -```bash -az group delete --name rg-${name} -y -``` - -## Resources - -* [AKS Add-On: Web Application Routing (Preview)][aks_addon_web_app_routing] - - -[aks_addons]:https://learn.microsoft.com/azure/aks/integrations#available-add-ons -[aks_addon_web_app_routing]:https://learn.microsoft.com/azure/aks/web-app-routing?tabs=without-osm -[kubenet]:https://learn.microsoft.com/azure/aks/configure-kubenet -[calico]:https://projectcalico.docs.tigera.io/security/kubernetes-policy -[rg]:https://learn.microsoft.com/azure/azure-resource-manager/management/manage-resource-groups-portal#what-is-a-resource-group -[aks]:https://learn.microsoft.com/azure/aks/intro-kubernetes -[kv]:https://learn.microsoft.com/azure/key-vault/general/overview -[dns]:https://learn.microsoft.com/azure/dns/dns-overview diff --git a/cloud-native/aks-webapp-routing/azure-vote-deployment-validation.png b/cloud-native/aks-webapp-routing/azure-vote-deployment-validation.png deleted file mode 100644 index b0baec0..0000000 Binary files a/cloud-native/aks-webapp-routing/azure-vote-deployment-validation.png and /dev/null differ diff --git a/cloud-native/aks-webapp-routing/azure-vote-deployment.png b/cloud-native/aks-webapp-routing/azure-vote-deployment.png deleted file mode 100644 index 46a9850..0000000 Binary files a/cloud-native/aks-webapp-routing/azure-vote-deployment.png and /dev/null differ diff --git a/cloud-native/aks-webapp-routing/bicepconfig.json b/cloud-native/aks-webapp-routing/bicepconfig.json deleted file mode 100644 index 91b4f8a..0000000 --- a/cloud-native/aks-webapp-routing/bicepconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "moduleAliases": { - "ts": {}, - "br": { - "oss-labs": { - "registry": "cloudnativeadvocates.azurecr.io" - } - } - } -} \ No newline at end of file diff --git a/cloud-native/aks-webapp-routing/deployment.yaml b/cloud-native/aks-webapp-routing/deployment.yaml deleted file mode 100644 index 40dc78c..0000000 --- a/cloud-native/aks-webapp-routing/deployment.yaml +++ /dev/null @@ -1,117 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: azure-vote-back -spec: - replicas: 1 - selector: - matchLabels: - app: azure-vote-back - template: - metadata: - labels: - app: azure-vote-back - spec: - nodeSelector: - "kubernetes.io/os": linux - containers: - - name: azure-vote-back - image: redis:latest - env: - - name: ALLOW_EMPTY_PASSWORD - value: "yes" - ports: - - containerPort: 6379 - name: redis ---- -apiVersion: v1 -kind: Service -metadata: - name: azure-vote-back -spec: - ports: - - port: 6379 - selector: - app: azure-vote-back ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: azure-vote-front -spec: - replicas: 1 - selector: - matchLabels: - app: azure-vote-front - strategy: - rollingUpdate: - maxSurge: 1 - maxUnavailable: 1 - minReadySeconds: 5 - template: - metadata: - labels: - app: azure-vote-front - spec: - nodeSelector: - "kubernetes.io/os": linux - containers: - - name: azure-vote-front - image: cloudnativeadvocates.azurecr.io/azure-vote-front:v1.0.0 - ports: - - containerPort: 80 - resources: - requests: - cpu: 250m - limits: - cpu: 500m - env: - - name: REDIS - value: "azure-vote-back" ---- -apiVersion: v1 -kind: Service -metadata: - name: azure-vote-front -spec: - ports: - - port: 80 - selector: - app: azure-vote-front ---- -apiVersion: autoscaling/v1 -kind: HorizontalPodAutoscaler -metadata: - name: azure-vote-front -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: azure-vote-front - minReplicas: 1 - maxReplicas: 50 - targetCPUUtilizationPercentage: 50 ---- -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - annotations: - kubernetes.azure.com/tls-cert-keyvault-uri: - name: azure-vote-front -spec: - ingressClassName: webapprouting.kubernetes.azure.com - rules: - - host: - http: - paths: - - backend: - service: - name: azure-vote-front - port: - number: 80 - path: / - pathType: Prefix - tls: - - hosts: - - - secretName: keyvault-azure-vote \ No newline at end of file diff --git a/cloud-native/aks-webapp-routing/hello-deployment-2.yaml b/cloud-native/aks-webapp-routing/hello-deployment-2.yaml deleted file mode 100644 index 565d184..0000000 --- a/cloud-native/aks-webapp-routing/hello-deployment-2.yaml +++ /dev/null @@ -1,65 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - name: hello-web-app-routing ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: aks-helloworld-2 - namespace: hello-web-app-routing -spec: - replicas: 1 - selector: - matchLabels: - app: aks-helloworld-2 - template: - metadata: - labels: - app: aks-helloworld-2 - spec: - containers: - - name: aks-helloworld-2 - image: mcr.microsoft.com/azuredocs/aks-helloworld:v1 - ports: - - containerPort: 80 - env: - - name: TITLE - value: "Welcome again to Azure Kubernetes Service (AKS) with Web Application Routing!" ---- -apiVersion: v1 -kind: Service -metadata: - name: aks-helloworld-2 - namespace: hello-web-app-routing -spec: - type: ClusterIP - ports: - - port: 80 - selector: - app: aks-helloworld-2 ---- -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - annotations: - kubernetes.azure.com/tls-cert-keyvault-uri: https://akv-books24543.vault.azure.net/certificates/hello-2/0ccf1df2eb384153a074ce6dcbe8e3a2 - name: aks-helloworld-2 - namespace: hello-web-app-routing -spec: - ingressClassName: webapprouting.kubernetes.azure.com - rules: - - host: hello2.contoso.work - http: - paths: - - backend: - service: - name: aks-helloworld-2 - port: - number: 80 - path: / - pathType: Prefix - tls: - - hosts: - - hello2.contoso.work - secretName: keyvault-aks-helloworld-2 \ No newline at end of file diff --git a/cloud-native/aks-webapp-routing/hello-deployment-validation.png b/cloud-native/aks-webapp-routing/hello-deployment-validation.png deleted file mode 100644 index 8b46b5a..0000000 Binary files a/cloud-native/aks-webapp-routing/hello-deployment-validation.png and /dev/null differ diff --git a/cloud-native/aks-webapp-routing/hello-deployment.png b/cloud-native/aks-webapp-routing/hello-deployment.png deleted file mode 100644 index dc88654..0000000 Binary files a/cloud-native/aks-webapp-routing/hello-deployment.png and /dev/null differ diff --git a/cloud-native/aks-webapp-routing/main.bicep b/cloud-native/aks-webapp-routing/main.bicep deleted file mode 100644 index 4edd5a3..0000000 --- a/cloud-native/aks-webapp-routing/main.bicep +++ /dev/null @@ -1,141 +0,0 @@ -targetScope = 'subscription' - -param name string -param location string -param tags object = {} -param kubernetesVersion string = '1.29' -param systemNodeCount int = 3 -param systemNodeSize string = 'Standard_D4s_v5' -param userObjectId string -param dnsName string - -var networkPlugin = 'kubenet' -var networkPolicy = 'calico' - -// Deploy the resource group -resource rg 'Microsoft.Resources/resourceGroups@2021-04-01' = { - name: 'rg-${name}' - location: location - tags: tags -} - -// Deploy the Kubernetes cluster -module aks '../../bicep/modules/azure-kubernetes-service/main.bicep' = { - scope: rg - name: 'aksDeploy' - params: { - name: 'aks-${name}' - location: location - tags: tags - kubernetesVersion: kubernetesVersion - networkPlugin: networkPlugin - networkPolicy: networkPolicy - systemNodeCount: systemNodeCount - systemNodeVmSize: systemNodeSize - } -} - -// Deploy the key vault -module kv '../../bicep/modules/azure-key-vault/main.bicep' = { - scope: rg - name: 'kvDeploy' - params: { - location: location - name: 'akv-${name}' - sku: 'standard' - tags: tags - userObjectId: userObjectId - tenantId: tenant().tenantId - accessPolicies: [ - { - objectId: aks.outputs.kubeletIdentityObjectId - permissions: { - certificates: [ - 'get' - ] - secrets: [ - 'get' - ] - } - tenantId: tenant().tenantId - } - ] - } - - dependsOn: [ - aks - ] -} - -// Deploy the public DNS zone -module dns '../../bicep/modules/azure-dns/main.bicep' = { - scope: rg - name: 'dnsDeploy' - params: { - location: 'Global' - name: dnsName - tags: tags - zoneType: 'Public' - // assignDnsZoneContributor: aks.outputs.kubeletIdentityObjectId - } - - dependsOn: [ - aks - ] -} - -// Deploy the key vault secrets provider add-on -module aksAddonKv '../../bicep/modules/azure-kubernetes-service-addons/main.bicep' = { - scope: rg - name: 'aksAddonKvDeploy' - params: { - location: location - clusterId: aks.outputs.id - addonProfiles: { - azureKeyvaultSecretsProvider: { - config: { - enableSecretRotation: 'true' - rotationPollInterval: '2m' - } - enabled: true - } - } - } - dependsOn: [ - aks - kv - ] -} - -// Deploy the web app routing add-on -module aksAddonIng '../../bicep/modules/azure-kubernetes-service-ingress/main.bicep' = { - scope: rg - name: 'aksAddonIngDeploy' - params: { - location: location - clusterId: aks.outputs.id - dnsZoneResourceId: dns.outputs.id - } - dependsOn: [ - aksAddonKv - ] -} - -// todo: troubleshoot this -// var mcResourceGroup = resourceGroup(aks.outputs.nodeResourceGroupName) -// resource userAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2022-01-31-preview' existing = { -// name: 'webapprouting-${aks.outputs.name}' -// scope: mcResourceGroup -// } - -// module aksAddonIngDns '../../bicep/modules/azure-kubernetes-service-ingress-dns/main.bicep' = { -// scope: rg -// name: 'aksAddonIngDnsDeploy' -// params: { -// dnsZoneName: dns.outputs.name -// principalId: userAssignedIdentity.properties.principalId -// } -// dependsOn: [ -// aksAddonIng -// ] -// } diff --git a/cloud-native/aks-webapp-routing/main.json b/cloud-native/aks-webapp-routing/main.json deleted file mode 100644 index 26c3945..0000000 --- a/cloud-native/aks-webapp-routing/main.json +++ /dev/null @@ -1,785 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "13040540872661234588" - } - }, - "parameters": { - "name": { - "type": "string" - }, - "location": { - "type": "string" - }, - "tags": { - "type": "object", - "defaultValue": {} - }, - "kubernetesVersion": { - "type": "string", - "defaultValue": "1.29" - }, - "systemNodeCount": { - "type": "int", - "defaultValue": 3 - }, - "systemNodeSize": { - "type": "string", - "defaultValue": "Standard_D4s_v5" - }, - "userObjectId": { - "type": "string" - }, - "dnsName": { - "type": "string" - } - }, - "variables": { - "networkPlugin": "kubenet", - "networkPolicy": "calico" - }, - "resources": [ - { - "type": "Microsoft.Resources/resourceGroups", - "apiVersion": "2021-04-01", - "name": "[format('rg-{0}', parameters('name'))]", - "location": "[parameters('location')]", - "tags": "[parameters('tags')]" - }, - { - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "aksDeploy", - "resourceGroup": "[format('rg-{0}', parameters('name'))]", - "properties": { - "expressionEvaluationOptions": { - "scope": "inner" - }, - "mode": "Incremental", - "parameters": { - "name": { - "value": "[format('aks-{0}', parameters('name'))]" - }, - "location": { - "value": "[parameters('location')]" - }, - "tags": { - "value": "[parameters('tags')]" - }, - "kubernetesVersion": { - "value": "[parameters('kubernetesVersion')]" - }, - "networkPlugin": { - "value": "[variables('networkPlugin')]" - }, - "networkPolicy": { - "value": "[variables('networkPolicy')]" - }, - "systemNodeCount": { - "value": "[parameters('systemNodeCount')]" - }, - "systemNodeVmSize": { - "value": "[parameters('systemNodeSize')]" - } - }, - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "5599997474738078815" - } - }, - "parameters": { - "name": { - "type": "string" - }, - "location": { - "type": "string" - }, - "tags": { - "type": "object" - }, - "slaTier": { - "type": "string", - "defaultValue": "Free", - "allowedValues": [ - "Free", - "Paid" - ], - "metadata": { - "description": "Defaults to Free tier" - } - }, - "managedIdentityType": { - "type": "string", - "defaultValue": "SystemAssigned", - "allowedValues": [ - "SystemAssigned", - "UserAssigned" - ], - "metadata": { - "description": "Two options are available: SystemAssigned or UserAssigned" - } - }, - "userAssignedIdentities": { - "type": "object", - "defaultValue": {}, - "metadata": { - "description": "Required when managed identity type is set to UserAssigned" - } - }, - "kubernetesVersion": { - "type": "string", - "defaultValue": "1.29", - "metadata": { - "description": "Default is 1.29" - } - }, - "defenderEnabled": { - "type": "bool", - "defaultValue": false - }, - "imageCleanerEnabled": { - "type": "bool", - "defaultValue": false - }, - "imageCleanerIntervalHours": { - "type": "int", - "defaultValue": 12 - }, - "systemNodeCount": { - "type": "int", - "defaultValue": 3 - }, - "systemNodeVmSize": { - "type": "string", - "defaultValue": "Standard_D2s_v5", - "metadata": { - "description": "Default system node pool size is Standard_D2s_v5" - } - }, - "registryName": { - "type": "string", - "defaultValue": "", - "metadata": { - "description": "Optional parameter to attach AKS cluster to an existing ACR" - } - }, - "networkPlugin": { - "type": "string", - "defaultValue": "kubenet", - "allowedValues": [ - "kubenet", - "azure", - "none" - ], - "metadata": { - "description": "Network plugin used for building the Kubernetes network." - } - }, - "networkPolicy": { - "type": "string", - "defaultValue": "calico", - "allowedValues": [ - "calico", - "azure" - ], - "metadata": { - "description": "Network policy used for building the Kubernetes network." - } - }, - "loadBalancerSku": { - "type": "string", - "defaultValue": "Standard", - "allowedValues": [ - "Standard", - "Basic" - ], - "metadata": { - "description": "The default is standard." - } - }, - "dnsServiceIP": { - "type": "string", - "defaultValue": "10.0.0.10", - "metadata": { - "description": "An IP address assigned to the Kubernetes DNS service. It must be within the Kubernetes service address range specified in serviceCidr." - } - }, - "dockerBridgeCidr": { - "type": "string", - "defaultValue": "172.17.0.1/16", - "metadata": { - "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." - } - }, - "logAnalyticsWorkspaceResourceId": { - "type": "string", - "defaultValue": "", - "metadata": { - "description": "Resource ID of log analytics workspace for auditing" - } - }, - "outboundType": { - "type": "string", - "defaultValue": "loadBalancer", - "allowedValues": [ - "loadBalancer", - "managedNATGateway", - "userAssignedNATGateway", - "userDefinedRouting" - ], - "metadata": { - "description": "This can only be set at cluster creation time and cannot be changed later." - } - }, - "podCidrs": { - "type": "array", - "defaultValue": [ - "10.244.0.0/16" - ], - "metadata": { - "description": "One IPv4 CIDR is expected for single-stack networking. Two CIDRs, one for each IP family (IPv4/IPv6), is expected for dual-stack networking." - } - }, - "serviceCidrs": { - "type": "array", - "defaultValue": [ - "10.0.0.0/16" - ], - "metadata": { - "description": "One IPv4 CIDR is expected for single-stack networking. Two CIDRs, one for each IP family (IPv4/IPv6), is expected for dual-stack networking. They must not overlap with any Subnet IP ranges." - } - }, - "ipFamilies": { - "type": "array", - "defaultValue": [ - "IPv4" - ], - "allowedValues": [ - "IPv4", - "IPv6" - ] - }, - "vnetSubnetID": { - "type": "string", - "defaultValue": "", - "metadata": { - "description": "If the cluster is using azure network plugin, then you can pass in the subnet resource ID like this `vnet.outputs.subnetId`; otherwise, leave it empty" - } - }, - "nodeTaints": { - "type": "array", - "defaultValue": [], - "metadata": { - "description": "Enable nodeTaints on the system node pool (e.g., ['CriticalAddonsOnly=true:NoSchedule'])" - } - }, - "addonProfiles": { - "type": "object", - "defaultValue": {}, - "metadata": { - "description": "AKS addons to enable" - } - }, - "enablePrometheusMetrics": { - "type": "bool", - "defaultValue": false - }, - "prometheusMetricLabelsAllowlist": { - "type": "string", - "defaultValue": "" - }, - "prometheusMetricAnnotationsAllowList": { - "type": "string", - "defaultValue": "" - } - }, - "resources": [ - { - "type": "Microsoft.ContainerService/managedClusters", - "apiVersion": "2022-08-03-preview", - "name": "[parameters('name')]", - "location": "[parameters('location')]", - "tags": "[parameters('tags')]", - "sku": { - "name": "Basic", - "tier": "[parameters('slaTier')]" - }, - "identity": { - "type": "[parameters('managedIdentityType')]", - "userAssignedIdentities": "[if(equals(parameters('managedIdentityType'), 'UserAssigned'), parameters('userAssignedIdentities'), null())]" - }, - "properties": { - "kubernetesVersion": "[parameters('kubernetesVersion')]", - "dnsPrefix": "[parameters('name')]", - "azureMonitorProfile": "[if(parameters('enablePrometheusMetrics'), createObject('metrics', createObject('enabled', true(), 'kubeStateMetrics', createObject('metricLabelsAllowlist', parameters('prometheusMetricLabelsAllowlist'), 'metricAnnotationsAllowList', parameters('prometheusMetricAnnotationsAllowList')))), null())]", - "networkProfile": { - "networkPlugin": "[parameters('networkPlugin')]", - "networkPolicy": "[parameters('networkPolicy')]", - "loadBalancerSku": "[parameters('loadBalancerSku')]", - "dnsServiceIP": "[parameters('dnsServiceIP')]", - "dockerBridgeCidr": "[parameters('dockerBridgeCidr')]", - "outboundType": "[parameters('outboundType')]", - "podCidrs": "[parameters('podCidrs')]", - "serviceCidrs": "[parameters('serviceCidrs')]", - "ipFamilies": "[parameters('ipFamilies')]" - }, - "agentPoolProfiles": [ - { - "name": "system", - "count": "[parameters('systemNodeCount')]", - "vmSize": "[parameters('systemNodeVmSize')]", - "mode": "System", - "vnetSubnetID": "[if(empty(parameters('vnetSubnetID')), null(), parameters('vnetSubnetID'))]", - "nodeTaints": "[if(empty(parameters('nodeTaints')), null(), parameters('nodeTaints'))]" - } - ], - "securityProfile": { - "defender": { - "securityMonitoring": { - "enabled": "[parameters('defenderEnabled')]" - } - }, - "imageCleaner": { - "enabled": "[parameters('imageCleanerEnabled')]", - "intervalHours": "[parameters('imageCleanerIntervalHours')]" - } - }, - "addonProfiles": "[parameters('addonProfiles')]" - } - }, - { - "condition": "[not(equals(parameters('registryName'), ''))]", - "type": "Microsoft.Authorization/roleAssignments", - "apiVersion": "2022-04-01", - "scope": "[format('Microsoft.ContainerRegistry/registries/{0}', parameters('registryName'))]", - "name": "[guid(resourceId('Microsoft.ContainerService/managedClusters', parameters('name')), parameters('registryName'))]", - "properties": { - "principalId": "[reference(resourceId('Microsoft.ContainerService/managedClusters', parameters('name')), '2022-08-03-preview').identityProfile.kubeletidentity.objectId]", - "roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')]" - }, - "dependsOn": [ - "[resourceId('Microsoft.ContainerService/managedClusters', parameters('name'))]" - ] - }, - { - "type": "Microsoft.Authorization/roleAssignments", - "apiVersion": "2022-04-01", - "name": "[guid(resourceId('Microsoft.ContainerService/managedClusters', parameters('name')), resourceGroup().id)]", - "properties": { - "principalId": "[reference(resourceId('Microsoft.ContainerService/managedClusters', parameters('name')), '2022-08-03-preview', 'full').identity.principalId]", - "roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]" - }, - "dependsOn": [ - "[resourceId('Microsoft.ContainerService/managedClusters', parameters('name'))]" - ] - } - ], - "outputs": { - "name": { - "type": "string", - "value": "[parameters('name')]" - }, - "id": { - "type": "string", - "value": "[resourceId('Microsoft.ContainerService/managedClusters', parameters('name'))]" - }, - "kubeletIdentityObjectId": { - "type": "string", - "value": "[reference(resourceId('Microsoft.ContainerService/managedClusters', parameters('name')), '2022-08-03-preview').identityProfile.kubeletidentity.objectId]" - }, - "nodeResourceGroupName": { - "type": "string", - "value": "[reference(resourceId('Microsoft.ContainerService/managedClusters', parameters('name')), '2022-08-03-preview').nodeResourceGroup]" - } - } - } - }, - "dependsOn": [ - "[subscriptionResourceId('Microsoft.Resources/resourceGroups', format('rg-{0}', parameters('name')))]" - ] - }, - { - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "kvDeploy", - "resourceGroup": "[format('rg-{0}', parameters('name'))]", - "properties": { - "expressionEvaluationOptions": { - "scope": "inner" - }, - "mode": "Incremental", - "parameters": { - "location": { - "value": "[parameters('location')]" - }, - "name": { - "value": "[format('akv-{0}', parameters('name'))]" - }, - "sku": { - "value": "standard" - }, - "tags": { - "value": "[parameters('tags')]" - }, - "userObjectId": { - "value": "[parameters('userObjectId')]" - }, - "tenantId": { - "value": "[tenant().tenantId]" - }, - "accessPolicies": { - "value": [ - { - "objectId": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, format('rg-{0}', parameters('name'))), 'Microsoft.Resources/deployments', 'aksDeploy'), '2022-09-01').outputs.kubeletIdentityObjectId.value]", - "permissions": { - "certificates": [ - "get" - ], - "secrets": [ - "get" - ] - }, - "tenantId": "[tenant().tenantId]" - } - ] - } - }, - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "6723983789050081110" - } - }, - "parameters": { - "name": { - "type": "string" - }, - "location": { - "type": "string" - }, - "tags": { - "type": "object" - }, - "sku": { - "type": "string", - "defaultValue": "standard", - "allowedValues": [ - "premium", - "standard" - ] - }, - "userObjectId": { - "type": "string", - "metadata": { - "description": "The object ID of a user, service principal or security group in AAD tenant." - } - }, - "tenantId": { - "type": "string" - }, - "accessPolicies": { - "type": "array", - "defaultValue": [], - "metadata": { - "description": "List of AccessPolicyEntry which is used when granting additional permissions for other users or managed identities" - } - } - }, - "resources": [ - { - "type": "Microsoft.KeyVault/vaults", - "apiVersion": "2022-07-01", - "name": "[parameters('name')]", - "location": "[parameters('location')]", - "tags": "[parameters('tags')]", - "properties": { - "accessPolicies": [ - { - "objectId": "[parameters('userObjectId')]", - "permissions": { - "certificates": [ - "all" - ], - "keys": [ - "all" - ], - "secrets": [ - "all" - ], - "storage": [ - "all" - ] - }, - "tenantId": "[parameters('tenantId')]" - } - ], - "sku": { - "family": "A", - "name": "[parameters('sku')]" - }, - "tenantId": "[parameters('tenantId')]" - } - }, - { - "condition": "[not(empty(parameters('accessPolicies')))]", - "type": "Microsoft.KeyVault/vaults/accessPolicies", - "apiVersion": "2022-07-01", - "name": "[format('{0}/{1}', parameters('name'), 'add')]", - "properties": { - "accessPolicies": "[parameters('accessPolicies')]" - }, - "dependsOn": [ - "[resourceId('Microsoft.KeyVault/vaults', parameters('name'))]" - ] - } - ] - } - }, - "dependsOn": [ - "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, format('rg-{0}', parameters('name'))), 'Microsoft.Resources/deployments', 'aksDeploy')]", - "[subscriptionResourceId('Microsoft.Resources/resourceGroups', format('rg-{0}', parameters('name')))]" - ] - }, - { - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "dnsDeploy", - "resourceGroup": "[format('rg-{0}', parameters('name'))]", - "properties": { - "expressionEvaluationOptions": { - "scope": "inner" - }, - "mode": "Incremental", - "parameters": { - "location": { - "value": "Global" - }, - "name": { - "value": "[parameters('dnsName')]" - }, - "tags": { - "value": "[parameters('tags')]" - }, - "zoneType": { - "value": "Public" - } - }, - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "5462253216366678906" - } - }, - "parameters": { - "name": { - "type": "string" - }, - "location": { - "type": "string" - }, - "tags": { - "type": "object" - }, - "zoneType": { - "type": "string", - "allowedValues": [ - "Public", - "Private" - ] - } - }, - "resources": [ - { - "type": "Microsoft.Network/dnsZones", - "apiVersion": "2018-05-01", - "name": "[parameters('name')]", - "location": "[parameters('location')]", - "tags": "[parameters('tags')]", - "properties": { - "zoneType": "[parameters('zoneType')]" - } - } - ], - "outputs": { - "id": { - "type": "string", - "value": "[resourceId('Microsoft.Network/dnsZones', parameters('name'))]" - } - } - } - }, - "dependsOn": [ - "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, format('rg-{0}', parameters('name'))), 'Microsoft.Resources/deployments', 'aksDeploy')]", - "[subscriptionResourceId('Microsoft.Resources/resourceGroups', format('rg-{0}', parameters('name')))]" - ] - }, - { - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "aksAddonKvDeploy", - "resourceGroup": "[format('rg-{0}', parameters('name'))]", - "properties": { - "expressionEvaluationOptions": { - "scope": "inner" - }, - "mode": "Incremental", - "parameters": { - "location": { - "value": "[parameters('location')]" - }, - "clusterId": { - "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, format('rg-{0}', parameters('name'))), 'Microsoft.Resources/deployments', 'aksDeploy'), '2022-09-01').outputs.id.value]" - }, - "addonProfiles": { - "value": { - "azureKeyvaultSecretsProvider": { - "config": { - "enableSecretRotation": "true", - "rotationPollInterval": "2m" - }, - "enabled": true - } - } - } - }, - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "15950648950143392136" - } - }, - "parameters": { - "location": { - "type": "string" - }, - "clusterId": { - "type": "string" - }, - "addonProfiles": { - "type": "object", - "metadata": { - "description": "AKS addons to enable" - } - } - }, - "variables": { - "clusterName": "[split(parameters('clusterId'), '/')[8]]" - }, - "resources": [ - { - "type": "Microsoft.ContainerService/managedClusters", - "apiVersion": "2022-08-03-preview", - "name": "[variables('clusterName')]", - "location": "[parameters('location')]", - "properties": { - "mode": "Incremental", - "id": "[parameters('clusterId')]", - "addonProfiles": "[parameters('addonProfiles')]" - } - } - ] - } - }, - "dependsOn": [ - "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, format('rg-{0}', parameters('name'))), 'Microsoft.Resources/deployments', 'aksDeploy')]", - "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, format('rg-{0}', parameters('name'))), 'Microsoft.Resources/deployments', 'kvDeploy')]", - "[subscriptionResourceId('Microsoft.Resources/resourceGroups', format('rg-{0}', parameters('name')))]" - ] - }, - { - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "aksAddonIngDeploy", - "resourceGroup": "[format('rg-{0}', parameters('name'))]", - "properties": { - "expressionEvaluationOptions": { - "scope": "inner" - }, - "mode": "Incremental", - "parameters": { - "location": { - "value": "[parameters('location')]" - }, - "clusterId": { - "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, format('rg-{0}', parameters('name'))), 'Microsoft.Resources/deployments', 'aksDeploy'), '2022-09-01').outputs.id.value]" - }, - "dnsZoneResourceId": { - "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, format('rg-{0}', parameters('name'))), 'Microsoft.Resources/deployments', 'dnsDeploy'), '2022-09-01').outputs.id.value]" - } - }, - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.28.1.47646", - "templateHash": "2186650111419086884" - } - }, - "parameters": { - "location": { - "type": "string" - }, - "clusterId": { - "type": "string" - }, - "dnsZoneResourceId": { - "type": "string", - "defaultValue": "" - } - }, - "variables": { - "clusterName": "[split(parameters('clusterId'), '/')[8]]", - "attachDnsZone": "[not(equals(parameters('dnsZoneResourceId'), ''))]" - }, - "resources": [ - { - "type": "Microsoft.ContainerService/managedClusters", - "apiVersion": "2022-08-03-preview", - "name": "[variables('clusterName')]", - "location": "[parameters('location')]", - "properties": { - "mode": "Incremental", - "id": "[parameters('clusterId')]", - "ingressProfile": { - "webAppRouting": { - "dnsZoneResourceId": "[if(variables('attachDnsZone'), parameters('dnsZoneResourceId'), null())]", - "enabled": true - } - } - } - } - ] - } - }, - "dependsOn": [ - "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, format('rg-{0}', parameters('name'))), 'Microsoft.Resources/deployments', 'aksDeploy')]", - "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, format('rg-{0}', parameters('name'))), 'Microsoft.Resources/deployments', 'aksAddonKvDeploy')]", - "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, format('rg-{0}', parameters('name'))), 'Microsoft.Resources/deployments', 'dnsDeploy')]", - "[subscriptionResourceId('Microsoft.Resources/resourceGroups', format('rg-{0}', parameters('name')))]" - ] - } - ] -} \ No newline at end of file