page_type: sample languages:
- java products:
- Azure Kubernetes Service description: "Deploy Tanzu Application Platform to AKS" urlFragment: "tap"
Se also :
- repo from VMWare
- https://tap-gui.demo-aks.spuchol.me
- https://docs.vmware.com/en/VMware-Tanzu-Application-Platform/1.4/tap.pdf
- https://docs.vmware.com/en/VMware-Tanzu-Application-Platform/1.4/tap-reference-architecture/GUID-reference-designs-tap-architecture-planning.html
This microservices branch was initially derived from AngularJS version to demonstrate how to split sample Spring application into microservices. To achieve that goal we use IaC with Azure Bicep, MS build of OpenJDK 11, GitHub Actions, Azure AD Workload Identity, Azure Key Vault, Azure Container Registry, Azure Database for MySQL
See :
- the AKS Micro-services Reference Architecture
- https://github.com/Azure-Samples/java-on-azure-examples/tree/main/aks/springboot
To get an Azure subscription:
- If you have a Visual studio subscription then you can activate your free credits here
- If you do not currently have one, you can sign up for a free trial subscription here
To install Azure Bicep locally, read https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/install
About how to build the container image, read :
Read :
- https://docs.github.com/en/actions/using-workflows/storing-workflow-data-as-artifacts
- https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-maven
- Overview of federated identity credentials in Azure Active Directory
You have to specify some KV secrets that will be then created in the GitHub Action Azure Infra services deployment workflow :
- SPRING-DATASOURCE-PASSWORD
- SPRING-CLOUD-AZURE-TENANT-ID
- VM-ADMIN-PASSWORD
dash '-' are not supported in GH secrets, so the secrets must be named in GH with underscore '_'.
(ex: the '&' character in the SPRING_DATASOURCE_URL must be escaped with '&' jdbc:mysql://petcliaks777.mysql.database.azure.com:3306/petclinic?useSSL=true&requireSSL=true&enabledTLSProtocols=TLSv1.2&verifyServerCertificate=true)
Add the App secrets used by the Spring Config to your GH repo secrets / Actions secrets / Repository secrets / Add :
Secret Name | Secret Value example |
---|---|
SPRING_DATASOURCE_PASSWORD | PUT YOUR PASSWORD HERE |
SPRING_CLOUD_AZURE_TENANT_ID | PUT YOUR AZURE TENANT ID HERE |
VM_ADMIN_PASSWORD | PUT YOUR PASSWORD HERE |
TANZU_NET_USER | PUT YOUR Tanzu Network USER HERE |
TANZU_NET_PASSWORD | PUT YOUR Tanzu Network USER PASSWORD HERE |
PG_ADM_PWD | PUT YOUR Tanzu Network USER PASSWORD HERE |
LOCATION="westeurope"
RG_KV="rg-kv-tanzu101"
RG_APP="rg-aks-tap-apps"
az group create --name $RG_KV --location $LOCATION
az group create --name $RG_APP --location $LOCATION
A Service Principal is required for GitHub Action Runner, read https://aka.ms/azadsp-cli
SPN_APP_NAME="gha_aks_tap_run"
# /!\ In CloudShell, the default subscription is not always the one you thought ...
subName="set here the name of your subscription"
subName=$(az account list --query "[?name=='${subName}'].{name:name}" --output tsv)
echo "subscription Name :" $subName
SUBSCRIPTION_ID=$(az account list --query "[?name=='${subName}'].{id:id}" --output tsv)
SUBSCRIPTION_ID=$(az account show --query id -o tsv)
TENANT_ID=$(az account show --query tenantId -o tsv)
Add your AZURE_SUBSCRIPTION_ID, AZURE_TENANT_ID to your GH repo Settings / Security / Secrets and variables / Actions / Actions secrets / Repository secrets
Read :
- https://learn.microsoft.com/en-us/azure/developer/github/connect-from-azure
- https://learn.microsoft.com/en-us/azure/developer/github/connect-from-azure?tabs=azure-cli%2Cwindows#use-the-azure-login-action-with-openid-connect
- https://learn.microsoft.com/en-us/azure/active-directory/develop/workload-identity-federation-create-trust?pivots=identity-wif-apps-methods-azp
In the GitHub Action Runner, to allow the Service Principal used to access the Key Vault, execute the command below:
#az ad app create --display-name $SPN_APP_NAME > aad_app.json
# This command will output JSON with an appId that is your client-id. The objectId is APPLICATION-OBJECT-ID and it will be used for creating federated credentials with Graph API calls.
#export APPLICATION_ID=$(cat aad_app.json | jq -r '.appId')
#export APPLICATION_OBJECT_ID=$(cat aad_app.json | jq -r '.id')
#az ad sp create --id $APPLICATION_ID
#export CREDENTIAL_NAME="gha_aks_run"
#export SUBJECT="repo:ezYakaEagle442/azure-tanzu-application-platform:environment:PoC" # "repo:organization/repository:environment:Production"
#export DESCRIPTION="GitHub Action Runner for Petclinic AKS demo"
#az rest --method POST --uri 'https://graph.microsoft.com/beta/applications/$APPLICATION_OBJECT_ID/federatedIdentityCredentials' --body '{"name":"$CREDENTIAL_NAME","issuer":"https://token.actions.githubusercontent.com","subject":"$SUBJECT","description":"$DESCRIPTION","audiences":["api://AzureADTokenExchange"]}'
# SPN_PWD=$(az ad sp create-for-rbac --name $SPN_APP_NAME --skip-assignment --query password --output tsv)
az ad sp create-for-rbac --name $SPN_APP_NAME --skip-assignment --sdk-auth
{
"clientId": "<GUID>",
"clientSecret": "<GUID>",
"subscriptionId": "<GUID>",
"tenantId": "<GUID>",
"activeDirectoryEndpointUrl": "https://login.microsoftonline.com",
"resourceManagerEndpointUrl": "https://management.azure.com/",
"activeDirectoryGraphResourceId": "https://graph.windows.net/",
"sqlManagementEndpointUrl": "https://management.core.windows.net:8443/",
"galleryEndpointUrl": "https://gallery.azure.com/",
"managementEndpointUrl": "https://management.core.windows.net/"
}
Store the above "clientSecret" to SPN_PWD environment variable : SPN_PWD=XXXXXXXXXXXXXXXXXXXXXXXX
Troubleshoot: If you hit "Error: : No subscriptions found for ***." , this is related to an IAM privilege in the subscription.
SPN_APP_ID=$(az ad sp list --all --query "[?appDisplayName=='${SPN_APP_NAME}'].{appId:appId}" --output tsv)
#SPN_APP_ID=$(az ad sp list --show-mine --query "[?appDisplayName=='${SPN_APP_NAME}'].{appId:appId}" --output tsv)
#TENANT_ID=$(az ad sp list --show-mine --query "[?appDisplayName=='${SPN_APP_NAME}'].{t:appOwnerOrganizationId}" --output tsv)
TENANT_ID=$(az ad sp list --all --query "[?appDisplayName=='${SPN_APP_NAME}'].{tenantId:appOwnerOrganizationId}" --output tsv)
# Enterprise Application
az ad app show --id $SPN_APP_ID
az ad app list --show-mine --query "[?displayName=='${SPN_APP_NAME}'].{objectId:id}"
# This is the unique ID of the Service Principal object associated with this application.
# SPN_OBJECT_ID=$(az ad app show --id $SPN_APP_ID --query id -o tsv)
SPN_OBJECT_ID=$(az ad sp list --all --query "[?appDisplayName=='${SPN_APP_NAME}'].{id:id}" --output tsv)
# This is the unique ID of the Service Principal object associated with this application.
az ad sp show --id $SPN_OBJECT_ID
# the assignee is an appId
az role assignment create --assignee $SPN_APP_ID --scope /subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${RG_KV} --role contributor
# az role assignment create --assignee $SPN_OBJECT_ID --scope /subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${RG_KV} --role contributor
# https://learn.microsoft.com/en-us/azure/key-vault/general/rbac-guide?tabs=azure-cli#azure-built-in-roles-for-key-vault-data-plane-operations
# "Key Vault Secrets User"
az role assignment create --assignee $SPN_APP_ID --scope /subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${RG_KV} --role 4633458b-17de-408a-b874-0445c86b69e6
# az role assignment create --assignee $SPN_OBJECT_ID --scope /subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${RG_KV} --role 4633458b-17de-408a-b874-0445c86b69e6
# "Key Vault Secrets Officer"
az role assignment create --assignee $SPN_APP_ID --scope /subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${RG_KV} --role b86a8fe4-44ce-4948-aee5-eccb2c155cd7
# az role assignment create --assignee $SPN_OBJECT_ID --scope /subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${RG_KV} --role b86a8fe4-44ce-4948-aee5-eccb2c155cd7
# "DNS Zone Contributor"
# https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles#dns-zone-contributor
az role assignment create --assignee $SPN_APP_ID --scope /subscriptions/${SUBSCRIPTION_ID} --role befefa01-2a29-4197-83a8-272ff33ce314
#az role assignment create --assignee $SPN_OBJECT_ID --scope /subscriptions/${SUBSCRIPTION_ID} --role befefa01-2a29-4197-83a8-272ff33ce314
# https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles#virtual-machine-contributor
# Virtual Machine Contributor has permission 'Microsoft.Network/publicIPAddresses/read'
#az role assignment create --assignee $SPN_APP_ID --scope /subscriptions/${SUBSCRIPTION_ID} --role 9980e02c-c2be-4d73-94e8-173b1dc7cf3c
#az role assignment create --assignee $SPN_OBJECT_ID --scope /subscriptions/${SUBSCRIPTION_ID} --role 9980e02c-c2be-4d73-94e8-173b1dc7cf3c
# Network-contributor: https://learn.microsoft.com/en-us/azure/role-based-access-control/resource-provider-operations#microsoftnetwork
az role assignment create --assignee $SPN_APP_ID --scope /subscriptions/${SUBSCRIPTION_ID} --role 4d97b98b-1d4f-4787-a291-c67834d212e7
#az role assignment create --assignee $SPN_OBJECT_ID --scope /subscriptions/${SUBSCRIPTION_ID} --role 4d97b98b-1d4f-4787-a291-c67834d212e7
# https://learn.microsoft.com/en-us/azure/role-based-access-control/role-assignments-portal#prerequisites
# /!\ To assign Azure roles, you must have: requires to have Microsoft.Authorization/roleAssignments/write and Microsoft.Authorization/roleAssignments/delete permissions,
# such as User Access Administrator or Owner.
az role assignment create --assignee $SPN_APP_ID --scope /subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${RG_KV} --role Owner
az role assignment create --assignee $SPN_APP_ID --scope /subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${RG_APP} --role Owner
#az role assignment create --assignee $SPN_OBJECT_ID --scope /subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${RG_KV} --role Owner
#az role assignment create --assignee $SPN_OBJECT_ID --scope /subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${RG_APP} --role Owner
**RBAC Permission model is set on KV, the pre-req requires to have Microsoft.Authorization/roleAssignments/write and Microsoft.Authorization/roleAssignments/delete permissions, such as User Access Administrator or Owner.
https://learn.microsoft.com/en-us/azure/role-based-access-control/role-assignments-portal#prerequisites To assign Azure roles, you must have: requires to have Microsoft.Authorization/roleAssignments/write and Microsoft.Authorization/roleAssignments/delete permissions, such as User Access Administrator or Owner. **
"Key Vault Secrets User" built-in role read secret contents including secret portion of a certificate with private key. Only works for key vaults that use the 'Azure role-based access control' permission model.
Read :
- Use GitHub Actions to connect to Azure documentation.
- https://github.com/Azure/login#configure-a-service-principal-with-a-secret
Paste in your JSON object for your service principal with the name AZURE_CREDENTIALS as secrets to your GH repo Settings / Security / Secrets and variables / Actions / Actions secrets / Repository secrets
You can test your connection with CLI :
az login --service-principal -u $SPN_APP_ID -p $SPN_PWD --tenant $TENANT_ID
Add SUBSCRIPTION_ID, TENANT_ID, SPN_APP_ID and SPN_PWD as secrets to your GH repo Settings / Security / Secrets and variables / Actions / Actions secrets / Repository secrets
Finally Create a GH PAT "GH_PAT" that can be use to , publish packages and delete packages
Your GitHub personal access token needs to have the workflow scope selected. You need at least delete:packages and read:packages scopes to delete a package. You need contents: read and packages: write permissions to publish and download artifacts
Create SSH Keys, WITHOUT any passphrase (type enter if prompt)
# https://github.com/Azure/azure-quickstart-templates/blob/master/quickstarts/microsoft.resources/deployment-script-ssh-key-gen/new-key.sh
export ssh_key=aksadm
echo -e 'y' | ssh-keygen -t rsa -b 4096 -f ~/.ssh/$ssh_key -C "youremail@groland.grd" # -N $ssh_passphrase
# test
# ssh -i ~/.ssh/$ssh_key $admin_username@$network_interface_pub_ip
Add $ssh_key & $ssh_key.pub as secrets SSH_PRV_KEY & SSH_PUB_KEY to your GH repo Settings / Security / Secrets and variables / Actions / Actions secrets / Repository secrets
To avoid to hit the error below :
"The subscription is not registered to use namespace 'Microsoft.KeyVault'. See https://aka.ms/rps-not-found for how to register subscriptions.\",\r\n \"details\": [\r\n ***\r\n \"code\": \"MissingSubscriptionRegistration\"
Read the docs Just run :
az feature list --output table --namespace Microsoft.ContainerService
az feature register --namespace "Microsoft.ContainerService" --name "AKS-GitOps"
az feature register --namespace "Microsoft.ContainerService" --name "EnableWorkloadIdentityPreview"
az feature register --namespace "Microsoft.ContainerService" --name "AKS-Dapr"
az feature register --namespace "Microsoft.ContainerService" --name "EnableAzureKeyvaultSecretsProvider"
az feature register --namespace "Microsoft.ContainerService" --name "AKS-AzureDefender"
az feature register --namespace "Microsoft.ContainerService" --name "AKS-PrometheusAddonPreview"
az feature register --namespace "Microsoft.ContainerService" --name "AutoUpgradePreview"
az feature register --namespace "Microsoft.ContainerService" --name "AKS-OMSAppMonitoring"
az feature register --namespace "Microsoft.ContainerService" --name "ManagedCluster"
az feature register --namespace "Microsoft.ContainerService" --name "AKS-AzurePolicyAutoApprove"
az feature register --namespace "Microsoft.ContainerService" --name "FleetResourcePreview"
az provider list --output table
az provider list --query "[?registrationState=='Registered']" --output table
az provider list --query "[?namespace=='Microsoft.KeyVault']" --output table
az provider list --query "[?namespace=='Microsoft.OperationsManagement']" --output table
az provider register --namespace Microsoft.KeyVault
az provider register --namespace Microsoft.ContainerRegistry
az provider register --namespace Microsoft.ContainerService
az provider register --namespace Microsoft.OperationalInsights
az provider register --namespace Microsoft.DBforMySQL
az provider register --namespace Microsoft.DBforPostgreSQL
az provider register --namespace Microsoft.Compute
az provider register --namespace Microsoft.AppConfiguration
az provider register --namespace Microsoft.AppPlatform
az provider register --namespace Microsoft.EventHub
az provider register --namespace Microsoft.Kubernetes
az provider register --namespace Microsoft.KubernetesConfiguration
az provider register --namespace Microsoft.Kusto
az provider register --namespace Microsoft.ManagedIdentity
az provider register --namespace Microsoft.Monitor
az provider register --namespace Microsoft.OperationsManagement
az provider register --namespace Microsoft.Network
az provider register --namespace Microsoft.ServiceBus
az provider register --namespace Microsoft.Storage
az provider register --namespace Microsoft.Subscription
# https://learn.microsoft.com/en-us/azure/aks/cluster-extensions
az extension add --name k8s-extension
az extension update --name k8s-extension
# https://learn.microsoft.com/en-us/azure/azure-arc/kubernetes/tutorial-use-gitops-flux2?
az extension add -n k8s-configuration
source <(kubectl completion bash) # setup autocomplete in bash into the current shell, bash-completion package should be installed first.
echo "source <(kubectl completion bash)" >> ~/.bashrc
alias k=kubectl
complete -F __start_kubectl k
alias kn='kubectl config set-context --current --namespace '
export gen="--dry-run=client -o yaml"
alias kp="kubectl get pods -o wide"
alias kd="kubectl get deployment -o wide"
alias ks="kubectl get svc -o wide"
alias kno="kubectl get nodes -o wide"
alias kdp="kubectl describe pod"
alias kdd="kubectl describe deployment"
alias kds="kubectl describe service"
vi ~/.vimrc
set ts=2 sw=2
. ~/.vimrc
https://learn.microsoft.com/en-us/azure/aks/managed-aad
# List existing groups in the directory
#az ad group list --filter "displayname eq '<group-name>'" -o table
az ad group list -o table
# Create an Azure AD group
AAD_ADM_GRP="AKS TAP Admin Group"
az ad group create --display-name "$AAD_ADM_GRP" --mail-nickname akstapadmingroup
aad_admin_group_object_id=$(az ad group show -g "$AAD_ADM_GRP" --query id -o tsv)
echo "aad_admin_group_object_id" : $aad_admin_group_object_id
# Add Users to the above Azure AD Admin Group
# The object ID of the User, or service principal.
USR_ID=$(az account show --query user.name -o tsv)
USR_SPN_ID=$(az ad user show --id ${USR_ID} --query id -o tsv)
az ad group member add --member-id $USR_SPN_ID -g $aad_admin_group_object_id
SPN_APP_NAME="gha_aks_tap_run"
SPN_OBJECT_ID=$(az ad sp list --all --query "[?appDisplayName=='${SPN_APP_NAME}'].{id:id}" --output tsv)
az ad group member add --member-id $SPN_OBJECT_ID -g $aad_admin_group_object_id
TAP_GUI_BACKSTAGE_APP_NAME=tap_gui_backstage
az ad app create --display-name $TAP_GUI_BACKSTAGE_APP_NAME > aad_app_tap_gui_backstage.json
# This command will output JSON with an appId that is your client-id. The objectId is APPLICATION-OBJECT-ID
export TAP_BACKSTAGE_AUTH_MICROSOFT_CLIENT_ID=$(cat aad_app_tap_gui_backstage.json | jq -r '.appId')
export TAP_BACKSTAGE_AUTH_MICROSOFT_TENANT_ID=$(az account show --query tenantId -o tsv)
export TAP_BACKSTAGE_AUTH_MICROSOFT_OBJECT_ID=$(cat aad_app_tap_gui_backstage.json | jq -r '.id')
az ad sp create --id $TAP_BACKSTAGE_AUTH_MICROSOFT_CLIENT_ID > aad_sp_tap_gui_backstage.json
az ad app credential reset --id $TAP_BACKSTAGE_AUTH_MICROSOFT_CLIENT_ID > aad_app_secret_tap_gui_backstage.json
export TAP_BACKSTAGE_AUTH_MICROSOFT_CLIENT_SECRET=$(cat aad_app_secret_tap_gui_backstage.json | jq -r '.password')
TAP_GUI_BACKSTAGE_APP_ID=$(az ad sp list --all --query "[?appDisplayName=='${TAP_GUI_BACKSTAGE_APP_NAME}'].{appId:appId}" --output tsv)
TAP_GUI_BACKSTAGE_OBJECT_ID=$(az ad sp list --all --query "[?appDisplayName=='${TAP_GUI_BACKSTAGE_APP_NAME}'].{id:id}" --output tsv)
TAP_GUI_BACKSTAGE_APP_OBJECT_ID=$(az ad app list --filter "displayName eq '$TAP_GUI_BACKSTAGE_APP_NAME'" --query "[?displayName=='$TAP_GUI_BACKSTAGE_APP_NAME'].{id:id}" -o tsv | tr -d '\r')
az ad app show --id $TAP_GUI_BACKSTAGE_APP_OBJECT_ID
Add AAD_ADM_GRP as secrets AAD_ADM_GRP to your GH repo Settings / Security / Secrets and variables / Actions / Actions secrets / Repository secrets
Add TAP_BACKSTAGE_AUTH_MICROSOFT_CLIENT_ID, TAP_BACKSTAGE_AUTH_MICROSOFT_CLIENT_SECRET & TAP_BACKSTAGE_AUTH_MICROSOFT_TENANT_ID as secrets to your GH repo Settings / Security / Secrets and variables / Actions / Actions secrets / Repository secrets
Once the IaC deployment workflow is sucessfully completed follow those nex tsteps to continue TAP Installation.
Read https://azure.github.io/azure-workload-identity/docs/installation/azwi.html
Install Azure AD Workload Identity CLI
AAD_WI_CLI_VERSION=1.0.0-beta.0 # 0.15.0
wget https://github.com/Azure/azure-workload-identity/releases/download/v$AAD_WI_CLI_VERSION/azwi-v$AAD_WI_CLI_VERSION-linux-amd64.tar.gz
gunzip azwi-v$AAD_WI_CLI_VERSION-linux-amd64.tar.gz
tar -xvf azwi-v$AAD_WI_CLI_VERSION-linux-amd64.tar
./azwi version
Once the AKS cluster is created, creates Dev & Ops Groups :
LOCATION="westeurope"
AKS_CLUSTER_NAME="aks-tap42"
RG_APP="rg-aks-tap-apps"
TANZU_INSTALL_DIR=tanzu
APP_NAME=tap42
aks_cluster_id=$(az aks show -n $AKS_CLUSTER_NAME -g $RG_APP --query id -o tsv)
echo "AKS cluster ID : " $aks_cluster_id
# Create the first example group in Azure AD for the application developers
APPDEV_ID=$(az ad group create --display-name appdev-${APP_NAME} --mail-nickname appdev-${APP_NAME} --query id -o tsv)
echo "APPDEV GROUP ID: " $APPDEV_ID
az role assignment create --assignee $APPDEV_ID --role "Azure Kubernetes Service Cluster User Role" --scope $aks_cluster_id
# Create a second example group, this one for SREs named opssre
OPSSRE_ID=$(az ad group create --display-name opssre-${APP_NAME} --mail-nickname opssre-${APP_NAME} --query id -o tsv)
echo "OPSSRE GROUP ID: " $OPSSRE_ID
az role assignment create --assignee $OPSSRE_ID --role "Azure Kubernetes Service Cluster User Role" --scope $aks_cluster_id
password=P@ssw0rd1 # Change it !!!
# You must use one of the verified domain names in your organization ex: foo@xxxEnvMCAP123456.onmicrosoft.com
VERIFIED_DOMAIN=xxxEnvMCAP123456.onmicrosoft.com
# Create a user for the Dev role
AKSDEV_ID=$(az ad user create --display-name "AKS Dev ${APP_NAME}" --user-principal-name "aksdev@$VERIFIED_DOMAIN" --password $password --query id -o tsv)
echo "AKS DEV USER ID: " $AKSDEV_ID
# Add the user to the appdev Azure AD group
az ad group member add --member-id $AKSDEV_ID --group appdev-${APP_NAME}
# Create a user for the SRE role
AKSSRE_ID=$(az ad user create --display-name "AKS SRE ${APP_NAME}" --user-principal-name "akssre@$VERIFIED_DOMAIN" --password $password --query id -o tsv)
echo "AKS SRE USER ID: " $AKSSRE_ID
# Add the user to the opssre Azure AD group
az ad group member add --member-id $AKSSRE_ID --group opssre-${APP_NAME}
# https://learn.microsoft.com/en-us/azure/aks/managed-aad#prerequisites
helm version
KUBELOGIN_VERSION=0.0.27
wget https://github.com/Azure/kubelogin/releases/download/v$KUBELOGIN_VERSION/kubelogin-linux-amd64.zip # -O kubelogin
sudo apt install unzip
unzip kubelogin-linux-amd64.zip
ls -al bin/linux_amd64/kubelogin
sudo mv bin/linux_amd64/kubelogin /usr/local/bin
ls -al /usr/local/bin/kubelogin
# Copy the latest Releases to shell's search path.
#vim ~/.profile
#. .profile
#vim ~/.bashrc
az aks get-credentials --name $AKS_CLUSTER_NAME -g $RG_APP
export KUBECONFIG=~/.kube/config
which kubelogin
kubelogin --version
kubelogin convert-kubeconfig -l azurecli
kubectl get no
kubectl apply -f $TANZU_INSTALL_DIR/k8s/role-dev-namespace.yaml
kubectl apply -f $TANZU_INSTALL_DIR/k8s/role-sre-namespace.yaml
export DEV_GROUP_OBECT_ID=$APPDEV_ID
envsubst < $TANZU_INSTALL_DIR/k8s/rolebinding-dev-namespace.yaml > $TANZU_INSTALL_DIR/k8s/deploy/rolebinding-dev-namespace.yaml
cat $TANZU_INSTALL_DIR/k8s/deploy/rolebinding-dev-namespace.yaml
kubectl apply -f ./$TANZU_INSTALL_DIR/k8s/deploy/rolebinding-dev-namespace.yaml
kubectl describe role dev-user-full-access -n development
kubectl describe rolebindings dev-user-access -n development
export SRE_GROUP_OBECT_ID=$OPSSRE_ID
envsubst < ./$TANZU_INSTALL_DIR/k8s/rolebinding-sre-namespace.yaml > ./$TANZU_INSTALL_DIR/k8s/deploy/rolebinding-sre-namespace.yaml
kubectl apply -f ./$TANZU_INSTALL_DIR/k8s/deploy/rolebinding-sre-namespace.yaml
export AKS_ADM_GROUP_OBECT_ID=$aad_admin_group_object_id
envsubst < ./$TANZU_INSTALL_DIR/k8s/aad-cluster-admin-binding.yaml > ./$TANZU_INSTALL_DIR/k8s/deploy/aad-cluster-admin-binding.yaml
cat ./$TANZU_INSTALL_DIR/k8s/deploy/aad-cluster-admin-binding.yaml
kubectl apply -f $TANZU_INSTALL_DIR/k8s/deploy/aad-cluster-admin-binding.yaml
kubectl apply -f $TANZU_INSTALL_DIR/k8s/aad-kapp-controller-binding.yaml
kubectl apply -f $TANZU_INSTALL_DIR/k8s/aad-metadata-store-binding.yaml
kubectl apply -f $TANZU_INSTALL_DIR/k8s/aad-tanzu-ingress-binding.yaml
kubectl apply -f $TANZU_INSTALL_DIR/k8s/aad-tap-install-binding.yaml
kubectl get clusterrolebindings -A
kubectl describe clusterrolebindings owner-cluster-admin
kubectl describe clusterrolebindings aks-cluster-admin-binding
kubectl describe clusterrolebindings aks-cluster-admin-binding-aad
kubectl get clusterroles -A
kubectl describe clusterrole admin
kubectl describe clusterrole cluster-admin
Create a folder named "tanzu" on your workstattion / local git grepo. The here under folders are already excluded in the .gitignore :
- tanzu/cli/*
- tanzu/tanzu-framework-linux-amd64-v0.25.4.tar
- tanzu/tanzu-cluster-essentials-linux-amd64-1.4.0.tgz
Read Tanzu docs to get the pre-req. You will get 3 files, and save them to the tanzu folder :
- tanzu/tanzu-framework-linux-amd64-v0.25.4.tar (the version name must match M.n.p like v0.25.4 NOT v0.25.4.1)
- tanzu/tanzu-cluster-essentials-linux-amd64-1.4.0.tgz
- tap-gui-blank-catalog.tgz
Those files are too big to get pushed using git CLI, instead you will upload them during the IaC deployment as soon as the Storage account is created. Once the Storage account is created, run this CLI snippet from your workstation :
# "/subscriptions/${SUBSCRIPTION_ID}/providers/Microsoft.Authorization/roleDefinitions/ba92f5b4-2d11-453d-a403-e96b0029c9fe"
# your subscription must have Role "Storage Blob Data Contributor"
USR_ID=$(az account show --query user.name -o tsv | tr -d '\r')
USR_SPN_ID=$(az ad user show --id ${USR_ID} --query id -o tsv)
SUBSCRIPTION_ID=$(az account show --query id -o tsv | tr -d '\r')
AZ_STORAGE_NAME=statapXXX
az role assignment create --scope "/subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${RG_APP}" --role "Storage Blob Data Contributor" --assignee-principal-type "User" --assignee-object-id "$USR_SPN_ID"
# ==== Tanzu Tools ====
TANZU_INSTALL_DIR=./tanzu
TANZU_CLI=tanzu-framework-linux-amd64-v0.25.4.tar # /!\ the version name must match M.n.p like v0.25.4 NOT v0.25.4.1
TANZU_ESSENTIALS=tanzu-cluster-essentials-linux-amd64-1.4.0.tgz
TANZU_GUI_CAT=tap-gui-blank-catalog.tgz
TANZU_BLOB_CLI=tanzu-cli
TANZU_BLOB_ESSENTIALS=tanzu-essentials
TANZU_BLOB_GUI_CAT=tanzu-catalog
RG_APP=rg-aks-tap-apps # RG where to deploy the other Azure services: AKS, TAP, ACR, MySQL, etc.
# ==== Azure storage , values must be consistent with the ones in iac/bicep/modules/aks/storage.bicep ====
AZ_STORAGE_NAME=statapaks # customize this
AZ_BLOB_CONTAINER_NAME=statapaks-blob # customize this
# AZ_BLOB_SVC_NAME: default # MUST NOT BE MODIFIED
# https://learn.microsoft.com/en-us/rest/api/storageservices/setting-timeouts-for-blob-service-operations
AZ_BLOB_MAX_CONNECTIONS=10
AZ_BLOB_MAXSIZE_CONDITION=440401920 # 420 Mb
AZ_BLOB_TIMEOUT=600
LOCAL_IP=$(curl whatismyip.akamai.com)
echo "LOCAL_IP="$LOCAL_IP
az config set extension.use_dynamic_install=yes_without_prompt
echo "About to upload tools to Azure BLOB Storage. /!\ --overwrite' is in preview and under development"
echo "AZ_BLOB_MAX_CONNECTIONS=$AZ_BLOB_MAX_CONNECTIONS"
echo "AZ_BLOB_TIMEOUT=$AZ_BLOB_TIMEOUT "
echo "AZ_BLOB_MAX_CONNECTIONS=$AZ_BLOB_MAX_CONNECTIONS"
echo "About to ADD network-rule to ALLOW $LOCAL_IP to Azure BLOB Storage AZ_STORAGE_NAME"
az storage account network-rule add --ip-address $LOCAL_IP --account-name $AZ_STORAGE_NAME --action "Allow" -g $RG_APP --only-show-errors
# https://learn.microsoft.com/en-us/rest/api/storageservices/setting-timeouts-for-blob-service-operations
az storage blob upload --name $TANZU_GUI_CAT --file $TANZU_INSTALL_DIR/$TANZU_GUI_CAT --container-name $AZ_BLOB_CONTAINER_NAME --account-name $AZ_STORAGE_NAME --auth-mode login --overwrite --max-connections $AZ_BLOB_MAX_CONNECTIONS --timeout $AZ_BLOB_TIMEOUT
az storage blob upload --name $TANZU_BLOB_CLI --file $TANZU_INSTALL_DIR/$TANZU_CLI --container-name $AZ_BLOB_CONTAINER_NAME --account-name $AZ_STORAGE_NAME --auth-mode login --overwrite --max-connections $AZ_BLOB_MAX_CONNECTIONS --timeout $AZ_BLOB_TIMEOUT
az storage blob upload --name $TANZU_BLOB_ESSENTIALS --file $TANZU_INSTALL_DIR/$TANZU_ESSENTIALS --container-name $AZ_BLOB_CONTAINER_NAME --account-name $AZ_STORAGE_NAME --auth-mode login --overwrite --max-connections $AZ_BLOB_MAX_CONNECTIONS --timeout $AZ_BLOB_TIMEOUT
echo "About to REMOVE network-rule ALLOWING $LOCAL_IP to Azure BLOB Storage $AZ_STORAGE_NAME"
az storage account network-rule remove --ip-address $LOCAL_IP --account-name $AZ_STORAGE_NAME -g $RG_APP --only-show-errors
Install TAP CLI on your workstation/WSL
TANZU_INSTALL_DIR=tanzu
TANZU_CLI_VERSION=v0.25.4 # file name must have version with v0.25.4 NOT v0.25.4.1
tar -xvf $TANZU_INSTALL_DIR/tanzu-framework-linux-amd64-$TANZU_CLI_VERSION.tar -C $TANZU_INSTALL_DIR
export TANZU_CLI_NO_INIT=true
TANZU_ESSENTIALS=tanzu-cluster-essentials-linux-amd64-1.4.0.tgz
tar -xvf $TANZU_INSTALL_DIR/$TANZU_ESSENTIALS -C $TANZU_INSTALL_DIR
cd $TANZU_INSTALL_DIR
export VERSION=$TANZU_CLI_VERSION
sudo install cli/core/$VERSION/tanzu-core-linux_amd64 /usr/local/bin/tanzu
tanzu version
tanzu plugin install --local cli all
tanzu plugin list
sudo cp kapp /usr/local/bin/kapp
sudo cp imgpkg /usr/local/bin/imgpkg
kapp --help
imgpkg copy --help
cd ..
Check & modify the file .env or setenv.bat :
export $(cat .env | xargs)
pwd
mkdir ./$TANZU_INSTALL_DIR/deploy
envsubst < ./$TANZU_INSTALL_DIR/tap-values.yml > ./$TANZU_INSTALL_DIR/deploy/tap-values.yml
echo "Cheking folder " ./$TANZU_INSTALL_DIR/deploy
ls -al ./$TANZU_INSTALL_DIR/deploy
cat ./$TANZU_INSTALL_DIR/deploy/tap-values.yml
Fork those repos :
- https://github.com/ezYakaEagle442/tanzu-simple
- https://github.com/ezYakaEagle442/tap-catalog
- https://github.com/ezYakaEagle442/tanzu-tools
- https://github.com/ezYakaEagle442/tanzu-app-deploy
https://github.com/ezYakaEagle442/tanzu-simple/blob/main/k8s/02-deployment.yml#L18 ==> image d'ACR a remplacer https://github.com/ezYakaEagle442/tanzu-simple/blob/main/config/workload.yaml#L15 https://github.com/ezYakaEagle442/tanzu-simple/blob/main/config/deliverable.yaml#L19
https://github.com/ezYakaEagle442/tap-catalog/blob/main/api/petstore.yaml#L17 https://github.com/ezYakaEagle442/tap-catalog/blob/main/api/tanzu-app.yaml#L17 https://github.com/ezYakaEagle442/tap-catalog/blob/main/api/openapi/openapi-tanzu-app.yaml#L7 ==> URL mut be updated
https://github.com/ezYakaEagle442/tanzu-tools/blob/main/tap/data/workload.yaml#L14 ==> URL mut be updated
troubleshoot namespace stuck in terminating-state read this.
#
kubectl get namespaces
i=0
for ns in $(kubectl get ns -o=custom-columns=:.metadata.name)
do
for status in $(kubectl get ns $ns -o=custom-columns=:status.phase)
do
if [[ "$status" == "Terminating" ]]
then
echo "Verifying Namespace $ns with status $status"
kubectl get namespace $ns -o json > tmp-$i.json
i=$((i+1))
echo "i="$i
fi
done
done
# Edit your tmp.json file. Remove the kubernetes value from the finalizers field and save the file. It should look like :
# "spec": {
# },
i=0
for ns in $(kubectl get ns -o=custom-columns=:.metadata.name)
do
for status in $(kubectl get ns $ns -o=custom-columns=:status.phase)
do
if [[ "$status" == "Terminating" ]]
then
echo "Verifying Namespace $ns with status $status"
curl -k -H "Content-Type: application/json" -X PUT --data-binary @tmp-$i.json http://127.0.0.1:8001/api/v1/namespaces/$ns/finalize
i=$((i+1))
echo "i="$i
fi
done
done
# cat bad.json | jq '. | setpath(["metadata","finalizers"]; [])' | curl -kD- -H "Content-Type: application/json" -X PUT --#data-binary @- "127.0.0.1:8001$(cat bad.json | jq -r '.metadata.selfLink')"
# To set a temporary proxy IP and port, run the following command. Be sure to keep your terminal window open until you delete the stuck namespace
kubectl proxy
kubectl get namespaces
# To add a dummy Pod to connect to it :
kubectl run dummy --image=nginx --restart=Never --port=80 -n tap-gui
kubectl exec -it dummy -n tap-gui -- bash
curl http://server:7000
# https://docs.vmware.com/en/VMware-Tanzu-Application-Platform/1.4/tap/tap-gui-install-tap-gui.html
export ING_HOST=tap.appinno.com #tap.westeurope.cloudapp.azure.com
echo "INGRESS HOST " $ING_HOST
mkdir $TANZU_INSTALL_DIR/k8s/deploy
envsubst < $TANZU_INSTALL_DIR/k8s/contour-ingress.yaml > $TANZU_INSTALL_DIR/k8s/deploy/contour-ingress.yaml
cat $TANZU_INSTALL_DIR/k8s/deploy/contour-ingress.yaml
kubectl apply -f $TANZU_INSTALL_DIR/k8s/deploy/contour-ingress.yaml -n tap-gui
kubectl get ing -n tap-gui
kubectl get httpproxy -n tap-gui
# https://docs.vmware.com/en/VMware-Tanzu-Application-Platform/1.4/tap/tap-gui-tls-cert-mngr-ext-clusterissuer.html
envsubst < $TANZU_INSTALL_DIR/k8s/letsencrypt-prod-cluster-issuer.yaml > $TANZU_INSTALL_DIR/k8s/deploy/letsencrypt-prod-cluster-issuer.yaml
cat $TANZU_INSTALL_DIR/k8s/deploy/letsencrypt-prod-cluster-issuer.yaml
kubectl apply -f $TANZU_INSTALL_DIR/k8s/deploy/letsencrypt-prod-cluster-issuer.yaml -n cert-manager
kubectl get clusterissuer -A -o wide
kubectl describe clusterissuer letsencrypt-production
kubectl get certs -n cert-manager
tanzu package installed update tap -p tap.tanzu.vmware.com -v 1.4.0 --values-file tap-values.yaml -n tap-install
troubleshoot Git error : https://docs.github.com/en/repositories/working-with-files/managing-large-files/removing-files-from-git-large-file-storage
remote: error: File tanzu/tanzu-framework-linux-amd64-v0.25.4.1.tar is 234.56 MB; this exceeds GitHub's file size limit of 100.00 MB
remote: error: GH001: Large files detected. You may want to try Git Large File Storage - https://git-lfs.github.com.
To github.com:ezYakaEagle442/azure-tanzu-application-platform
! [remote rejected] main -> main (pre-receive hook declined)
error: failed to push some refs to 'git@github.com:ezYakaEagle442/azure-tanzu-application-platform'
git filter-branch --force --index-filter \
'git rm --cached --ignore-unmatch tanzu/tanzu-framework-linux-amd64-v0.25.4.1.tar' \
--prune-empty --tag-name-filter cat -- --all
git commit --amend -CHEAD
git push
See GitHub Actions :
- Deploy the Azure Infra services workflow
- Maven Backends Build workflow
- Maven UI Build workflow
- Java Apps Backends Deploy workflow
- Java Apps UI Deploy workflow
- Delete ALL the Azure Infra services workflow, except KeyVault
****
Workflow Design
The Workflow run the steps in this in this order :
├── Deploy the Azure Infra services workflow ./.github/workflows/deploy-iac.yml
│ ├── Trigger the pre-req ./.github/workflows/deploy-iac.yml#L75
│ ├── Create Azure Key Vault ./.github/workflows/deploy-iac-pre-req.yml#L108
│ ├── Authorize local IP to access the Azure Key Vault ./.github/workflows/deploy-iac-pre-req.yml#L115
│ ├── Create the secrets ./.github/workflows/deploy-iac-pre-req.yml#L121
│ ├── Disable local IP access to the Key Vault ./.github/workflows/deploy-iac-pre-req.yml#L152
│ ├── Deploy the pre-req ./.github/workflows/deploy-iac-pre-req.yml#L180
│ ├── Create Log Analytics Workspace ./iac/bicep/pre-req.bicep#L68
│ ├── Create appInsights ./iac/bicep/pre-req.bicep#L68
│ ├── Create ACR ./iac/bicep/pre-req.bicep#L104
│ ├── Create Identities ./iac/bicep/pre-req.bicep#L124
│ ├── Create VNet ./iac/bicep/pre-req.bicep#L135
│ ├── Create roleAssignments ./iac/bicep/pre-req.bicep#L155
│ ├── Create MySQL ./iac/bicep/pre-req.bicep#L174
│ ├── Deploy AKS ./iac/bicep/main.bicep
│ ├── Call AKS module ./iac/bicep/main.bicep#L95
│ ├── Whitelist AKS Env. OutboundIP to KV and MySQL ./.github/workflows/deploy-iac.yml#L119
│ ├── Call DB data loading Init ./.github/workflows/deploy-iac.yml#L154
│ ├── Call Maven Build ./.github/workflows/deploy-iac.yml#L159
│ ├── Maven Build ./.github/workflows/maven-build.yml#L128
│ ├── Publish the Maven package ./.github/workflows/maven-build.yml#L176
│ ├── Build image and push it to ACR ./.github/workflows/maven-build.yml#L241
│ ├── Call Maven Build-UI ./.github/workflows/deploy-iac.yml#L166
│ ├── Build image and push it to ACR ./.github/workflows/maven-build-ui.yml#L191
│ ├── Deploy Backend Services ./.github/workflows/deploy-iac.yml#L185
│ ├── Deploy Backend services calling ./.github/workflows/deploy-app-svc.yml
│ ├── Deploy the UI calling ./.github/workflows/deploy-app-ui.yml
You need to set your own param values in :
env:
# ==== Versions ====
DEPLOYMENT_VERSION: 2.6.13
AZ_CLI_VERSION: 2.45.0
JAVA_VERSION: 11
# ==== General settings ====
APP_NAME: tap42
LOCATION: westeurope # francecentral
RG_KV: rg-kv-tanzu101 # RG where to deploy KV
RG_APP: rg-aks-tap-apps # RG where to deploy the other Azure services: AKS, TAP, ACR, MySQL, etc.
# DNS
DNS_ZONE: cloudapp.azure.com
APP_DNS_ZONE: tap.westeurope.cloudapp.azure.com
CUSTOM_DNS: appinnohandsonlab.com # set here your own domain name
AZURE_DNS_LABEL_NAME: petclinic
TAP_NAMESPACE: tanzu
PETCLINIC_NAMESPACE: petclinic
AKS_CLUSTER_NAME: aks-tap42
VNET_NAME: vnet-aks
DNS_PREFIX: tanzu-tap42 # customize this param
ING_NS: ingress # Namespace to use for the Ingress Controller
AKS_IDENTITY_NAME: id-aks-tap42-cluster-dev-westeurope-101 # customize this , MUST BE 'id-aks-${appName}-cluster-dev-${location}-101'
# ==== Identities ====:
CUSTOMERS_SVC_APP_ID_NAME: id-aks-tap42-petclinic-customers-service-dev-westeurope-101 # customize this, MUST BE 'id-aks-${appName}-petclinic-customers-service-dev-${location}-101'
VETS_SVC_APP_ID_NAME: id-aks-tap42-petclinic-vets-service-dev-westeurope-101 # customize this, MUST BE 'id-aks-${appName}-petclinic-vets-service-dev-${location}-101'
VISITS_SVC_APP_ID_NAME: id-aks-tap42-petclinic-visits-service-dev-westeurope-101 # customize this, MUST BE 'id-aks-${appName}-petclinic-visits-service-dev-${location}-101'
CONFIG_SERVER_APP_ID_NAME: id-aks-tap42-petclinic-config-server-dev-westeurope-101 # customize this, MUST BE 'id-aks-${appName}-petclinic-config-server-dev-${location}-101'
# MySQL
MYSQL_SERVER_NAME: tap42
MYSQL_DB_NAME: petclinic
MYSQL_ADM_USR: mys_adm
MYSQL_TIME_ZONE: Europe/Paris
MYSQL_CHARACTER_SET: utf8
MYSQL_COLLATION: utf8_general_ci
MYSQL_PORT: 3306
MYSQL_VERSION: "5.7" # "8.0.21"
# SKU common for MySQL & PG
DB_SKU_NAME: Standard_B1ms
DB_SKU_TIER : Burstable
# PG
PG_SERVER_NAME: tap42
PG_DB_NAME: tap
PG_ADM_USR: pgs_adm
PG_TIME_ZONE: Europe/Paris
PG_CHARACTER_SET: utf8
PG_COLLATION: fr_FR.utf8 # select * from pg_collation ;
PG_PORT: 5432
PG_VERSION: "13"
# ==== Versions ====
DEPLOYMENT_VERSION: 2.6.13
AZ_CLI_VERSION: 2.45.0
JAVA_VERSION: 11
# ==== General settings ====
RG_KV: rg-kv-tanzu101 # RG where to deploy KV
RG_APP: rg-aks-tap-apps # RG where to deploy the other Azure services: AKS, TAP, ACR, MySQL, etc.
REPOSITORY: tap # set this to your ACR repository
PROJECT_NAME: petclinic # set this to your project's name
env:
# ==== Versions ====
DEPLOYMENT_VERSION: 2.6.13
AZ_CLI_VERSION: 2.45.0
JAVA_VERSION: 11
# ==== General settings ====
RG_APP: rg-aks-tap-apps # RG where to deploy the other Azure services: AKS, TAP, ACR, MySQL, etc.
REPOSITORY: tap # set this to your ACR repository
Once you commit, then push your code update to your repo, it will trigger a Maven build which you need to can CANCELL from https://github.com/USERNAME/azure-tanzu-application-platform/actions/workflows/maven-build.yml the first time you trigger the workflow, anyway it will fail because the ACR does not exist yet and the docker build will fail to push the Images.
Note: the GH Hosted Runner / Ubuntu latest image has already Azure CLI installed
env:
# ==== Versions ====
TANZU_CLI_VERSION: v0.25.4
TAP_VERSION_NUMBER: 1.4.0
CERT_MANAGER_VERSION: v1.11.0
AZ_CLI_VERSION: 2.45.0
# ==== General settings ====
APP_NAME: tap42
LOCATION: westeurope # francecentral
RG_KV: rg-kv-tanzu101 # RG where to deploy KV
RG_APP: rg-aks-tap-apps # RG where to deploy the other Azure services: AKS, TAP, ACR, MySQL, etc.
#DNS_ZONE: cloudapp.azure.com
#APP_DNS_ZONE: westeurope.cloudapp.azure.com
CUSTOM_DNS: appinnohandsonlab.com
AZURE_DNS_LABEL_NAME: tap-gui
TANZU_DNS_CHILD_ZONE: tap.appinnohandsonlab.com
CATALOG_URL: https://github.com/ezYakaEagle442/tap-catalog
cloudapp.azure.com DNZ zone can not be used because child zone *.tap. is required, ex: tap-gui.tap.mydomain.com. You must therefote use your own custom domain, once the IaC workflows has sucessfully deployed AKS and the Azure DNS zone,
https://docs.microsoft.com/en-us/azure/dns/dns-delegate-domain-azure-dns#delegate-the-domain
LOCATION="westeurope"
RG_APP="rg-aks-tap-apps"
DNS_ZONE="appinno.com" # set here your own domain name
ns_server=$(az network dns record-set ns show --zone-name $DNS_ZONE --name @ -g $RG_APP --query nsRecords[0] --output tsv)
ns_server_length=$(echo -n $ns_server | wc -c)
ns_server="${ns_server:0:$ns_server_length-1}"
echo "Name Server 1" $ns_server
ns_server=$(az network dns record-set ns show --zone-name $DNS_ZONE --name @ -g $RG_APP --query nsRecords[1] --output tsv)
ns_server_length=$(echo -n $ns_server | wc -c)
ns_server="${ns_server:0:$ns_server_length-1}"
echo "Name Server 2" $ns_server
In the registrar's DNS management page, edit the NS records and replace the NS records with the Azure DNS name servers.
nslookup $DNS_ZONE $ns_server
Read https://docs.vmware.com/en/VMware-Tanzu-Application-Platform/1.4/tap/authn-authz-azure-ad.html
Identify or create a list of groups in the Azure AD for each of the Tanzu Application Platform default roles (app-operator, app-viewer, and app-editor) :
LOCATION="westeurope"
AKS_CLUSTER_NAME="aks-tap42"
RG_APP="rg-aks-tap-apps"
TANZU_INSTALL_DIR=tanzu
APP_NAME=tap42
aks_cluster_id=$(az aks show -n $AKS_CLUSTER_NAME -g $RG_APP --query id -o tsv)
echo "AKS cluster ID : " $aks_cluster_id
az aks get-credentials --name $AKS_CLUSTER_NAME -g $RG_APP
# Create the first example group in Azure AD for the application developers
TAP_APP_OPERATOR_ID=$(az ad group create --display-name tap-app-operator --mail-nickname tap-app-operator --query id -o tsv)
echo "TAP APP OPERATOR GROUP ID: " $TAP_APP_OPERATOR_ID
TAP_APP_OPERATOR_ID=$(az ad group show --group tap-app-operator --query id -o tsv | tr -d '\r')
az role assignment create --assignee $TAP_APP_OPERATOR_ID --role "Azure Kubernetes Service Cluster User Role" --scope $aks_cluster_id
TAP_APP_VIEWER_ID=$(az ad group create --display-name tap-app-viewer --mail-nickname tap-app-viewer --query id -o tsv)
echo "TAP APP OPERATOR GROUP ID: " $TAP_APP_VIEWER_ID
TAP_APP_VIEWER_ID=$(az ad group show --group tap-app-viewer --query id -o tsv | tr -d '\r')
az role assignment create --assignee $TAP_APP_VIEWER_ID --role "Azure Kubernetes Service Cluster User Role" --scope $aks_cluster_id
TAP_APP_EDITOR_ID=$(az ad group create --display-name tap-app-edittor --mail-nickname tap-app-edittor --query id -o tsv)
echo "TAP APP EDITOR GROUP ID: " $TAP_APP_EDITOR_ID
TAP_APP_EDITOR_ID=$(az ad group show --group tap-app-edittor --query id -o tsv | tr -d '\r')
az role assignment create --assignee $TAP_APP_EDITOR_ID --role "Azure Kubernetes Service Cluster User Role" --scope $aks_cluster_id
Install the Tanzu Application Platform RBAC CLI plug-in Download the Tanzu Application Platform RBAC CLI plug-in tar.gz file from Tanzu Network
tar -zxvf tanzu-auth-plugin_1.1.0-beta.1.tar.gz
tanzu plugin install rbac --local linux-amd64
# Which NS ??? ==> workaround : allow to ALL NS, not good from a security perspective
# tanzu rbac binding add -g OBJECT-ID -r TAP-ROLE -n NAMESPACE
TAP_NAMESPACE=tanzu
DEV_NAMESPACE=tap-dev
TAP_INSTALL_NAMESPACE=tap-install
KAPP_NAMESPACE=kapp-controller
AAD_ADM_GRP="AKS TAP Admin Group"
aad_admin_group_object_id=$(az ad group show -g "$AAD_ADM_GRP" --query id -o tsv)
echo "aad_admin_group_object_id" : $aad_admin_group_object_id
tanzu rbac binding add -g $aad_admin_group_object_id -r app-operator -n $TAP_INSTALL_NAMESPACE
tanzu rbac binding add -g $aad_admin_group_object_id -r app-viewer -n $TAP_INSTALL_NAMESPACE
tanzu rbac binding add -g $aad_admin_group_object_id -r app-editor -n $TAP_INSTALL_NAMESPACE
tanzu rbac binding add -g $aad_admin_group_object_id -r service-operator -n $TAP_INSTALL_NAMESPACE
# Only TAP default roles are support [app-viewer, app-editor, app-operator, service-operator]
tanzu rbac binding add -g $TAP_APP_OPERATOR_ID -r app-operator -n $TAP_NAMESPACE
tanzu rbac binding add -g $TAP_APP_VIEWER_ID -r app-viewer -n $DEV_NAMESPACE
tanzu rbac binding add -g $TAP_APP_EDITOR_ID -r app-editor -n $DEV_NAMESPACE
tanzu rbac binding add -g $TAP_APP_EDITOR_ID -r app-editor -n $KAPP_NAMESPACE
# tanzu rbac binding add -g $TAP_APP_OPERATOR_ID -r app-operator -A
# tanzu rbac binding add -g $TAP_APP_VIEWER_ID -r app-viewer -A
# tanzu rbac binding add -g $TAP_APP_EDITOR_ID -r app-edittor -A
# You must use one of the verified domain names in your organization ex: foo@xxxEnvMCAP123456.onmicrosoft.com
USR_ID=$(az account show --query user.name -o tsv)
APPDEV_ID=$(az ad group show --group appdev-${APP_NAME} --query id -o tsv)
echo "APPDEV GROUP ID: " $APPDEV_ID
OPSSRE_ID=$(az ad group show --group opssre-${APP_NAME} --query id -o tsv)
echo "OPSSRE GROUP ID: " $OPSSRE_ID
tanzu rbac binding add --user $USR_ID --role app-operator --namespace $DEV_NAMESPACE
tanzu rbac binding add --user $USR_ID --role app-viewer --namespace $DEV_NAMESPACE
tanzu rbac binding add --user $USR_ID --role app-editor --namespace $DEV_NAMESPACE
tanzu rbac binding add --user $USR_ID --role service-operator --namespace $DEV_NAMESPACE
tanzu rbac binding add --group $APPDEV_ID --role app-operator --namespace $DEV_NAMESPACE
tanzu rbac binding add --group $APPDEV_ID --role app-viewer --namespace $DEV_NAMESPACE
tanzu rbac binding add --group $APPDEV_ID --role app-editor --namespace $DEV_NAMESPACE
tanzu rbac binding add --group $OPSSRE_ID --role app-operator --namespace $DEV_NAMESPACE
tanzu rbac binding add --group $OPSSRE_ID --role app-viewer --namespace $DEV_NAMESPACE
tanzu rbac binding add --group $OPSSRE_ID --role app-editor --namespace $DEV_NAMESPACE
tanzu rbac binding add --group $OPSSRE_ID --role service-operator --namespace $DEV_NAMESPACE
tanzu rbac binding get --role app-editor --namespace user-ns
# https://backstage.io/docs/auth/microsoft/provider
# https://learn.microsoft.com/en-gb/azure/active-directory/develop/reply-url
# https://mappslearning.wordpress.com/2022/04/19/enabling-microsoft-azure-authenticator-for-tanzu-application-platform-tap/
# Register reply address for the application. : /api/auth/microsoft/handler/frame
APP_DNS_ZONE=tap-gui.tap.appinno.com
az ad app update \
--id ${TAP_BACKSTAGE_AUTH_MICROSOFT_CLIENT_ID} \
--web-redirect-uris "https://${APP_DNS_ZONE}/api/auth/microsoft/handler/frame"
# test from a browser:
https://tap-gui.tap.appinno.com/api/auth/microsoft
https://tap-gui.tap.appinno.com/api/auth/github
envsubst < ./$TANZU_INSTALL_DIR/tap-values.yml > ./$TANZU_INSTALL_DIR/deploy/tap-values.yml
echo "Cheking folder " ./$TANZU_INSTALL_DIR/deploy
ls -al ./$TANZU_INSTALL_DIR/deploy
cat ./$TANZU_INSTALL_DIR/deploy/tap-values.yml
Access to the TAP GUI: https://tap-gui.tap.
Ex: https://tap-gui.tap.appinno.com/
To update TAP-values run the Workflow .github/workflows/update-tap-values.yml the command below :
TANZU_INSTALL_DIR=tanzu
TAP_INSTALL_NAMESPACE=tap-install
tanzu package installed update tap -p tap.tanzu.vmware.com -v $TAP_VERSION --values-file ${TANZU_INSTALL_DIR}/deploy/tap-values.yml -n ${TAP_INSTALL_NAMESPACE}
tanzu package installed list -A
To check the TAP-GUI final configiuration inside the AKS cluster :
kubernetes describe pod server-6d88c74f7d-mfrm7 -n tap-gui
kubernetes logs server-6d88c74f7d-mfrm7 -n tap-gui
kubernetes get secrets -n tap-gui
kubernetes get secret app-config-ver-1 -n tap-gui
kubernetes get secret app-config-ver-1 -n tap-gui -o jsonpath='{.data}' > app-config.encoded
cat app-config.encoded | base64 --decode > app-config.yaml
LOCATION="westeurope"
AKS_CLUSTER_NAME="aks-tap42"
RG_APP="rg-aks-tap-apps"
az aks nodepool stop --nodepool-name tapnodepool --cluster-name $AKS_CLUSTER_NAMEKSCluster -g $RG_APP
az aks nodepool start --nodepool-name tapnodepool --cluster-name $AKS_CLUSTER_NAMEKSCluster -g $RG_APP
az aks stop --cluster-name $AKS_CLUSTER_NAMEKSCluster -g $RG_APP
az aks start --cluster-name $AKS_CLUSTER_NAMEKSCluster -g $RG_APP
The issue tracker is the preferred channel for bug reports, features requests and submitting pull requests.
For pull requests, editor preferences are available in the editor config for easy use in common text editors. Read more and download plugins at http://editorconfig.org.
https://github.com/ezYakaEagle442/azure-tanzu-application-platform has been forked from https://github.com/ezYakaEagle442/aks-java-petclinic-mic-srv, itself already forked from https://github.com/spring-petclinic/spring-petclinic-microservices
It is not possible to fork twice a repository using the same user account. However you can duplicate a repository
This repo https://github.com/ezYakaEagle442/azure-tanzu-application-platform has been duplicated from https://github.com/spring-petclinic/spring-petclinic-microservices
source <(kubectl completion bash) # setup autocomplete in bash into the current shell, bash-completion package should be installed first.
echo "source <(kubectl completion bash)" >> ~/.bashrc
alias k=kubectl
complete -F __start_kubectl k
alias kn='kubectl config set-context --current --namespace '
export gen="--dry-run=client -o yaml"
alias kp="kubectl get pods -o wide"
alias kd="kubectl get deployment -o wide"
alias ks="kubectl get svc -o wide"
alias kno="kubectl get nodes -o wide"
alias kdp="kubectl describe pod"
alias kdd="kubectl describe deployment"
alias kds="kubectl describe service"
vi ~/.vimrc
set ts=2 sw=2
. ~/.vimrc
``