This article is going to tackle the installation of VMware Tanzu Application Platform and securing the UI with transport layer security (TLS) and Microsoft Windows Azure Active Directory (Azure AD). But first, what is the Tanzu Application Platform?
VMware Tanzu Application Platform is a modular, application-aware platform that provides a rich set of developer tooling and a pre-paved path to production. Additionally, it allows developers to build and deploy software quickly and securely on any compliant public cloud or on-premises Kubernetes cluster.
Below is a great diagram of what Tanzu Application Platform is conceptually. For a more in-depth look at how Tanzu Application Platform works, read this article by Gowtham Shankar.
Installing Tanzu Application Platform is pretty straightforward, but there are still a few gotchas that this post will help out with.
- First, please have a look at the prerequisites.
- You will also need to have access to VMware Tanzu Network.
- From Tanzu Network, download the Tanzu command line interface (CLI) for your OS and then unpack it.
- Next, you will need to download Cluster Essentials for VMware Tanzu here.
- Make sure you have accepted all applicable EULAs.
- You will also need a domain and to carve out a subdomain particularly for Tanzu Application Platform. Please note that a registry is required—for all of the examples below, Harbor will be used.
With all that out of the way, let's get started by setting up some useful exports.
export INSTALL_BUNDLE=registry.tanzu.vmware.com/tanzu-cluster-essentials/cluster-essentials-bundle@sha256:ab0a3539da241a6ea59c75c0743e9058511d7c56312ea3906178ec0f3491f51d export INSTALL_REGISTRY_HOSTNAME=registry.tanzu.vmware.com export INSTALL_REGISTRY_USERNAME=TANZU-NET-USER export INSTALL_REGISTRY_PASSWORD=TANZU-NET-PASSWORD export TAP_VERSION=1.1.0
Note that the above INSTALL_BUNDLE
is for Tanzu Application Platform 1.1.x. If you are attempting to install something older than this version, you will need to look through the Tanzu Application Platform docs to get the correct INSTALL_BUNDLE
.
Create a namespace to install Tanzu Application Platform into.
kubectl create ns tap-install
You will now need to cd into the directory where you untarred the Tanzu Cluster Essentials.
cd $HOME/tanzu-cluster-essentials ## Or wherever you have cluster-essentials untarred
Run the installer script.
./install.sh --yes
If everything completes successfully you can move on to copying kapp to our path.
sudo cp $HOME/tanzu-cluster-essentials/kapp /usr/local/bin/kapp ##Or wherever you have cluster-essentials untarred
Next,install the Tanzu CLI.
export TANZU_CLI_NO_INIT=true
cd $HOME/tanzu # or wherever you downloaded the cli install cli/core/VERSION/tanzu-core-darwin_amd64 /usr/local/bin/tanzu
Be sure to check your version.
tanzu version
Once the version is confirmed, complete a clean install of the plug-ins.
tanzu plugin clean cd $HOME/tanzu # again wherever you have downloaded this tanzu plugin install --local cli all # make sure you are not in the cli directory when you do this go one directory above it
Check the plug-ins.
tanzu plugin list
You’ll need to create a container registry secret (i.e., Docker registry secret).
tanzu secret registry add tap-registry --username ${INSTALL_REGISTRY_USERNAME} --password ${INSTALL_REGISTRY_PASSWORD} --server ${INSTALL_REGISTRY_HOSTNAME} --export-to-all-namespaces --yes --namespace tap-install
Add the Tanzu Application Platform package repository to the cluster by running:
tanzu package repository add tanzu-tap-repository --url registry.tanzu.vmware.com/tanzu-application-platform/tap-packages:$TAP_VERSION --namespace tap-install
Get the status of the Tanzu Application Platform package repository, and ensure the status updates to “reconcile” succeeded by running:
tanzu package repository get tanzu-tap-repository --namespace tap-install
Next, you’ll need to create a Tanzu Application Platform values file. Below are a few simple options, but again, our end goal is to have TLS and Azure AD in our final install.
You can find an example of a values file here. Below is an example of a standard Tanzu Application Platform values file.
profile: full ceip_policy_disclosed: true # Installation fails if this is set to 'false' buildservice: kp_default_repository: myharbor.com/tap/build-service kp_default_repository_username: YOUR_REGISTRY_USER kp_default_repository_password: YOUR_REGISTRY_PASSWORD tanzunet_username: YOUR_TANZU_USERNAME tanzunet_password: YOUR_TANZU_PASSWORD descriptor_name: "full" enable_automatic_dependency_updates: true supply_chain: basic cnrs: domain_name: tap.alexanderbrash.dev domain_template: "{{.Name}}-{{.Namespace}}.{{.Domain}}" ootb_supply_chain_basic: registry: server: myharbor.com repository: "tap/supply-chain" gitops: ssh_secret: "" learningcenter: ingressDomain: "learningcenter.tap.alexanderbrash.dev" tap_gui: service_type: ClusterIP ingressEnabled: "true" ingressDomain: "tap.alexanderbrash.dev" app_config: app: baseUrl: http://tap-gui.tap.alexanderbrash.dev #Note this must be called tap-gui I tried tap-ui and it did not work catalog: locations: - type: url target: https://github.com/badraoul/tap-test/blob/main/blank/catalog-info.yaml backend: baseUrl: http://tap-gui.tap.alexanderbrash.dev #Note this must be called tap-gui I tried tap-ui and it did not work cors: origin: http://tap-gui.tap.alexanderbrash.dev #Note this must be called tap-gui I tried tap-ui and it did not work metadata_store: app_service_type: LoadBalancer # (optional) Defaults to LoadBalancer. Change to NodePort for distributions that don't support LoadBalancer grype: namespace: "default" # (optional) Defaults to default namespace. targetImagePullSecret: "tap-registry" contour: envoy: service: type: LoadBalancer
The following is an example utilizing Amazon Web Services Network Load Balancer (AWS NLB).
profile: full ceip_policy_disclosed: true # Installation fails if this is set to 'false' buildservice: kp_default_repository: myharbor.com/tap/build-service kp_default_repository_username: HARBOR_USER kp_default_repository_password: HARBOR_PASSWORD tanzunet_username: TANZU_NET_USER tanzunet_password: TANZU_NET_PASSWORD descriptor_name: "tap-1.0.0-full" enable_automatic_dependency_updates: true supply_chain: basic cnrs: domain_name: alexanderbrash.dev ootb_supply_chain_basic: registry: server: myharbor.com repository: "tap/supply-chain" gitops: ssh_secret: "" learningcenter: ingressDomain: "lab.alexanderbrash.dev" tap_gui: service_type: ClusterIP ingressEnabled: "true" ingressDomain: "alexanderbrash.dev" app_config: app: baseUrl: http://tap-gui.alexanderbrash.dev catalog: locations: - type: url target: https://github.com/badraoul/tap-test/blob/main/blank/catalog-info.yaml backend: baseUrl: http://tap-gui.alexanderbrash.dev cors: origin: http://tap-gui.alexanderbrash.dev metadata_store: app_service_type: LoadBalancer # (optional) Defaults to LoadBalancer. Change to NodePort for distributions that don't support LoadBalancer grype: namespace: "default" # (optional) Defaults to default namespace. targetImagePullSecret: "tap-registry" contour: infrastructure_provider: aws envoy: service: aws: LBType: nlb
Below is the desired outcome and an example of using TLS.
profile: full ceip_policy_disclosed: true # Installation fails if this is set to 'false' buildservice: kp_default_repository: myharbor.com/tap/build-service kp_default_repository_username: HARBOR_USER kp_default_repository_password: HARBOR_PASSWORD tanzunet_username: TANZU_NET_USER tanzunet_password: TANZU_NET_PASSWORD descriptor_name: "full" enable_automatic_dependency_updates: true supply_chain: basic cnrs: domain_name: tap-lab.alexanderbrash.net domain_template: "{{.Name}}-{{.Namespace}}.{{.Domain}}" default_tls_secret: tls-certs/tap-lab-alexbrash-net-wldcrd ootb_supply_chain_basic: registry: server: myharbor.com repository: "tap/supply-chain" gitops: ssh_secret: "" learningcenter: ingressDomain: "learningcenter.tap-lab.alexanderbrash.net" tap_gui: service_type: ClusterIP ingressEnabled: "true" ingressDomain: "tap-lab.alexanderbrash.net" tls: secretName: tap-lab-alexbrash-net-wldcrd namespace: tls-certs app_config: app: baseUrl: https://tap-gui.tap-lab.alexanderbrash.net catalog: locations: - type: url target: https://github.com/badraoul/tap-test/blob/main/blank/catalog-info.yaml backend: baseUrl: https://tap-gui.tap-lab.alexanderbrash.net cors: origin: https://tap-gui.tap-lab.alexanderbrash.net metadata_store: app_service_type: LoadBalancer # (optional) Defaults to LoadBalancer. Change to NodePort for distributions that don't support LoadBalancer grype: namespace: "default" # (optional) Defaults to default namespace. targetImagePullSecret: "tap-registry" contour: envoy: service: type: LoadBalancer
For TLS to work you need to create a TLS delegation for Envoy and a namespace to keep the TLS secrets.
So first, create the namespace.
kubectl create ns tls-certs
Next, build the TLS delegation resource.
cat <<EOF > tls-delegation.yaml apiVersion: projectcontour.io/v1 kind: TLSCertificateDelegation metadata: name: tap-lab-alexbrash-net-wldcrd namespace: tls-certs spec: delegations: - secretName: tap-lab-alexbrash-net-wldcrd targetNamespaces: - "*" EOF
kubectl apply -f tls-delegation.yaml
Now, create the certificate in the TLS-certs namespace.
kubectl create secret tls tap-lab-alexbrash-net-wldcrd --key cert-key.pem --cert cert.pem -n tls-certs
After that, add Azure AD. By default, the Tanzu Application Platform GUI uses a guest account, but backstage supports different authentication providers (you can find a list here).
Another reason TLS is added to the Tanzu Application Platform GUI is that it's required to enable authentication.
Inside the Azure Portal, head over to "Azure Active Directory," then under "App registrations" click on "New registration." From here, simply give it a name, then under "Supported account types" select the appropriate option for your organization. (In this example, the default option was selected.) Last, under "Redirect URI" select "Web" for platform.
Next, enter the below uniform resource identifier (URI):
https://tap-gui.yourdomain/api/auth/microsoft/handler/frame
You will then need to create a client secret. Under "Certificates and secrets" select "New client secret" and follow the prompts. Please note that your client secret is the "Value" not the Secret ID. (I made that mistake and was troubleshooting why things were not working for a while.)
For the values file you will need the following three things:
- client ID
- tenant ID
- client secret
Your values file will now look like this:
profile: full ceip_policy_disclosed: true # Installation fails if this is set to 'false' buildservice: kp_default_repository: HARBOR_REGISTRY_URL/tap/build-service kp_default_repository_username: HARBOR_USER kp_default_repository_password: HARBOR_PASSWORD tanzunet_username: TANZU_NET_USER tanzunet_password: TANZU_NET_PASSWORD descriptor_name: "full" enable_automatic_dependency_updates: true supply_chain: basic cnrs: domain_name: tap.alexanderbrash.dev domain_template: "{{.Name}}-{{.Namespace}}.{{.Domain}}" default_tls_secret: tls-certs/tap-alexbrash-dev-wildcard ootb_supply_chain_basic: registry: server: HARBOR_REGISTRY_URL repository: "tap/supply-chain" gitops: ssh_secret: "" learningcenter: ingressDomain: "learningcenter.tap.alexanderbrash.dev" tap_gui: service_type: ClusterIP ingressEnabled: "true" ingressDomain: "tap.alexanderbrash.dev" tls: secretName: tap-alexbrash-dev-wildcard namespace: tls-certs app_config: auth: allowGuestAccess: false environment: development providers: microsoft: development: clientId: AZURE_CLIENTID clientSecret: AZURE_CLIENT_SECRET tenantId: AZURE_TENANTID app: baseUrl: https://tap-gui.tap.alexanderbrash.dev catalog: locations: - type: url target: https://github.com/badraoul/tap-test/blob/main/blank/catalog-info.yaml backend: baseUrl: https://tap-gui.tap.alexanderbrash.dev cors: origin: https://tap-gui.tap.alexanderbrash.dev metadata_store: app_service_type: LoadBalancer # (optional) Defaults to LoadBalancer. Change to NodePort for distributions that don't support LoadBalancer grype: namespace: "default" # (optional) Defaults to default namespace. targetImagePullSecret: "tap-registry" contour: envoy: service: type: LoadBalancer
With all that out of the way, let's install the Tanzu Application Platform.
tanzu package install tap -p tap.tanzu.vmware.com -v $TAP_VERSION --values-file tap-values.yml -n tap-install
You will need to ensure that all packages are reconciling successfully.
tanzu package installed list -n tap-install
Please note: install times depend on the available resources in your cluster. With that in mind, I recommend at least four m5.x large nodes (i.e.g, four nodes that are 4vCPUs and 16GB of RAM with at least 70GB of disk space).
A successful reconciliation looks like the image below:
And that's it—you now have the Tanzu Application Platform up and running!