 and deployment tools at VMware Tanzu. And when I'm not passionately debating about packaging abstractions with my team, I enjoy gardening. I love rose bushes, but rose bushes have thorns. And that is what Kubernetes package management is today. It gets us started, but we often prick ourselves. What are these thorns? Well, today I have to install and update my packages manually without being able to use standard Kubernetes APIs, managing multiple packages or packages that have dependencies makes this process even more tedious and error-prone. And other challenges, I don't have a single artifact that I can easily inspect to get a bill of materials of everything that will be installed on my cluster. Overall, I don't have confidence that I know exactly what is running on my cluster and can recreate it anywhere, including in an air-gapped environment. Now, we all value the declarative APIs and layered approach that Kubernetes provides. Why not bring that same goodness to package management on Kubernetes? Similarly, we as the community are embracing standard OCI registry APIs. What if we could leverage OCI concepts like immutable digests to provide guarantees on what exact bits are running on a cluster? Let's keep the beautiful roses and evolve it to be thornless. We have learned that app operators, cluster operators, developers and package authors all benefit from different abstractions. With Carvo, we want users to take advantage of the part of the stack they need. Users don't have to take on the complexity introduced by additional layers and they can easily move up and down the stack when they need to. To enable this, we use app as the lowest level abstraction similar to a pod. And just like deployment builds on top of pod, a package and package install build on top of app. A package repository builds on top of packages. To look at how each of these abstractions actually look like, let's start with a simple application. It is made up of a service and a deployment. I'm going to use an app CR to deploy this app. An app CR represents a group of Kubernetes resources. I can use it to specify how to fetch template and deploy my app. And for each of these steps, I can specify what tool I want to use to accomplish it. I'm using a Git ref here as my source for fetching because I want to keep my app up to date with changes to the Git repo. But Fetch actually supports a variety of different sources including config map, which can be helpful for local development or an OCI image. Similarly for template, we support using YTT and help. We'd love to integrate more tools with your involvement and help in the project. We want to make Carvel really easy to use and extend so you can take it and run with it. Now let's deploy this app. The deploy succeeded and here's my app. Now I want to expose my app to the outside world. I want to use contours HTTP proxy to do that. I would like to consume Contour as a package that someone else has authored. This is where a package repository is helpful. You can think of a package repo as a Maven repo or RPM repo. It holds a collection of packages that are available to install on your cluster. After adding the package repo to my cluster, here are all the packages that are now available to install. I know my app works with version 117.1 of Contour, so let's go ahead and install that. Looking at the Contour package, we see that a package contains configuration metadata and OCI images that tell the package manager how to install itself. Similar to an app CR, package authors can use different tools for fetching, templating and deploying. You'll notice here we fetch using an immutable image reference, a digest. This means when you install this package, you're always going to get exactly the same bits. Now to install this package, I'm going to create a package installed referencing it. When I'm consuming a package authored by someone else, I don't know the details of how that software is fetched, templated and deployed. With a layered approach, we can encapsulate those details away from the consumer, providing a simpler API, while still leveraging the same app CR deploy mechanisms when interacting with the Kubernetes API to deploy the package. After my package install succeeds, I have Contour running. I can now add HTTP proxy provided by Contour to my simple app, check in those changes into my Git repo, and since I have my app CR watching on changes to my Git repo, it will create a HTTP proxy for me. I am now set up for continuous updates and I have confidence in what's running on my cluster. I can drive updates to my app with changes to the Git repo. I can make changes to either my app or the Contour package using standard Kubernetes objects. I know what's running on my cluster is locked down to the contents of an immutable bundle and I can pick up my configuration and recreate the same state on any Kubernetes cluster, including in an air gap environment. We just saw what a package manager that is compatible with GitOps ideas can unlock and yet there is still much more I want to share with you. We have an opportunity to build something really cool and useful with Carvel. Please come join us by trying out the tools. We are very active on Kubernetes Slack and would love to keep in touch with you there. Thank you and have fun at KubeCon.