# kctrl - Package Helm Chart from Helm Repo ###### tags: `kctrl` ## Packaging Helm Chart from Helm Repo In this tutorial, we will see how to package an helm chart from a helm repo. We will use [MongoDb enterprise operator](https://github.com/mongodb/helm-charts/tree/main/charts/enterprise-operator) as an example here. ### Prerequisites 1. Install Carvel tools - [imgpkg](https://carvel.dev/imgpkg/docs/latest/install/), [kapp](https://carvel.dev/kapp/docs/latest/install/), [kbld](https://carvel.dev/kbld/docs/latest/install/), [vendir](https://carvel.dev/vendir/docs/latest/install/), [ytt](https://carvel.dev/ytt/docs/latest/install/). 2. Identify helm chart and helm repo. [`MongoDb enterprise operator`](https://github.com/mongodb/mongodb-enterprise-kubernetes) is available in this [`repo`](https://mongodb.github.io/helm-charts/) with chart name as [`enterprise-operator`](https://github.com/mongodb/helm-charts/tree/main/charts/enterprise-operator) and is managed by `mongodb` itself. We will package this helm chart and make it available for distribution. 3. Kubernetes cluster (I will be using [minikube](https://minikube.sigs.k8s.io/docs/)). 4. OCI registry where the package bundle and repository bundles will be pushed (I will be using my [Docker Hub](https://hub.docker.com/) account). ### Initialize Package ```bash $ mkdir tutorial-3 $ cd tutorial-3 $ kctrl pkg init ``` To initialize, we will use `kctrl pkg init`. This command asks a few basic questions regarding how we want to initialize our package. Lets go through them together: `> Enter the package reference name (samplepackage.corp.com):` * In this question, we need to enter the package name which will be a valid DNS subdomain name. We will use `mongodb.carvel.dev` as our package name. `> Enter source (1):` * Here, we need to enter from where to get the Kubernetes manifest or helm chart which needs to be packaged. As mentioned earlier, we will use [`enterprise-operator`](https://github.com/mongodb/helm-charts/tree/main/charts/enterprise-operator) from this [`repo`](https://mongodb.github.io/helm-charts/). Hence, we will select Option `3`. `> Enter helm chart repository URL ():` * In this, we have to enter the helm repository URL. We will enter `https://mongodb.github.io/helm-charts`. `> Enter helm chart name ():` * We will use `enterprise-operator` as the chart name. `> Enter helm chart version ():` * We will use `1.17.0` version. After entering all the above details, [`vendir`](https://carvel.dev/vendir/) will download the helm chart locally into `upstream` folder. `kctrl` will generate two files - package-build.yml and pacakge-resources.yml as output. `Package-resources.yml` file contain Package, PackageInstall and PackageMetadata while `package-build.yml` contains PackageBuild. All the values entered above have been recorded in these files. These files will be used by the `dev` and `pkg release` command subsequently. ### Release the package `kctrl pkg release` will be used to release the package. ```bash $ kctrl pkg release -v 1.0.0 ``` This command will create an imgpkg bundle, upload it to the OCI registry, create `package.yml` and `metadata.yml` which can be released for consumption eventually. Also, we are versioning our package with `-v` flag. `> Enter the registry URL ():` * Here we need to enter the registry URL where we need to push our imgpkg bundle. While entering the registry URL, ensure to change the value from `docker.io/rohitagg2020/mongodb-bundle` to `docker.io/<YOUR_DOCKERHUB_ACCOUNT>/mongodb-bundle`. Alternatively, you can enter other valid OCI registry URL. Now, we have created our Package and PackageMetadata. Let's see how the Package and PackageMetadata files look like: ```bash $ cat carvel-artifacts/packages/mongodb.carvel.dev/package.yml apiVersion: data.packaging.carvel.dev/v1alpha1 kind: Package metadata: creationTimestamp: null name: mongodb.carvel.dev.1.0.0 spec: refName: mongodb.carvel.dev releasedAt: "2022-11-10T08:34:33Z" template: spec: deploy: - kapp: {} fetch: - imgpkgBundle: image: index.docker.io/rohitagg2020/mongodb-bundle@sha256:194e7f573a31a61653533742730143aedf62bf640d4145bf2220a6375380a36c template: - helmTemplate: path: upstream - ytt: paths: - '-' - kbld: paths: - '-' - .imgpkg/images.yml valuesSchema: openAPIv3: properties: agent: properties: name: default: mongodb-agent type: string version: default: 11.12.0.7388-1 type: string type: object ... type: object version: 1.0.0 $ cat carvel-artifacts/packages/mongodb.carvel.dev/metadata.yml apiVersion: data.packaging.carvel.dev/v1alpha1 kind: PackageMetadata metadata: creationTimestamp: null name: mongodb.carvel.dev spec: displayName: mongodb longDescription: mongodb.carvel.dev shortDescription: mongodb.carvel.dev ``` Next step is to add it to package repository. These files can be submitted to the version control tools like github, etc. so that next time while running `pkg init` or `pkg release`, these values can be picked up as default values. ### Add package to the package repository `kctrl` can be used to release packages grouped together into a `PackageRepository`. Let’s bundle the `dynatrace` package created above into the PackageRepository. We will reuse the package repository which was created in `tutorial-2` `kctrl` will create a repo bundle from all the packages and metadata present in the `packages` folder. We will copy the `package.yml` and `metadata.yml` created above into the `packages` folder. We will follow the bundle format as mentioned [here](https://carvel.dev/kapp-controller/docs/v0.32.0/packaging-artifact-formats/#package-repository-bundle). Alternatively, while running `pkg release`, `--repo-output` flag can be used to copy the `package.yml` and `metadata.yml` in the prescribed PackageRepository bundle format at a specified location. ```bash $ mkdir -p packages/mongodb.carvel.dev $ cp ../tutorial-3/carvel-artifacts/packages/mongodb.carvel.dev/package.yml packages/mongodb.carvel.dev/1.0.0.yml $ cp ../tutorial-3/carvel-artifacts/packages/mongodb.carvel.dev/metadata.yml packages/mongodb.carvel.dev/ $ tree . └── packages └── mongodb.carvel.dev ├── 1.0.0.yml └── metadata.yml ``` Now, we will run `kctrl pkg repo release` to create and release the repository bundle. This repository bundle can be distributed to the the package consumer. ```bash $ kctrl pkg repo release -v 2.0.0 ``` In this command, it will ask for package repository name and where to push our repository bundle. Also, we are versioning our package repository with `-v` flag. `> Enter the package repository name (sample-repo.carvel.dev):` * We will use `demo-repo.carvel.dev` as our package repository name. `> Enter the registry url ():` * All the `packages` and `metadata` yaml files present in the `packages` folder will be bundled into `imgpkg bundle` and then pushed to the above registry url. While entering the registry URL, ensure to change the value from `docker.io/rohitagg2020/demo-repo-bundle` to `docker.io/<YOUR_DOCKERHUB_ACCOUNT>/demo-repo-bundle`. Alternatively, you can enter other valid OCI registry URL. ### Test the package (Optional) To test the package, we will again use kctrl. First step is to add the packageRepository to the Kubernetes cluster by using `kctrl pkg repo add` command. Once the package repository is added, all the packages in that repository becomes available to install. Then we can install a package by using `kctrl pkg install` command. Since package repository and package install are custom resources(CRs), we have to deploy the `kapp-controller` onto the cluster so that all these CRs become available on the cluster. #### Install kapp controller **_NOTE_**: In case you have already installed `kapp-controller`, skip this section. To install, `kapp-controller`, run ```bash $ kapp deploy -a kc -f https://github.com/vmware-tanzu/carvel-kapp-controller/releases/latest/download/release.yml ``` #### Add package repository To add the package repo, we will run ```bash $ kubectl create ns kctrl-test $ kctrl pkg repo add -r demo-repo --url docker.io/rohitagg2020/demo-repo-bundle:2.0.0 -n kctrl-test ``` To list the available packages, run ```bash $ kctrl pkg available --list -n kctrl-test ``` #### Install package To install the package, we will run ```bash $ kctrl pkg install -i pkg-install-demo -p mongodb.carvel.dev -v 1.0.0 -n kctrl-test ``` #### Confirm package installed successfully To confirm that package has been installed successfully, list down the pods and ensure that `mongodb-operator` has been deployed successfully. `$ kubectl get pods -n kctrl-test`