Use Gitops delivery with a Carvel App

This topic explains how you can deliver Carvel Packages, created by the Carvel Package Supply Chains, from a GitOps repository to one or more run clusters using Carvel App. You can use Carvel Package Supply Chains with Supply Chain Choreographer.

Prerequisites

To use GitOps Delivery with Carvel App, you must complete the following prerequisites:

  • You must create a Workload that uses the Carvel Package supply chains. For information about Carvel Packages, see Carvel Package Supply Chains. You must have at least one Carvel Package generated by this Workload stored in your GitOps repository.
  • You must have at least one run cluster. run clusters serve as your deployment environments. They can either be Tanzu Application Platform clusters, or Kubernetes clusters, but they must have kapp-controller and Contour installed. See the Carvel documentation and the Contour documentation.
  • If you plan to use a build cluster to control the deployment on all of the run clusters, you must create a Build cluster that has network access to your run clusters. If you intend to deploy directly on the run cluster without using a build cluster, a build cluster is only necessary for building the package.

Set up run cluster namespaces

Each run cluster must have a namespace and ServiceAccount with the correct permissions to deploy the Carvel Packages, PackageInstalls and Kubernetes Secrets. Create a namespace and ServiceAccount with the following permissions:

---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: RUN-CLUSTER-NS
  name: app-package-and-pkgi-install-role
rules:
  - apiGroups: ["data.packaging.carvel.dev"]
    resources: ["packages"]
    verbs: ["get", "list", "create", "update", "delete", "patch"]
  - apiGroups: ["packaging.carvel.dev"]
    resources: ["packageinstalls"]
    verbs: ["get", "list", "create", "update", "delete", "patch"]
  - apiGroups: [""]
    resources: ["secrets"]
    verbs: ["get", "list", "create", "update", "delete", "patch"]

Where RUN-CLUSTER-NS is the run cluster namespace you want to use.

If your run cluster is a Tanzu Application Platform cluster, see Set up developer namespaces to use your installed packages.

If your run cluster is not a Tanzu Application Platform cluster, the ServiceAccount must also have the following permissions:

---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: RUN-CLUSTER-NS
  name: app-cr-role
rules:
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["get", "list", "create", "update", "delete"]
- apiGroups: [""]
  resources: ["configmaps", "services"]
  verbs: ["get", "list", "create", "update", "delete"]
- apiGroups: ["networking.k8s.io"]
  resources: ["ingresses"]
  verbs: ["get", "list", "create", "update", "delete"]

Where RUN-CLUSTER-NS is the name of your run cluster you want to create a namespace with.

Create Carvel PackageInstalls and secrets

For each Carvel Package and each run cluster, you must create a Carvel PackageInstall and a Secret. The Carvel PackageInstall and the Secret is stored in your GitOps repository and deployed to run clusters by the Carvel App.

The following example shows GitOps repository structure after completing the procedures in this section:

app.default.tap/
  packages/
    20230321004057.0.0.yaml  # Package
  staging/
    packageinstall.yaml      # PackageInstall
    params.yaml              # Secret
  prod/
    packageinstall.yaml      # PackageInstall
    params.yaml              # Secret
  1. For each run cluster, create a Secret that has the values for each Package parameter. To see the configurable properties of the Package, inspect the Package CR’s valuesSchema. See Carvel Package Supply Chains. Store the Secret in your GitOps repository at PACKAGE-NAME/RUN-CLUSTER/params.yaml.

    ---
    apiVersion: v1
    kind: Secret
    metadata:
      name: app-values
    stringData:
      values.yaml: |
        ---
        workload_name: app
        replicas: 2
        hostname: app.mycompany.com
    

    Where:

    • PACKAGE-NAME is the name of your Carvel package you want to use.
    • RUN-CLUSTER is the name of the run cluster you want to use with the package.
    Note

    You must set a value for the workload_name parameter. You can skip setting other fields to use the default parameter values.

  2. For each run cluster, create a PackageInstall. Reference the Secret you created earlier. Store the PackageInstall in your GitOps repository at PACKAGE-NAME/RUN-CLUSTER/packageinstall.yaml.

    ---
    apiVersion: packaging.carvel.dev/v1alpha1
    kind: PackageInstall
    metadata:
      name: app
    spec:
      serviceAccountName: RUN-CLUSTER-NS-SA # ServiceAccount on run cluster with permissions to deploy Package, see "Set up run Cluster Namespaces"
      packageRef:
        refName: app.default.tap # name of the Package
        versionSelection:
          constraints: 20230321004057.0.0 # version of the Package
      values:
      - secretRef:
          name: app-values # Secret created in previous step
    

    Where:

    • PACKAGE-NAME is the name of your Carvel package you want to use.
    • RUN-CLUSTER is the name of the run cluster you want to use with the package.
    • RUN-CLUSTER-NS-SA is the ServiceAccount on your run cluster with permissions to deploy the package.

    To continuously deploy the latest version of your Package, set versionSelection.constraints: >=0.0.0. To revert to a previous version, update the versionSelection.constraints: field and annotate the PackageInstall:

    packaging.carvel.dev/downgradable: ""
    

    See the Carvel documentation.

  3. Push the PackageInstalls and Secrets to your GitOps repository.

Create an app

To create an app:

  1. You must give the build cluster access to the run clusters. On the build cluster create a Secret containing the run cluster’s kubeconfig for each run cluster:

    kubectl create secret generic RUN-CLUSTER-kubeconfig \
       -n BUILD-CLUSTER-NS \
       --from-file=value.yaml=PATH-TO-RUN-CLUSTER-KUBECONFIG
    

    Where:

    • RUN-CLUSTER is the name of the run cluster you want to use with your app.
    • BUILD-CLUSTER-NS is the namespace of the build cluster you want to use.
    • PATH-TO-RUN-CLUSTER-KUBECONFIG is the location of your run cluster kubeconfig.
  2. Each Carvel App custom resource (CR) must specify either a service account, by using spec.serviceAccountName, in the same namespace where the App CR is located on the Build cluster. Or specify a Secret with kubeconfig contents for a target destination run cluster, by using spec.cluster.kubeconfigSecretRef.name, to explicitly provide the privileges required for managing app resources. The example in this section uses a target run cluster.

  3. The Carvel App custom resource represents a collection of Kubernetes resources that kapp-controller can fetch and deploy to a cluster.

    The App points at the Git repository branch where kapp-controller resources, such as PackageRepository and Packages, are defined. By default, an App custom resource syncs the cluster with its fetch source every 30 seconds to prevent the cluster state from drifting from its source of truth. Create the following App on your Build cluster:

    ---
    apiVersion: kappctrl.k14s.io/v1alpha1
    kind: App
    metadata:
      name: hello-app-app
      namespace: BUILD-CLUSTER-NS
    spec:
      # specifies that app should be deployed to destination cluster;
      # by default, cluster is same as where this resource resides
      cluster:
        # specifies namespace in destination cluster
        namespace: ns2
        # specifies secret containing kubeconfig
        kubeconfigSecretRef:
          # specifies secret name within app's namespace
          name: cluster1
          # specifies key that contains kubeconfig
          key: value
      fetch:
      - git:
          url: # GitOps repo URL ex: https://github.com/mycompany/my-gitops
          ref: # GitOps repo branchex: origin/main
          subPath: PATH-FOR-PACKAGES # ex: hello-app.dev.tap/packages/
      - git:
          url: # GitOps repo URL ex: https://github.com/mycompany/my-gitops
          ref: # GitOps repo branch ex: origin/main
          subPath: PATH-FOR-PACKAGE-INSTALLS # ex: hello-app.dev.tap/runcluster1
      template:
      - ytt: {}
    
      deploy:
      - kapp:
          intoNs: DESIRED-NAMESPACE
          rawOptions: ["--dangerous-allow-empty-list-of-resources=true"]
    

    Where:

    • DESIRED-NAMESPACE is the namespace you want to use with your app.
    • PATH-FOR-PACKAGE-INSTALLS is the package install path.
    • PATH-FOR-PACKAGES is the package path.
    • BUILD-CLUSTER-NS is the build cluster namespace.
    Note

    The fetch section includes entries for all the locations in the GitOps repository to deploy, and append with other run clusters if needed.

Verify applications

To verify your installation:

  1. Target a run cluster. Confirm that all Packages from the GitOps repository are deployed:

    kubectl get packages -A
    
  2. Target a run cluster. Confirm that all PackageInstalls are reconciled:

    kubectl get packageinstalls -A
    

You can access your application on each run cluster.

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