# kctrl - Package Kubernetes manifest from Git ###### tags: `kctrl` ## Packaging manifest from Git In this tutorial, we will see how to create a package from Kuberenetes manifest present in a Git repository. We will again use [MongoDb enterprise operator](https://github.com/mongodb/mongodb-enterprise-kubernetes) 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 git and the Kubernetes artifact. [`MongoDb enterprise operator`](https://github.com/mongodb/mongodb-enterprise-kubernetes) Github Repository mentions that [`crds.yaml`](https://github.com/mongodb/mongodb-enterprise-kubernetes/blob/master/crds.yaml) and [`mongodb-enterprise.yaml`](https://github.com/mongodb/mongodb-enterprise-kubernetes/blob/master/mongodb-enterprise.yaml) are the Kubernetes resources which can be installed directly to the cluster to make the operator available. We will package `crds.yaml` and `mongodb-enterprise.yaml` into a Carvel package 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-4 $ cd tutorial-4 $ 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-operator.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 Kubernetes manifest from this [`repo`](https://github.com/mongodb/mongodb-enterprise-kubernetes). Hence, we will select Option `4`. `> Enter Git URL ():` * In this, we will enter the github URL. We will enter `https://github.com/mongodb/mongodb-enterprise-kubernetes`. `> Enter Git Reference (origin/main):` * We need to provide the branch from where we want to fetch our Kubernetes manifest. We will use `1.17.2`. `> Enter the paths which contain Kubernetes manifests ():` * As mentioned above, we will use `crds.yaml,mongodb-enterprise.yaml` 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-operator-bundle` to `docker.io/<YOUR_DOCKERHUB_ACCOUNT>/mongodb-operator-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-operator.carvel.dev/package.yml apiVersion: data.packaging.carvel.dev/v1alpha1 kind: Package metadata: creationTimestamp: null name: mongodb-operator.carvel.dev.1.0.0 spec: refName: mongodb-operator.carvel.dev releasedAt: "2022-11-10T08:34:33Z" template: spec: deploy: - kapp: {} fetch: - imgpkgBundle: image: index.docker.io/rohitagg2020/mongodb-operator-bundle@sha256:234e7f573a31a61653533742730143aedf62bf640d4145bf2220a6375380aabc template: - ytt: paths: - upstream - kbld: paths: - '-' - .imgpkg/images.yml valuesSchema: openAPIv3: default: null nullable: true version: 1.0.0 $ cat carvel-artifacts/packages/mongodb-operator.carvel.dev/metadata.yml apiVersion: data.packaging.carvel.dev/v1alpha1 kind: PackageMetadata metadata: creationTimestamp: null name: mongodb-operator.carvel.dev spec: displayName: mongodb-operator longDescription: mongodb-operator.carvel.dev shortDescription: mongodb-operator.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-operator.carvel.dev $ cp ../tutorial-3/carvel-artifacts/packages/mongodb-operator.carvel.dev/package.yml packages/mongodb.carvel.dev/1.0.0.yml $ cp ../tutorial-3/carvel-artifacts/packages/mongodb-operator.carvel.dev/metadata.yml packages/mongodb.carvel.dev/ $ tree . └── packages └── mongodb-operator.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 3.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:3.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-operator.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`