This topic tells you how to manage Custom Stacks with your Tanzu Build Service (commonly known as TBS).

A CustomStack is a resource that allows users to create a customized ClusterStack from Ubuntu 22.04 (Jammy Jellyfish) and UBI7/UBI8 non-minimal-based OCI images.

Note: CustomStacks created with UBI7/UBI8 images do not currently support adding packages, mixins, or caCerts. Currently, only the Java Tanzu Buildpacks support CustomStacks that use UBI images.

Note: Private registries which require a custom CA certificate are not currently supported as publishing destinations for CustomStack images.

CustomStacks can be used to:

  • Convert a pre-existing base image that you’d like to use with Tanzu Build Service into a ClusterStack resource.
  • Add required stack metadata to base images.
  • Add CA certificates to build and/or run image.
  • Add packages and mixin labels to build and/or run image.
  • Set CNB user and group IDs.

Creating a CustomStack

Note: CustomStacks make changes to a base image that require root permissions such as adding OS packages, setting the user or group id, or adding CA certificates to the OS trusted store. This means that CustomStack pods must run as privileged. However, TBS does NOT require any privileged containers to install or run – only when using CustomStacks is a privileged container ever created.

A CustomStack is created by running kubectl apply with a resource configuration file. The following defines the relevant fields of the CustomStack resource spec in more detail:

  • source: The location of base images used for building the stack. See more info in Source Configuration.
  • destination: The location to publish built images and optional ClusterStack. See more info in Destination Configuration.
  • caCerts: References to config maps of CA certificates to add to one or both of the stack images.
  • packages: List of packages to install on one or both of the stack images. A list of all available packages can be found in Software Packages in “jammy” on the ubuntu packages web page.
  • mixins: List of mixin labels to add to one or both of the stack images. Information on the mixins concept can be found in Stack on the Buildpacks.io website.
  • service-account-name: Name of service account with secret containing credentials to push to registry.
  • user: User and group ID of the CNB user.
    • Not required if the user is already present in metadata.
    • If the user and/or group ID do not exist on the image, they are created.

Source configuration

The source field describes the base images for the CustomStack. It can be configured in exactly one of the following ways:

  • Registry Images

    source:
    registryImages:
      build:
        image: <build-base-image>
      run:
        image: <run-base-image>
    
    • build-base-image: The fully qualified reference of the build base image.
    • run-base-image: The fully qualified reference of the run base image.
  • Stack

    stack:
    name: <cluster-stack-name>
    kind: ClusterStack
    
    • cluster-stack-name: Name of ClusterStack to base CustomStack images on.

Destination Configuration

The destination field describes where the built images are published and whether a ClusterStack should be created.

destination:
  build:
    tag: <output-build-image-tag>
  run:
    tag: <output-run-image-tag>
  stack: # Optional
    name: <output-cluster-stack-name>
    kind: ClusterStack
  • output-build-image-tag: The registry location where the build image is created.
  • output-run-image-tag: The registry location where the run image is created.
  • output-cluster-stack-name: Name of ClusterStack to create with CustomStack images.

Example CustomStack from registry images

apiVersion: v1
kind: ConfigMap
metadata:
  name: build-ca-certs
data:
  cert-1: |
    -----BEGIN CERTIFICATE-----
    ...
    -----END CERTIFICATE-----
  cert-2: |
    -----BEGIN CERTIFICATE-----
    ...
    -----END CERTIFICATE-----
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: run-ca-certs
data:
  cert-3: |
    -----BEGIN CERTIFICATE-----
    ...
    -----END CERTIFICATE-----
---
apiVersion: stacks.stacks-operator.tanzu.vmware.com/v1alpha1
kind: CustomStack
metadata:
  name: stack-sample
spec:
  source:
    registryImages:
      build:
        image: paketobuildpacks/build@sha256:ae88191cc5bfd0dcd2938954f20d5df5060a562af8e3d65a92a815612054537c
      run:
        image: paketobuildpacks/run@sha256:48f67dcb3f2b27403de80193e34abd3172b3fbdfdd87e452721aba90ea68fc66
  destination:
    build:
      tag: my.registry.io/final-build-image
    run:
      tag: my.registry.io/final-run-image
    stack: # Optional
      name: stack-sample-cluster-stack
      kind: ClusterStack
  caCerts: # Optional
    buildRef: # Optional
      name: build-ca-certs
    runRef: # Optional
      name: run-ca-certs
  packages: # Optional
    - name: cowsay
    - name: cowsay-off
    - name: fortune
      phase: build
    - name: rolldice
      phase: run
  mixins: # Optional
    - name: set=build-utils
      phase: build
    - name: set=run-utils
      phase: run
    - name: set=shared-utils
  serviceAccountName: default
  user: # Optional
    userID: 1000
    groupID: 1000

Example CustomStack from ClusterStack

apiVersion: v1
kind: ConfigMap
metadata:
  name: build-ca-certs
data:
  cert-1: |
    -----BEGIN CERTIFICATE-----
    ...
    -----END CERTIFICATE-----
  cert-2: |
    -----BEGIN CERTIFICATE-----
    ...
    -----END CERTIFICATE-----
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: run-ca-certs
data:
  cert-3: |
    -----BEGIN CERTIFICATE-----
    ...
    -----END CERTIFICATE-----
---
apiVersion: stacks.stacks-operator.tanzu.vmware.com/v1alpha1
kind: CustomStack
metadata:
  name: stack-sample
spec:
  source:
    stack:
      name: stack-sample-cluster-stack
      kind: ClusterStack
  destination:
    build:
      tag: my.registry.io/final-build-image
    run:
      tag: my.registry.io/final-run-image
    stack: # Optional
      name: final-stack-sample-cluster-stack
      kind: ClusterStack
  caCerts: # Optional
    buildRef: # Optional
      name: build-ca-certs
    runRef: # Optional
      name: run-ca-certs
  packages: # Optional
    - name: cowsay
    - name: cowsay-off
    - name: fortune
      phase: build # Optional
    - name: rolldice
      phase: run # Optional
  mixins: # Optional
    - name: set=build-utils
      phase: build # Optional
    - name: set=run-utils
      phase: run # Optional
    - name: set=shared-utils
  serviceAccountName: default
  user: # Optional
    userID: 1000 # Optional
    groupID: 1000 # Optional

Debugging CustomStacks

When a CustomStack is created, a pod is created in the same namespace which modifies the base image and pushes the resulting stack image to the registry. The pod is named stack-pod-<customstack-name>-<number>

Where:

  • customstack-name is the name of your CustomStack.
  • number is the revision of your CustomStack. This is incremented by one each time a new spec is applied.

The ten latest pods are kept around for debugging purposes. To debug a failing CustomStack, check the logs of the corresponding pod: kubectl logs <pod-name> -c <create-build-image/create-run-image>

Where:

  • pod-name is the name of the pod.
  • create-build-image/create-run-image is the container whose logs you want to see.
    • create-build-image for logs related to creating the build image.
    • create-run-image for logs related to create the run image.
check-circle-line exclamation-circle-line close-line
Scroll to top icon