|
| 1 | +# CosmosDB Sample Application |
| 2 | +This is a very simple voting application to illustrate how to integrate different Azure resources into a Kubernetes application using the [Azure Service Operator](https://github.com/Azure/azure-service-operator). |
| 3 | + |
| 4 | +## Pre-requisites |
| 5 | +- Azure Subscription |
| 6 | +- Azure CLI |
| 7 | +- Helm |
| 8 | +- Kubernetes Cluster >= 1.16.0 |
| 9 | +- Docker |
| 10 | +- Environment Variables |
| 11 | + - `AZURE_TENANT_ID` - this value must be set in your environment to your Azure Tenant ID for some scripts and commands to work properly. You can view this if you are logged into the Azure CLI using `az account show` |
| 12 | + - `AZURE_SUBSCRIPTION_ID` - this value must be set in your environment to your Azure Subscription ID for some scripts and commands to work properly. You can view this if you are logged into the Azure CLI using `az account show` |
| 13 | + |
| 14 | +## Outline |
| 15 | +1. Creating a basic AKS cluster |
| 16 | +2. Deploying the Azure Service Operator to the AKS cluster |
| 17 | +3. Deploying the sample application |
| 18 | +4. Setting up managed identity for authorization to Azure resources |
| 19 | + |
| 20 | +## Resources |
| 21 | +- Scripts |
| 22 | + - [shared.sh](scripts/shared.sh) - this script sets up names and values that are shared between the scripts. If you want to customize the names of resources deployed for this application you will need to edit this file for the other scripts to function properly. |
| 23 | + - [gen_helm_values.sh](scripts/gen_helm_values.sh) - this script will use the Azure CLI to generate the content for the helm chart's values.yaml. |
| 24 | + - [step1_create_cluster.sh](scripts/step1_create_cluster.sh) - this script will use the Azure CLI to create a basic AKS cluster that we'll use to deploy our application to. |
| 25 | + - [step2_install_operator.sh](scripts/step2_install_operator.sh) - this script will deploy the Azure Service Operator and it's dependencies to an AKS cluster. |
| 26 | + - [step3_deploy_application.sh](scripts/step3_deploy_application.sh) - this script will deploy the application using the Helm chart located [here](charts/azure-votes-cosmosdb). |
| 27 | + - [step4_create_app_identity.sh](scripts/step4_create_app_identity.sh) - this script will use the Azure CLI to create a managed identity that our application will use to access Azure resources securely. |
| 28 | + |
| 29 | +## Creating a basic AKS cluster |
| 30 | +You can use the [script](scripts/step1_create_cluster.sh) to create the AKS or you can enter these commands if you'd like to customize them yourself. |
| 31 | + |
| 32 | +The first thing we need is a resource group to put the AKS cluster resource into. |
| 33 | +``` |
| 34 | +az group create -n rg-aso-sample-infra -l eastus |
| 35 | +``` |
| 36 | + |
| 37 | +Next we create the AKS cluster. You can customize this command to suite your needs but in order to use the csi-secret-store-provider to mount Azure KeyVault secrets the cluster will need to be Kubernetes 1.16 or greater. |
| 38 | +``` |
| 39 | +az aks create \ |
| 40 | + --resource-group rg-aso-sample-infra \ |
| 41 | + --name aks-aso-sample-infra \ |
| 42 | + --kubernetes-version 1.16.7 \ |
| 43 | + --generate-ssh-keys |
| 44 | +``` |
| 45 | + |
| 46 | +## Install Azure Service Operator |
| 47 | +You can use the [script](scripts/step2_install_operator.sh) to install the Azure Service Operator into an AKS cluster using the Helm chart. |
| 48 | + |
| 49 | +### Create a Managed Identity for the Azure Service Operator |
| 50 | +For this sample we will use Azure AD Pod Identity to authorize the service operator to create Azure resources. In order to configure AAD Pod Identity we need to give the AKS Service Principal permissions to manage the Managed Identity that the operator will be running as. You can get the client id of the AKS Service Principal using the following command: |
| 51 | +``` |
| 52 | +az aks show -g rg-aso-sample-infra -n aks-aso-sample-infra --query "servicePrincipalProfile.clientId" |
| 53 | +``` |
| 54 | + |
| 55 | +For this next command, make sure to copy the resource ID and client ID from the output. Create a Managed Identity for the Azure Service Operator: |
| 56 | +``` |
| 57 | +az identity create -g rg-aso-sample-infra -n aso-manager-identity |
| 58 | +``` |
| 59 | + |
| 60 | +Create a role assignment for the AKS Service Principal to access the Managed Identity for the Azure Service Principal: |
| 61 | +``` |
| 62 | +az role assignment create --role "Managed Identity Operator" --assignee "<paste-aks-service-principal-client-id>" --scope "<paste-managed-identity-resource-id>" |
| 63 | +``` |
| 64 | + |
| 65 | +Create a role assignment for the Azure Service Operator to be able to create resources in Azure: |
| 66 | +``` |
| 67 | +az role assignment create --role "Contributor" --assignee "<paste-managed-identity-client-id>" --scope "/subscriptions/$AZURE_SUBSCRIPTION_ID" |
| 68 | +``` |
| 69 | + |
| 70 | +### Deploy Dependencies |
| 71 | +First get the credentials for the AKS cluster we have already created: |
| 72 | +``` |
| 73 | +az aks get-credentials -g rg-aso-sample-infra -n aks-aso-sample-infra |
| 74 | +``` |
| 75 | + |
| 76 | +We need to deploy cert-manager as a requirement for the Azure Service Operator: |
| 77 | +``` |
| 78 | +kubectl create namespace cert-manager |
| 79 | +kubectl label namespace cert-manager cert-manager.io/disable-validation=true |
| 80 | +kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/v0.12.0/cert-manager.yaml |
| 81 | +``` |
| 82 | + |
| 83 | +We need to deploy csi-secrets-store-provider-azure for our application, this component will mount KeyVault secrets as Volumes to our application's container. |
| 84 | +``` |
| 85 | +helm install csi-secrets-store-provider-azure \ |
| 86 | + csi-secrets-store-provider-azure/csi-secrets-store-provider-azure |
| 87 | +``` |
| 88 | + |
| 89 | +### Deploy Azure Service Operator |
| 90 | +This sample uses the Helm Chart to install the Azure Service Operator and you can see more details about deploy the helm chart [here](https://github.com/Azure/azure-service-operator) |
| 91 | + |
| 92 | +``` |
| 93 | +helm install aso "azure-service-operator/azure-service-operator" \ |
| 94 | + --set azureSubscriptionID=$AZURE_SUBSCRIPTION_ID \ |
| 95 | + --set azureTenantID=$AZURE_TENANT_ID \ |
| 96 | + --set azureUseMI=True \ |
| 97 | + --set aad-pod-identity.azureIdentity.resourceID=<paste-managed-identity-resource-id> \ |
| 98 | + --set aad-pod-identity.azureIdentity.clientID=<paste-managed-identity-client-id> |
| 99 | +``` |
| 100 | + |
| 101 | +## Deploy the Application |
| 102 | +This sample application can be deployed using the helm chart. You will need to supply your own values in the [values.yaml](charts/azure-votes-cosmosdb/values.yaml). The [gen_helm_values.sh](scripts/gen_helm_values.sh) script can use the Azure CLI to generate most of the values for you except for the AKS Virtual Network name, that you will need to look up in the Azure Portal. |
| 103 | + |
| 104 | +Component Templates: |
| 105 | +- [Resource Group](charts/azure-votes-cosmosdb/templates/resourcegroup.yaml) |
| 106 | +- [App Insights](charts/azure-votes-cosmosdb/templates/appinsights.yaml) |
| 107 | +- [KeyVault](charts/azure-votes-cosmosdb/templates/keyvault.yaml) |
| 108 | +- [CosmosDB](charts/azure-votes-cosmosdb/templates/cosmosdb.yaml) |
| 109 | +- [AAD Identity](charts/azure-votes-cosmosdb/templates/azureidentity.yaml) |
| 110 | +- [AAD Identity Binding](charts/azure-votes-cosmosdb/templates/azureidentitybinding.yaml) |
| 111 | +- [Secret Provider](charts/azure-votes-cosmosdb/templates/secretprovider.yaml) |
| 112 | +- [App Deployment](charts/azure-votes-cosmosdb/templates/app_deployment.yaml) |
| 113 | +- [App Service](charts/azure-votes-cosmosdb/templates/app_service.yaml) |
| 114 | + |
| 115 | +### Build and push the sample application |
| 116 | +In order for the application to run you will need to build and push the docker container for it. You can use the docker image tag provided or build and push the container to a registry of your choosing by editing [this script](api/build_and_push.sh). If you do this you will need to change the `app.image` value in [values.yaml](charts/azure-votes-cosmosdb/values.yaml). The pod for our application won't come up until a later step when we setup the Managed Identity for the sample application. |
| 117 | + |
| 118 | +### Helm Install |
| 119 | +``` |
| 120 | +helm install app ./charts/azure-votes-cosmosdb |
| 121 | +``` |
| 122 | + |
| 123 | +## Configure Application Managed Identity |
| 124 | +In this sample we use AAD Pod Identity to read and mount Azure KeyVault secrets into our pod's containers. To do that we create a managed identity that our Pod's containers can bind to and authorize with. The steps required are written out by [this script](scripts/step4_create_app_identity.sh) but not executed because you may need to retry some of the commands. Before we can run these steps we need to verify that the resource group and keyvault resource have been provisioned using kubectl and looking the "Successfully provisioned" message. |
| 125 | + |
| 126 | +Verify Resource Group has been provisioned: |
| 127 | +``` |
| 128 | +kubectl describe resourcegroup rg-aso-votes-app |
| 129 | +``` |
| 130 | + |
| 131 | +Verify KeyVault has been provisioned: |
| 132 | +``` |
| 133 | +kubectl describe keyvault kv-aso-votes-app |
| 134 | +``` |
| 135 | + |
| 136 | +### Create Managed Identity |
| 137 | +Again, make sure to copy the resource ID and client ID of the managed identity from the terminal output. Create the identity: |
| 138 | +``` |
| 139 | +az identity create -g rg-aso-votes-app -n mi-aso-votes-app |
| 140 | +``` |
| 141 | + |
| 142 | +Create a role assignment for the AKS Service Principal to access the Managed Identity for the sample application: |
| 143 | +``` |
| 144 | +az role assignment create --role "Managed Identity Operator" --assignee ${AKS_SP_ID} --scope \$APP_IDENTITY_ID |
| 145 | +``` |
| 146 | + |
| 147 | +Create a role assignment for the Managed Identity of the application to read KeyVault secrets: |
| 148 | +``` |
| 149 | +az role assignment create --role Reader --assignee <paste-managed-identity-client-id> --scope "/subscriptions/${AZURE_SUBSCRIPTION_ID}/resourcegroups/rg-aso-votes-app/providers/Microsoft.KeyVault/vaults/kv-aso-votes-app" |
| 150 | +``` |
| 151 | + |
| 152 | +Add a policy to KeyVault to be able to get secrets using the Managed Identity: |
| 153 | +``` |
| 154 | +az keyvault set-policy -n kv-aso-votes-app --secret-permissions get --spn <paste-managed-identity-client-id> |
| 155 | +``` |
| 156 | + |
| 157 | +### Update Helm Chart |
| 158 | +Now that we have the proper managed identity name and client ID we can update the [values.yaml](charts/azure-votes-cosmosdb/values.yaml) file to fix the pod for our application. Update the following fields in your values.yaml file using the name and ID from the previous step: |
| 159 | +``` |
| 160 | +app: |
| 161 | + identity: |
| 162 | + name: <paste-managed-identity-name> |
| 163 | + clientID: <paste-managed-identity-clientid> |
| 164 | +``` |
| 165 | + |
| 166 | +Deploy the updated helm chart: |
| 167 | +``` |
| 168 | +helm upgrade aso ./charts/azure-votes-cosmosdb |
| 169 | +``` |
| 170 | + |
| 171 | +After a few minutes the Pod should be able to authorize with KeyVault and mount the secret for CosmosDB to the container. |
0 commit comments