Skip to content

Tanzu Packages Explained

In this blog post, I will describe what Tanzu Packages are and how they can be used. You might have read about Tanzu Kubernetes Grid (TKG) Extensions in my previous blog post or the official VMware documentation. However, Tanzu Packages are the evolution of TKG Extensions. They easily install add-ons such as Cert-Manager, Contour, Prometheus, Harbor, and others onto your TKG clusters via the Tanzu CLI. Tanzu Packages have been introduced with the Tanzu Community Edition and as part of TKG 1.4. If you have played with both solutions, you will have realized that they are using different package repositories with slightly different content. The reason being is that the TKG 1.4 repository includes all compatible, tested, and VMware-supported packages. Tanzu Community Edition is open-source, and therefore packages will be maintained and supported by the community. A comparison between the different Tanzu Editions and their content can be found here.

List of TKG 1.4 supported packages:

A list of Tanzu Community Edition packages can be found here:

If you are using Tanzu Mission Control (TMC), it also has a new catalog feature that deploys Tanzu Packages on your TMC managed TKG clusters.

The TKG 1.4 Tanzu Packages can also be used on vSphere with Tanzu, also known as Tanzu Kubernetes Grid Service (TKGS). Nevertheless, as of writing this blog post, there is the limitation that the observability packages have not been validated on vSphere with Tanzu yet.


So what are Tanzu Packages really, and what are they built on. First of all, Tanzu Packages are based on the open-source project CARVEL. Carvel is a set of composable and single-purpose tools with the goal of easing the application management on Kubernetes. And with management, I mean the entire life-cycle starting with building, templating, packaging, deploying, and day2. Here is an excellent session (only 26 minutes) from VMware’s Helen George and João Pereira at KubeCon Europe 2021 about Carvel:

Let’s have a closer look at Tanzu CLI and how it uses Carvel to deploy and manage Tanzu Packages.

Tanzu CLI

The Tanzu CLI provides an easy way to manage our TKG clusters and Tanzu Packages. It hides a lot of the complexity and creates all of the required Kubernetes resources for you. We will look at the workflow from a Tanzu CLI consumer perspective.

But before we start, please download and install Tanzu CLI, kubectl, and the Carvel tools described here. You can also configure Tanzu CLI auto-completion for your shell (bash, zsh):

➜  ~ tanzu completion --help

Output shell completion code for the specified shell [bash zsh].

The shell completion code must be evaluated to provide completion. See Examples
for how to perform this for your given shell.

Note for bash users: make sure the bash-completions package has been installed.
Note for zsh users: zsh >= 5.2 is required for command completion.

  tanzu completion [command]


# Bash instructions:

  ## Load only for current session:
  source <(tanzu completion bash)

  ## Load for all new sessions:
  tanzu completion bash >  $HOME/.tanzu/
  printf "\n# Tanzu shell completion\nsource '$HOME/.tanzu/'\n" >> $HOME/.bash_profile

# Zsh instructions:

  ## Load only for current session:
  source <(tanzu completion zsh)

  ## Load for all new sessions:
  echo "autoload -U compinit; compinit" >> ~/.zshrc
  tanzu completion zsh > "${fpath[1]}/_tanzu"

Tanzu Packages

For this scenario, I will use a Tanzu Kubernetes Cluster (TKC), which I’ve easily and fast deployed in my Workload Management enabled vSphere with Tanzu environment. The process for Tanzu Kubernetes Grid Multi-Cloud (TKGM) is almost the same. The only difference is that the kapp-controller is already installed on a TKGM 1.4 based cluster. The first thing we have to do is install the kapp-controller, but what is it?


The kapp-controller is a package manager for Kubernetes, and it is a crucial component of Carvel and Tanzu Packages. It provides declarative APIs for the continuous delivery of applications and packages. Additionally, it gives Developers the flexibility to choose from various supported sources (e.g., Git, Helm, imgpkg) and templating tools (e.g., ytt, Helm). Applications are defined as part of an App CustomResourceDefinition (CRD) and deployed via kapp. Kapp-controller comes with multiple CRDs, and we will look at the most important ones during the process.

kapp-controller = declarative APIs, package management, and reconciliation for your applications

The App CRD defines a set of Kubernetes resources and breaks down the application specification into three steps.

  • 1. Fetch – From which source do you want to fetch your image and configuration (Git, Helm, imgpkg …).
  • 2. Template: Which tool do you want to use for templating (ytt, Helm, …).
  • 3. Deploy: Kapp is currently the only tool that is supported for deployment. However, there is the possibility that other tools will be added in the future.
kind: App
  name: simple-app
  namespace: default
  serviceAccountName: default-ns-sa
  - git:
      ref: origin/develop
      subPath: config-step-2-template
  - ytt: {}
  - kapp: {}

After applying an application via the App CR (Custom Resource), the kapp-controller will continuously reconcile it with your Kubernetes cluster.

To install the kapp-controller onto our TKC, we can simply use the manifest from here and apply it to our cluster.

➜  ~ k apply -f kapp-controller.yaml
namespace/tkg-system created
namespace/tanzu-package-repo-global created created
service/packaging-api created created created created created created
configmap/kapp-controller-config created
deployment.apps/kapp-controller created
serviceaccount/kapp-controller-sa created created created created created

You should see the kapp-controller pod coming up under the tkg-system namespace. If not, check if your Pod Security Policies are configured ok.

➜  ~ k get pods -n tkg-system
NAME                               READY   STATUS    RESTARTS   AGE
kapp-controller-5d8f7d9477-nk8fc   1/1     Running   0          66s

Now that we have the kapp-controller running, we can add the Tanzu Package Repository to our TKC. But wait, what is a Package Repository?

Package Repository

A Package Repository is a collection of Packages that can be provided and maintained by the Software Producer. In our case, this is where we find all the Tanzu Packages (Contour, Prometheus, Fluent Bit, etc…) that we might want to deploy onto our TKC. The PackageRepository CRD is created by the Software Consumer to tell the kapp-controller where the Package Repository can be found and make the Packages available on a Kubernetes cluster. It references an Image Bundle “imgpkgBundle”, which I cover in the next section.

Package Repository = collection of Packages a user can install from

kind: PackageRepository
  name: simple-package-repository
  namespace: default
      image: k8slt/corp-com-pkg-repo:1.0.0


With the Carvel tool imgpkg, we can efficiently distribute and relocate multiple Packages via a single immutable OCI (Open Container Initiative) artifact. It combines configuration files and dependent OCI images of your applications into a Bundle. A Bundle is essentially an OCI image that can be used with every OCI compliant image registry. If you want to learn how to create a Bundle yourself, look at this basic workflow.

Bundle = single OCI artifact that combines configuration files and dependent OCI images of multiple applications

You probably guessed it already, the Tanzu Package Repositories are Bundles as well, and we can use the imgpkg copy command to copy them for, e.g., air-gapped scenarios.

We can now add the Tanzu Package Repository to our TKG cluster via Tanzu CLI. We will use the “tanzu-package-repo-global” namespace, which was created via the kapp-controller manifest. Kapp-controller is configured to share all packages within the “tanzu-package-repo-global” namespace cluster-wide; see Namespacing section of the kapp-controller documentation for more details. Please note: If you choose a different namespace, the Packages will only be visible and deployable in that particular namespace.

➜  ~ tanzu package repository add repo --url -n tanzu-package-repo-global
- Adding package repository 'repo'...
 Added package repository 'repo'

➜  ~ tanzu package repository list -n tanzu-package-repo-global
- Retrieving repositories...
  NAME  REPOSITORY                                                      STATUS       DETAILS
  repo  Reconciling

➜  ~ k get packagerepositories -n tanzu-package-repo-global
repo   5m46s   Reconcile succeeded

We have successfully added the Tanzu Packages Repository to our TKG cluster. Now we can check what Packages are available for installation. But first, let’s cover what a Package is?


A Package is a combination of an OCI Image and configuration metadata. The Package CRD wraps the App CRD and adds attributes such as “version” and “refName” to it. It provides an easy way to define your application and share it as a Package that can be reused in multiple environments.

Package = OCI Image plus configuration metadata of an application

kind: Package
  version: 1.0.0
  releaseNotes: |
        Initial release of the simple app package
      - imgpkgBundle:
      - ytt:
          - config/
      - kbld:
          - '-'
          - .imgpkg/images.yml
      - kapp: {}

Now let’s check if we have available Packages via the newly added repository. We will again use the Tanzu CLI to list all available Packages.

➜  ~ tanzu package available list
\ Retrieving available packages...
  NAME                           DISPLAY-NAME  SHORT-DESCRIPTION  cert-manager  Certificate management       Contour       An ingress controller  external-dns  This package provides DNS synchronization functionality.    fluent-bit    Fluent Bit is a fast Log Processor and Forwarder       grafana       Visualization and analytics software        Harbor        OCI Registry    multus-cni    This package provides the ability for enabling attaching multiple network interfaces to pods in Kubernetes    prometheus    A time series database for your metrics

As you can see, we don’t have to specify a namespace as we used the “tanzu-package-repo-global” namespace for our repository, and all Packages are available cluster-wide. Let’s identify a package that we want to install first. In this case, I am going to look at the cert-manager package. We can get the available package version and additional details with the following command.

➜  ~ tanzu package available list
\ Retrieving package versions for
  NAME                           VERSION               RELEASED-AT  1.1.0+vmware.1-tkg.2  2020-11-24T18:00:00Z

➜  ~ tanzu package available get
| Retrieving package details for
DISPLAY-NAME:         cert-manager
SHORT-DESCRIPTION:    Certificate management
LONG-DESCRIPTION:     Provides certificate management provisioning within the cluster
MAINTAINERS:          [{Nicholas Seemiller}]
SUPPORT:              Support provided by VMware for deployment on TKG 1.4+ clusters. Best-effort support for deployment on any conformant Kubernetes cluster. Contact support by opening a support request via VMware Cloud Services or
CATEGORY:             [certificate management

Finally, we can install the Package via Tanzu CLI. I will create a “packages” namespace for all the Custom Resources created during the process as we don’t want to have anything in the “default” namespace.

➜  ~ k create ns packages
namespace/packages created

➜  ~ tanzu package install cert-manager --package-name --version 1.1.0+vmware.1-tkg.2 -n packages
- Installing package ''
\ Getting namespace 'packages'
- Getting package metadata for ''
\ Creating service account 'cert-manager-packages-sa'
- Creating cluster admin role 'cert-manager-packages-cluster-role'
\ Creating cluster role binding 'cert-manager-packages-cluster-rolebinding'
| Creating package resource
/ Package install status: Reconciling

 Added installed package 'cert-manager' in namespace 'packages'

➜  ~ tanzu package installed list -n packages
| Retrieving installed packages...
  NAME          PACKAGE-NAME                   PACKAGE-VERSION       STATUS
  cert-manager  1.1.0+vmware.1-tkg.2  Reconcile succeeded

➜  ~ k get packageinstalls,app -n packages
NAME                                               PACKAGE NAME                    PACKAGE VERSION        DESCRIPTION           AGE   1.1.0+vmware.1-tkg.2   Reconcile succeeded   67s

NAME                                DESCRIPTION           SINCE-DEPLOY   AGE   Reconcile succeeded   63s            67s

➜  ~ k get ns
NAME                           STATUS   AGE
cert-manager                   Active   57s
default                        Active   13d
kube-node-lease                Active   13d
kube-public                    Active   13d
kube-system                    Active   13d
packages                       Active   94s
tanzu-package-repo-global      Active   12d
tkg-system                     Active   12d
vmware-system-auth             Active   13d
vmware-system-cloud-provider   Active   13d
vmware-system-csi              Active   13d

➜  ~ k get pods -n cert-manager
NAME                                       READY   STATUS    RESTARTS   AGE
cert-manager-84856fcf54-g8p8h              1/1     Running   0          60s
cert-manager-cainjector-5c8f5b649b-qzq82   1/1     Running   0          60s
cert-manager-webhook-6986456c8-9vd7n       1/1     Running   0          60s

We successfully installed the cert-manager package onto our cluster. We can see it created the App and PackageInstall custom resources in our “packages” namespace and the actual Pods into a different “cert-manager” namespace. But what is the PackageInstall custom resource?


The PackageInstall CRD is the actual implementation of a Package onto a Kubernetes cluster. The idea is that the Package & Package CR is created by the Software Producer, and the PackageInstall CR is implemented by the Software Consumer.

PackageInstall = represents the deployment of a Package on a Kubernetes cluster

kind: PackageInstall
  name: pkg-demo
  namespace: default
  serviceAccountName: default-ns-sa
      constraints: 1.0.0


You might think, wait, isn’t there a solution that does the same thing called Helm? Helm has a similar scope, but Carvel is complementary and adds additional functionality. Helm can still be used as a source and for templating. However, when it comes to actual application deployment, Carvel is using kapp. The significant benefit is that Carvel and, more precisely, kapp-controller continuously reconcile and come with declarative APIs. The Software Producer can leverage all the functionality provided by the Carvel tools and the described way via Packages, Package Repositories, and Bundle OCI Images to provide and distribute Software Packages.

Tanzu Packages are much easier to deploy and manage in comparison to the Tanzu Extensions. A lot of the yaml file handling disappeared as this is done automatically via the Tanzu CLI. For the Software Consumer or Cluster Admin, Tanzu CLI is the easy way to deploy and manage all of the supported Tanzu Packages on their TKG clusters.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: