Recently I have been working on a new Bicep module that significantly simplifies deploying Helm charts onto Azure Kubernetes Service (AKS). This module harnesses the power of the AKS run command.
I used the aks-run-command module from the bicep public repository as a starting point. So, credit goes to them too on this. You can see more of the public registry modules at https://github.com/Azure/bicep-registry-modules.
Why deploy Helm Charts via Bicep?
Deploying a Helm chart via Bicep is particularly advantageous for bootstrapping Kubernetes clusters with essential tools like Argo CD, paving the way for a GitOps approach. By integrating Helm, the Kubernetes package manager, into the Bicep deployment, you establish a foundational setup upon which you can build a more automated, version-controlled, and reproducible infrastructure management process. This aligns perfectly with the GitOps philosophy, where the desired state of your cluster is defined and maintained through code, leading to streamlined, scalable, and more secure Kubernetes operations. It’s also good for DR scenarios to get your cluster up and running again quicker.
What is the “Helm Install Command” Module?
This Bicep module is basically an Azure CLI Deployment Script that automates the deployment of a Helm chart onto an AKS cluster. It encapsulates the complexity of the deployment process, making it a seamless experience for the user.
Key Features
– Effortless Helm Chart Deployments: The module facilitates the deployment of Helm charts onto AKS clusters with minimal manual intervention.
– Dynamic Identity Management: It supports both new and existing Managed Identities, offering flexibility in identity management.
– Fine-Tuned Control: Parameters such as Helm repository details, and Helm application parameters are customizable, so you can install any helm chart.
– Delay Mechanism: Includes an initial script delay to account for Azure AD Role Assignments propagation.
Under the Hood: How Does it Work?
1. Managed Identity Configuration: Depending on the user’s choice, the module either creates a new Managed Identity or uses an existing one.
2. RBAC Setup: Assigns the necessary Azure RBAC roles to the Managed Identity for executing the deployment script.
3. Deployment Script Execution: Utilizes an Azure CLI deployment script to run the necessary Helm commands on the AKS cluster.
4. Output Handling: Captures the command output, providing visibility into the deployment process.
The Bash Script
The module employs a Bash script that performs the following:
– Delays execution to ensure RBAC settings are in place.
– Generates a Helm values file from a base64 encoded string.
– Executes Helm commands to add the repository, update it, and deploy the Helm chart.
Her is a copy of the bash script. You can also find an up-to-date copy in my AKS-Bicep Git Repo.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
#!/bin/bash set -e +H # -e to exit on error # +H to prevent history expansion # Set the script's locale to UTF-8 to ensure proper handling of UTF-8 encoded text export LANG=C.UTF-8 if [ "$initialDelay" != "0" ] then echo "Waiting on RBAC replication ($initialDelay)" sleep $initialDelay #Force RBAC refresh az logout az login --identity fi # Define the filename for the Helm values helmValuesFileName="$(dirname "$0")/helmvalues.yaml" echo "Creating Helm values file..." echo -n $helmAppValues | base64 -d > $helmValuesFileName echo "Helm values file created and stored at $helmValuesFileName" echo "Sending command to AKS Cluster $aksName in $RG" cmdOut=$(az aks command invoke -g $RG -n $aksName --command "helm repo add ${helmRepo} ${helmRepoURL} && helm repo update && helm upgrade --install ${helmAppName} ${helmApp} ${helmAppParams} -f $helmValuesFileName" --file $helmValuesFileName -o json) echo $cmdOut jsonOutputString=$cmdOut echo $jsonOutputString > $AZ_SCRIPTS_OUTPUT_PATH |
How to Use the “Helm Install Command” Module
Let’s take a look at two examples on using this new bicep module.
Automatically Create Managed Identity and RBAC
This example demonstrates how to automatically create a new managed identity and set up Role Based Access Control (RBAC) for deploying an internal Nginx ingress using Helm.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
module InstallInternalNginxIngress '../modules/Custom/deployment-scripts/aks-helm-install/main.bicep' = { name: 'Install-Internal-Ingress' params: { aksName: aksClusterName location: location newOrExistingManagedIdentity: 'new' helmRepo: 'ingress-nginx' helmRepoURL: 'https://kubernetes.github.io/ingress-nginx' helmApp: 'ingress-nginx/ingress-nginx' helmAppName: 'internal-ingress' helmAppParams: '--namespace internal-ingress --create-namespace' helmAppValues: loadFileAsBase64('../yaml/internalIngress.yaml') } dependsOn: [ aksCluster ] } |
In this example we have set the parameter newOrExistingManagedIdentity
to new. This then tells the bicep to create a new managed identity and set the correct RBAC.
Next, we supply the details for the helm chart we want to install, including any parameters you want to include with the helm command. In this case –namespace and –create-namespace.
Finally, we supply a path to the helm values file. In this case I have it saved under the yaml folder.
You do not need to supply any values for both helmAppParams
and helmAppValues
to have a successful installation of you helm app.
Using an Existing Managed Identity
For scenarios where an existing managed identity with the correct RBAC is available, you have a few extra parameters to fill in.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
module InstallInternalNginxIngress '../modules/Custom/deployment-scripts/aks-helm-install/main.bicep' = { name: 'Install-Internal-Ingress' params: { aksName: aksClusterName location: location newOrExistingManagedIdentity: 'existing' managedIdentityName: 'aks-run-command-id' existingManagedIdentitySubId: subscription().subscriptionId existingManagedIdentityResourceGroupName: 'resourceGroupName' helmRepo: 'ingress-nginx' helmRepoURL: 'https://kubernetes.github.io/ingress-nginx' helmApp: 'ingress-nginx/ingress-nginx' helmAppName: 'internal-ingress' helmAppParams: '--namespace internal-ingress --create-namespace' helmAppValues: loadFileAsBase64('../yaml/internalIngress.yaml') } dependsOn: [ aksCluster ] } |
Here you will see newOrExistingManagedIdentity
is set to existing. With this set to existing we need to use a few more parameters which are: managedIdentityName
, existingManagedIdentitySubId
, and existingManagedIdentityResourceGroupName
. This allows the module to get the existing managed identity and use it to run the script.
All other parameters are the same with the same conditions.
Conclusion
I hope you like this new Bicep module and can see the benefit in it. Your feedback is invaluable to me, so please let me know what you think in the comments below. How will you use this module to enhance your AKS environment? Let’s discuss and continue to evolve our cloud capabilities together.
0 Comments