This topic explains how to deploy Harbor into a shared services cluster in Tanzu Kubernetes Grid. The procedures below apply to vSphere, Amazon EC2, and Azure deployments.

Harbor

Harbor is an open-source, trusted, cloud-native container registry that stores, signs, and scans content. Harbor extends the open-source Docker distribution by adding the functionalities usually required by users such as security and identity control and management.

Tanzu Kubernetes Grid includes signed binaries for Harbor, which you can deploy into a shared services cluster to provide container registry services for other Tanzu Kubernetes (workload) clusters. You deploy Harbor as a shared service. In this way, Harbor is available to all of the workload clusters in a given Tanzu Kubernetes Grid instance. To implement Harbor as a shared service, you deploy it into a special cluster that is reserved for running shared services in a Tanzu Kubernetes Grid instance.

You can use the Harbor shared service as a private registry for images that you want to make available to all of the workload clusters that you deploy from a given management cluster. An advantage to using the Harbor shared service is that it is managed by Kubernetes, so it provides greater reliability than a stand-alone registry. Also, the Harbor implementation that Tanzu Kubernetes Grid provides as a shared service has been tested for use with Tanzu Kubernetes Grid and is fully supported.

Using the Harbor Shared Service in Internet-Restricted Environments

Another use-case for deploying Harbor as a shared service is for Tanzu Kubernetes Grid deployments in Internet-restricted environments. For more information, see Using the Harbor Shared Service in Internet-Restricted Environments.

Harbor Registry and ExternalDNS

VMware recommends installing ExternalDNS alongside the Harbor registry on infrastructures with load balancing (AWS, Azure, and vSphere with NSX Advanced Load Balancer), especially in production or other environments in which Harbor availability is important.

If the IP address to the shared services ingress load balancer changes, ExternalDNS automatically picks up the change and re-maps the new address to the Harbor hostname. This precludes the need to manually re-map the address as described in Connect to the Harbor User Interface.

Prerequisites

  • You have installed the Tanzu CLI, kubectl, and the Carvel tools. For instructions, see Install the Tanzu CLI and Other Tools.
  • You have deployed a management cluster on vSphere, Amazon EC2, or Azure, in either an Internet-connected or Internet-restricted environment. If you are using Tanzu Kubernetes Grid in an Internet-restricted environment, you performed the procedure in Prepare an Internet-Restricted Environment before you deployed the management cluster.
  • You have installed yq v4.5 or later.

Prepare a Shared Services Cluster for Harbor Deployment

Each Tanzu Kubernetes Grid instance can have only one shared services cluster. You must deploy Harbor to a cluster that will be used only for shared services.

To prepare a shared services cluster for Harbor:

  1. Create a shared services cluster, if it is not already created, by following the procedure in Create a Shared Services Cluster.

  2. Set the context of kubectl to the shared services cluster. For example:

    kubectl config use-context tkg-services-admin@tkg-services
    
  3. Install the Cert Manager and Contour packages in the cluster. For instructions, see Implementing Ingress Control with Contour.

  4. (Optional) Install the ExternalDNS package in the cluster. For instructions, see Implementing Service Discovery with ExternalDNS.

  5. Proceed to Deploy Harbor into the Shared Services Cluster below.

Deploy Harbor into the Shared Services Cluster

After you have deployed a shared services cluster and prepared it for Harbor, you can deploy Harbor:

  1. Confirm that the Harbor package is available in the cluster:

    tanzu package available list -A
    
  2. Retrieve the version of the available package:

    tanzu package available list harbor.tanzu.vmware.com -A
    
  3. Create a configuration file named harbor-data-values.yaml. This file configures the Harbor package.

    1. Retrieve the template for the Harbor package as follows:

      image_url=$(kubectl -n tanzu-package-repo-global get packages harbor.tanzu.vmware.com.PACKAGE-VERSION -o jsonpath='{.spec.template.spec.fetch[0].imgpkgBundle.image}')
      imgpkg pull -b $image_url -o /tmp/harbor-package-PACKAGE-VERSION
      cp /tmp/harbor-package-PACKAGE-VERSION/config/values.yaml harbor-data-values.yaml
      

      Where PACKAGE-VERSION is the version of the Harbor package that you want to install. For example:

      image_url=$(kubectl -n tanzu-package-repo-global get packages harbor.tanzu.vmware.com.2.2.3+vmware.1-tkg.1 -o jsonpath='{.spec.template.spec.fetch[0].imgpkgBundle.image}')
      imgpkg pull -b $image_url -o /tmp/harbor-package-2.2.3
      cp /tmp/harbor-package-2.2.3/config/values.yaml harbor-data-values.yaml
      

      The resulting harbor-data-values.yaml file for v2.2.3 contains the following template:

      #@data/values
      #@overlay/match-child-defaults missing_ok=True
      
      ---
      #! The namespace to install Harbor
      namespace: tanzu-system-registry
      
      #! The FQDN for accessing Harbor admin UI and Registry service.
      hostname: harbor.yourdomain.com
      #! The network port of the Envoy service in Contour or other Ingress Controller.
      port:
      https: 443
      
      #! The log level of core, exporter, jobservice, registry. Its value is debug, info, warning, error or fatal.
      logLevel: info
      
      #! [Optional] The certificate for the ingress if you want to use your own TLS certificate.
      #! We will issue the certificate by cert-manager when it's empty.
      tlsCertificate:
      #! [Required] the certificate
      tls.crt:
      #! [Required] the private key
      tls.key:
      #! [Optional] the certificate of CA, this enables the download
      #! link on portal to download the certificate of CA
      ca.crt:
      
      #! Use contour http proxy instead of the ingress when it's true
      enableContourHttpProxy: true
      
      #! [Required] The initial password of Harbor admin.
      harborAdminPassword:
      
      #! [Required] The secret key used for encryption. Must be a string of 16 chars.
      secretKey:
      
      database:
      #! [Required] The initial password of the postgres database.
      password:
      
      core:
      replicas: 1
      #! [Required] Secret is used when core server communicates with other components.
      secret:
      #! [Required] The XSRF key. Must be a string of 32 chars.
      xsrfKey:
      jobservice:
      replicas: 1
      #! [Required] Secret is used when job service communicates with other components.
      secret:
      registry:
      replicas: 1
      #! [Required] Secret is used to secure the upload state from client
      #! and registry storage backend.
      #! See: https://github.com/docker/distribution/blob/master/docs/configuration.md#http
      secret:
      notary:
      #! Whether to install Notary
      enabled: true
      trivy:
      #! enabled the flag to enable Trivy scanner
      enabled: true
      replicas: 1
      #! gitHubToken the GitHub access token to download Trivy DB
      gitHubToken: ""
      #! skipUpdate the flag to disable Trivy DB downloads from GitHub
      #
      #! You might want to set the value of this flag to `true` in test or CI/CD environments to avoid GitHub rate limiting issues.
      #! If the value is set to `true` you have to manually download the `trivy.db` file and mount it in the
      #! `/home/scanner/.cache/trivy/db/trivy.db` path.
      skipUpdate: false
      
      #! The persistence is always enabled and a default StorageClass
      #! is needed in the k8s cluster to provision volumes dynamically.
      #! Specify another StorageClass in the "storageClass" or set "existingClaim"
      #! if you have already existing persistent volumes to use
      #
      #! For storing images and charts, you can also use "azure", "gcs", "s3",
      #! "swift" or "oss". Set it in the "imageChartStorage" section
      persistence:
      persistentVolumeClaim:
        registry:
          #! Use the existing PVC which must be created manually before bound,
          #! and specify the "subPath" if the PVC is shared with other components
          existingClaim: ""
          #! Specify the "storageClass" used to provision the volume. Or the default
          #! StorageClass will be used(the default).
          #! Set it to "-" to disable dynamic provisioning
          storageClass: ""
          subPath: ""
          accessMode: ReadWriteOnce
          size: 10Gi
        jobservice:
          existingClaim: ""
          storageClass: ""
          subPath: ""
          accessMode: ReadWriteOnce
          size: 1Gi
        database:
          existingClaim: ""
          storageClass: ""
          subPath: ""
          accessMode: ReadWriteOnce
          size: 1Gi
        redis:
          existingClaim: ""
          storageClass: ""
          subPath: ""
          accessMode: ReadWriteOnce
          size: 1Gi
        trivy:
          existingClaim: ""
          storageClass: ""
          subPath: ""
          accessMode: ReadWriteOnce
          size: 5Gi
      #! Define which storage backend is used for registry and chartmuseum to store
      #! images and charts. Refer to
      #! https://github.com/docker/distribution/blob/master/docs/configuration.md#storage
      #! for the detail.
      imageChartStorage:
        #! Specify whether to disable `redirect` for images and chart storage, for
        #! backends which not supported it (such as using minio for `s3` storage type), please disable
        #! it. To disable redirects, simply set `disableredirect` to `true` instead.
        #! Refer to
        #! https://github.com/docker/distribution/blob/master/docs/configuration.md#redirect
        #! for the detail.
        disableredirect: false
        #! Specify the "caBundleSecretName" if the storage service uses a self-signed certificate.
        #! The secret must contain keys named "ca.crt" which will be injected into the trust store
        #! of registry's and chartmuseum's containers.
        #! caBundleSecretName:
      
        #! Specify the type of storage: "filesystem", "azure", "gcs", "s3", "swift",
        #! "oss" and fill the information needed in the corresponding section. The type
        #! must be "filesystem" if you want to use persistent volumes for registry
        #! and chartmuseum
        type: filesystem
        filesystem:
          rootdirectory: /storage
          #maxthreads: 100
        azure:
          accountname: accountname #! required
          accountkey: base64encodedaccountkey #! required
          container: containername #! required
          realm: core.windows.net #! optional
        gcs:
          bucket: bucketname #! required
          #! The base64 encoded json file which contains the key
          encodedkey: base64-encoded-json-key-file #! optional
          rootdirectory: null #! optional
          chunksize: 5242880 #! optional
        s3:
          region: us-west-1 #! required
          bucket: bucketname #! required
          accesskey: null #! eg, awsaccesskey
          secretkey: null #! eg, awssecretkey
          regionendpoint: null #! optional, eg, http://myobjects.local
          encrypt: false #! optional
          keyid: null #! eg, mykeyid
          secure: true #! optional
          v4auth: true #! optional
          chunksize: null #! optional
          rootdirectory: null #! optional
          storageclass: STANDARD #! optional
        swift:
          authurl: https://storage.myprovider.com/v3/auth
          username: username
          password: password
          container: containername
          region: null #! eg, fr
          tenant: null #! eg, tenantname
          tenantid: null #! eg, tenantid
          domain: null #! eg, domainname
          domainid: null #! eg, domainid
          trustid: null #! eg, trustid
          insecureskipverify: null #! bool eg, false
          chunksize: null #! eg, 5M
          prefix: null #! eg
          secretkey: null #! eg, secretkey
          accesskey: null #! eg, accesskey
          authversion: null #! eg, 3
          endpointtype: null #! eg, public
          tempurlcontainerkey: null #! eg, false
          tempurlmethods: null #! eg
        oss:
          accesskeyid: accesskeyid
          accesskeysecret: accesskeysecret
          region: regionname
          bucket: bucketname
          endpoint: null #! eg, endpoint
          internal: null #! eg, false
          encrypt: null #! eg, false
          secure: null #! eg, true
          chunksize: null #! eg, 10M
          rootdirectory: null #! eg, rootdirectory
      
      #! The http/https network proxy for core, exporter, jobservice, trivy
      proxy:
      httpProxy:
      httpsProxy:
      noProxy: 127.0.0.1,localhost,.local,.internal
      
      #! The PSP names used by Harbor pods. The names are separated by ','. 'null' means all PSP can be used.
      pspNames: null
      
      #! The metrics used by core, registry and exporter
      metrics:
      enabled: false
      core:
        path: /metrics
        port: 8001
      registry:
        path: /metrics
        port: 8001
      exporter:
        path: /metrics
        port: 8001
      

      After you retrieve the template, do not remove the /tmp/harbor-package-PACKAGE-VERSION directory if you intend to generate random passwords and secrets for Harbor. See the step below.

    2. Set the mandatory passwords and secrets in the harbor-data-values.yaml file by doing one of the following:

      • To automatically generate random passwords and secrets, run:

        # Skip this command if the /tmp/harbor-package-PACKAGE-VERSION directory is already present on your machine.
        image_url=$(kubectl -n tanzu-package-repo-global get packages harbor.tanzu.vmware.com.PACKAGE-VERSION -o jsonpath='{.spec.template.spec.fetch[0].imgpkgBundle.image}')
        # Skip this command if the /tmp/harbor-package-PACKAGE-VERSION directory is already present on your machine.
        imgpkg pull -b $image_url -o /tmp/harbor-package-PACKAGE-VERSION
        bash /tmp/harbor-package-PACKAGE-VERSION/config/scripts/generate-passwords.sh harbor-data-values.yaml
        

        Where PACKAGE-VERSION is the version of the Harbor package that you want to install.

        For example, for the Harbor package v2.2.3, run:

        image_url=$(kubectl -n tanzu-package-repo-global get packages harbor.tanzu.vmware.com.2.2.3+vmware.1-tkg.1 -o jsonpath='{.spec.template.spec.fetch[0].imgpkgBundle.image}')
        imgpkg pull -b $image_url -o /tmp/harbor-package-2.2.3
        bash /tmp/harbor-package-2.2.3/config/scripts/generate-passwords.sh harbor-data-values.yaml
        
      • To set your own passwords and secrets, update the following entries in the harbor-data-values.yaml file:

        • harborAdminPassword
        • secretKey
        • database.password
        • core.secret
        • core.xsrfKey
        • jobservice.secret
        • registry.secret
    3. Specify other settings in the harbor-data-values.yaml file.

      • Set the hostname setting to the hostname you want to use to access Harbor. For example, harbor.yourdomain.com.
      • To use your own certificates, update the tls.crt, tls.key, and ca.crt settings with the contents of your certificate, key, and CA certificate. The certificate can be signed by a trusted authority or be self-signed. If you leave these blank, Tanzu Kubernetes Grid automatically generates a self-signed certificate.
      • If you used the generate-passwords.sh script, optionally update the harborAdminPassword with something that is easier to remember.
      • Optionally, update the persistence settings to specify how Harbor stores data.

        If you need to store a large quantity of container images in Harbor, set persistence.persistentVolumeClaim.registry.size to a larger number.

        If you do not update the storageClass under persistence settings, Harbor uses the shared services cluster's default storageClass. If the default storageClass or a storageClass that you specify in harbor-data-values.yaml supports the accessMode ReadWriteMany, you must update the persistence.persistentVolumeClaim accessMode settings for registry, jobservice, database, redis, and trivy from ReadWriteOnce to ReadWriteMany. vSphere 7 with VMware vSAN 7 supports accessMode: ReadWriteMany but vSphere 6.7u3 does not. If you are using vSphere 7 without vSAN or you are using vSphere 6.7u3, use the default value ReadWriteOnce.

      To see more information about the values in the harbor-data-values.yaml file, run the below command against your target cluster:

      tanzu package available get harbor.tanzu.vmware.com/AVAILABLE-VERSION --values-schema
      

      Where AVAILABLE-VERSION is the version of the Harbor package. The --values-schema flag retrieves the valuesSchema section from the Package API resource for the Harbor package. You can set the output format, --output, for the values schema to yaml, json, or table. For more information, see Packages in CLI Reference for User-Managed Packages.

      For example:

      tanzu package available get harbor.tanzu.vmware.com/2.2.3+vmware.1-tkg.1 --values-schema
      
    4. Remove all comments in the harbor-data-values.yaml file:

      yq -i eval '... comments=""' harbor-data-values.yaml
      
  4. Install the package:

    • If the target namespace exists in the cluster, run:

      tanzu package install harbor \
      --package-name harbor.tanzu.vmware.com \
      --version AVAILABLE-PACKAGE-VERSION \
      --values-file harbor-data-values.yaml \
      --namespace TARGET-NAMESPACE
      

      Where:

      • TARGET-NAMESPACE is the namespace in which you want to install the Harbor package and deploy the Harbor package app, which is managed by kapp-controller. For example, my-packages. If this flag is not specified, the Tanzu CLI installs the package and its resources in the default namespace. The Harbor pods and any other resources associated with Harbor are created in the tanzu-system-registry namespace; do not install the Harbor package into this namespace.
      • AVAILABLE-PACKAGE-VERSION is the version that you retrieved above.

      For example:

      tanzu package install harbor \
      --package-name harbor.tanzu.vmware.com \
      --version 2.2.3+vmware.1-tkg.1 \
      --values-file harbor-data-values.yaml \
      --namespace my-packages
      
    • If the target namespace does not exist in the cluster, run:

      tanzu package install harbor \
      --package-name harbor.tanzu.vmware.com \
      --version AVAILABLE-PACKAGE-VERSION \
      --values-file harbor-data-values.yaml \
      --namespace TARGET-NAMESPACE
      --create-namespace
      

      Where:

      • TARGET-NAMESPACE is the namespace in which you want to install the Harbor package and deploy the Harbor package app, which is managed by kapp-controller. For example, my-packages. If this flag is not specified, the Tanzu CLI installs the package and its resources in the default namespace. The Harbor pods and any other resources associated with Harbor are created in the tanzu-system-registry namespace; do not install the Harbor package into this namespace.
      • AVAILABLE-PACKAGE-VERSION is the version that you retrieved above.

      For example:

      tanzu package install harbor \
      --package-name harbor.tanzu.vmware.com \
      --version 2.2.3+vmware.1-tkg.1 \
      --values-file harbor-data-values.yaml \
      --namespace my-packages
      --create-namespace
      

    Alternatively, you can create the namespace before installing the package by running the kubectl create namespace TARGET-NAMESPACE command.

  5. Confirm that the harbor package has been installed:

    tanzu package installed list -A
    

    For example:

    tanzu package installed list -A
    - Retrieving installed packages...
      NAME            PACKAGE-NAME                     PACKAGE-VERSION                   STATUS               NAMESPACE
      cert-manager    cert-manager.tanzu.vmware.com    1.1.0+vmware.1-tkg.2              Reconcile succeeded  my-packages
      contour         contour.tanzu.vmware.com         1.17.1+vmware.1-tkg.1             Reconcile succeeded  my-packages
      harbor          harbor.tanzu.vmware.com          2.2.3+vmware.1-tkg.1              Reconcile succeeded  my-packages
      antrea          antrea.tanzu.vmware.com                                            Reconcile succeeded  tkg-system
      [...]
    

    To see more details about the package, you can also run:

    tanzu package installed get harbor --namespace PACKAGE-NAMESPACE
    

    Where PACKAGE-NAMESPACE is the namespace in which the harbor package is installed.

    For example:

    tanzu package installed get harbor --namespace my-packages
    \ Retrieving installation details for harbor...
    NAME:                    harbor
    PACKAGE-NAME:            harbor.tanzu.vmware.com
    PACKAGE-VERSION:         2.2.3+vmware.1-tkg.1
    STATUS:                  Reconcile succeeded
    CONDITIONS:              [{ReconcileSucceeded True  }]
    USEFUL-ERROR-MESSAGE:
    
  6. Confirm that the harbor app has been successfully reconciled in your PACKAGE-NAMESPACE:

    kubectl get apps -A
    

    For example:

    NAMESPACE     NAME             DESCRIPTION           SINCE-DEPLOY   AGE
    my-packages   cert-manager     Reconcile succeeded   78s            3h5m
    my-packages   contour          Reconcile succeeded   57s            6m3s
    my-packages   harbor           Reconcile succeeded   40s            24m
    tkg-system    antrea           Reconcile succeeded   45s            3h18m
    [...]
    

    If the status is not Reconcile Succeeded, view the full status details of the harbor app. Viewing the full status can help you troubleshoot the problem.

    kubectl get app harbor --namespace PACKAGE-NAMESPACE -o yaml
    

    Where PACKAGE-NAMESPACE is the namespace in which you installed the package. If troubleshooting does not help you solve the problem, you must uninstall the package before installing it again:

    tanzu package installed delete harbor
    
  7. Confirm that the Harbor services are running by listing all of the pods in the cluster:

    kubectl get pods -A
    

    In the tanzu-system-regisry namespace, you should see the harbor core, database, jobservice, notary, portal, redis, registry, and trivy services running in a pod with names similar to the following:

    NAMESPACE               NAME                                    READY   STATUS    RESTARTS   AGE
    [...]
    tanzu-system-ingress    contour-6b568c9b88-h5s2r                1/1     Running   0          26m
    tanzu-system-ingress    contour-6b568c9b88-mlg2r                1/1     Running   0          26m
    tanzu-system-ingress    envoy-wfqdp                             2/2     Running   0          26m
    tanzu-system-registry   harbor-core-557b58b65c-4kzhn            1/1     Running   0          23m
    tanzu-system-registry   harbor-database-0                       1/1     Running   0          23m
    tanzu-system-registry   harbor-jobservice-847b5c8756-t6kfs      1/1     Running   0          23m
    tanzu-system-registry   harbor-notary-server-6b74b8dd56-d7swb   1/1     Running   2          23m
    tanzu-system-registry   harbor-notary-signer-69d4669884-dglzm   1/1     Running   2          23m
    tanzu-system-registry   harbor-portal-8f677757c-t4cbj           1/1     Running   0          23m
    tanzu-system-registry   harbor-redis-0                          1/1     Running   0          23m
    tanzu-system-registry   harbor-registry-85b96c7777-wsdnj        2/2     Running   0          23m
    tanzu-system-registry   harbor-trivy-0                          1/1     Running   0          23m
    [...]
    
  8. Obtain the Harbor CA certificate from the harbor-tls secret in the tanzu-system-registry namespace:

    kubectl -n tanzu-system-registry get secret harbor-tls -o=jsonpath="{.data.ca\.crt}" | base64 -d
    

    Make a copy of the output.

Connect to the Harbor User Interface

The Harbor UI is exposed via the Envoy service load balancer that is running in the tanzu-system-ingress namespace in the shared services cluster. To allow users to connect to the Harbor UI, you must map the address of the Envoy service load balancer to the hostname of the Harbor service, for example, harbor.yourdomain.com. How you map the address of the Envoy service load balancer to the hostname depends on whether your Tanzu Kubernetes Grid instance is running on vSphere, on Amazon EC2, or on Azure.

  1. Obtain the address of the Envoy service load balancer.

    kubectl get svc envoy -n tanzu-system-ingress -o jsonpath='{.status.loadBalancer.ingress[0]}'
    

    On vSphere without NSX Advanced Load Balancer (ALB), the Envoy service is exposed via NodePort instead of LoadBalancer, so the above output will be empty, and you can use the IP address of any worker node in the shared services cluster instead. On Amazon EC2, it has a FQDN similar to a82ebae93a6fe42cd66d9e145e4fb292-1299077984.us-west-2.elb.amazonaws.com. On vSphere with NSX ALB and Azure, the Envoy service has a Load Balancer IP address similar to 20.54.226.44.

  2. Map the address of the Envoy service load balancer to the hostname of the Harbor service.

    • vSphere: If you deployed Harbor on a shared services cluster that is running on vSphere, you must add an IP to hostname mapping in /etc/hosts or add corresponding A records in your DNS server. For example, if the IP address is 10.93.9.100, add the following to /etc/hosts:

      10.93.9.100 harbor.yourdomain.com notary.harbor.yourdomain.com
      

      On Windows machines, the equivalent to /etc/hosts/ is C:\Windows\System32\Drivers\etc\hosts.

    • Amazon EC2 or Azure: If you deployed Harbor on a shared services cluster that is running on Amazon EC2 or Azure, you must create two DNS CNAME records (on Amazon EC2) or two DNS A records (on Azure) for the Harbor hostnames on a DNS server on the Internet.

      • One record for the Harbor hostname that you configured in harbor-data-values.yaml (for example, harbor.yourdomain.com) that points to the FQDN or IP of the Envoy service load balancer.
      • Another record for the Notary service that is running in Harbor (for example, notary.harbor.yourdomain.com) that points to the FQDN or IP of the Envoy service load balancer.

Users can now connect to the Harbor UI by navigating to https://harbor.yourdomain.com in a Web browser and log in as user admin with the harborAdminPassword that you configured in harbor-data-values.yaml.

Push and Pull Images to and from the Harbor Package

Now that Harbor is set up as a shared service, you can push images to it to make them available for your Tanzu Kubernetes clusters to pull.

  1. If Harbor uses a self-signed certificate, download the Harbor CA certificate from https://harbor.yourdomain.com/api/v2.0/systeminfo/getcert and install it on your local machine, so Docker can trust this CA certificate.

    • On Linux, save the certificate as /etc/docker/certs.d/harbor.yourdomain.com/ca.crt.
    • On macOS, follow this procedure.
    • On Windows, right-click the certificate file and select Install Certificate.
  2. Log in to the Harbor registry with the user admin. When prompted, enter the harborAdminPassword that you set when you installed the Harbor package in the shared services cluster.

    docker login harbor.yourdomain.com -u admin
    
  3. Tag an existing image that you have already pulled locally, for example, nginx:1.7.9.

    docker tag nginx:1.7.9 harbor.yourdomain.com/library/nginx:1.7.9
    
  4. Push the image to the Harbor registry.

    docker push harbor.yourdomain.com/library/nginx:1.7.9
    
  5. Now you can pull the image from the Harbor registry on any machine where the Harbor CA certificate is installed.

    docker pull harbor.yourdomain.com/library/nginx:1.7.9
    

Push the Tanzu Kubernetes Grid Images into the Harbor Registry

The Tanzu Kubernetes Grid images are published in a public container registry and used by Tanzu Kubernetes Grid to deploy Tanzu Kubernetes clusters and packages. When creating a Tanzu Kubernetes cluster, in order for Tanzu Kubernetes cluster nodes to pull Tanzu Kubernetes Grid images from the Harbor shared service rather than over the Internet, you must first push those images to the Harbor shared service.

This procedure is optional if your Tanzu Kubernetes clusters have internet connectivity to pull external images.

If you only want to store your application images rather than the Tanzu Kubernetes Grid images in the Harbor shared service, follow the procedure in Trust Custom CA Certificates on Cluster Nodes to enable the Tanzu Kubernetes cluster nodes to pull images from the Harbor shared service, and skip the rest of this procedure.

NOTE: If your Tanzu Kubernetes Grid instance is running in an Internet-restricted environment, you must perform these steps on a machine that has an Internet connection and can access the Harbor registry that you have just deployed as a shared service.

  1. Create a public project named tkg from Harbor UI. Or, you can use another project name.

  2. Set the FQDN of the Harbor registry that is running as a shared service as an environment variable.

    On Windows platforms, use the SET command instead of export. Include the name of the default project in the variable. For example, if you set the Harbor hostname to harbor.yourdomain.com, set the following:

    export TKG_CUSTOM_IMAGE_REPOSITORY=harbor.yourdomain.com/tkg
    
  3. Follow step 2 and step 3 in Prepare an Internet-Restricted Environment to generate and run the publish-images.sh script.

  4. When the script finishes, add or update the following rows in the global configuration file, ~/.config/tanzu/tkg/config.yaml.

    These variables ensure that when creating a Management Cluster or Tanzu Kubernetes Cluster, Tanzu Kubernetes Grid always pulls Tanzu Kubernetes Grid images from Harbor that is running as a shared service, rather than from the external internet. If Harbor uses self-signed certificates, add the following to the configuration file:

    • TKG_CUSTOM_IMAGE_REPOSITORY_SKIP_TLS_VERIFY: false. Because the Tanzu connectivity webhook injects the Harbor CA certificate into cluster nodes, TKG_CUSTOM_IMAGE_REPOSITORY_SKIP_TLS_VERIFY should always be set to false when using Harbor as a shared service.
    • TKG_CUSTOM_IMAGE_REPOSITORY_CA_CERTIFICATE. Provide the CA certificate in base64 encoded format.

      TKG_CUSTOM_IMAGE_REPOSITORY: harbor.yourdomain.com/tkg
      TKG_CUSTOM_IMAGE_REPOSITORY_SKIP_TLS_VERIFY: false
      TKG_CUSTOM_IMAGE_REPOSITORY_CA_CERTIFICATE: LS0t[...]tLS0tLQ==
      

    If your Tanzu Kubernetes Grid instance is running in an Internet-restricted environment, you can disconnect the Internet connection now.

You can now use the tanzu cluster create command to deploy Tanzu Kubernetes clusters, and the images will be pulled from Harbor that is running in the shared services cluster. You can push images to the Harbor registry to make them available to all clusters that are running in the Tanzu Kubernetes Grid instance.

Connections between Tanzu Kubernetes cluster nodes and Harbor are secure, regardless of whether you use a trusted or a self-signed certificate for the Harbor shared service.

Update a Running Harbor Deployment

If you need to make changes to the configuration of the Harbor package after deployment, follow these steps to update your deployed Harbor package.

  1. Update the Harbor configuration in harbor-data-values.yaml. For example, you can increase the amount of registry storage by updating the persistence.persistentVolumeClaim.registry.size value.

  2. Update the configuration of the installed package:

    tanzu package installed update harbor \
    --version INSTALLED-PACKAGE-VERSION \
    --values-file harbor-data-values.yaml \
    --namespace INSTALLED-PACKAGE-NAMESPACE
    

    Where:

    • INSTALLED-PACKAGE-VERSION is the version of the installed Harbor package.
    • INSTALLED-PACKAGE-NAMESPACE is the namespace in which the Harbor package is installed.

    For example:

    tanzu package installed update harbor \
    --version 2.2.3+vmware.1-tkg.1 \
    --values-file harbor-data-values.yaml \
    --namespace my-packages
    

The Harbor package will be reconciled using the new value or values that you added. It can take up to five minutes for kapp-controller to apply the changes.

For more information about the tanzu package installed update command, see Update a Package in CLI Reference for User-Managed Packages. You can use this command to update the version or the configuration of an installed package.

check-circle-line exclamation-circle-line close-line
Scroll to top icon