hey I hope I'm audible so we know it's the last day of the conference and everyone has a lot to think about you're pretty saturated but we hoping we can give you like a little bit more right so we're going to be talking about project carel today but before we jump into that a little bit about ourselves so my name is somic I work at team tanzu atcom and I mainly work with developer experience tooling and a part of my job is to maintain the project we're going to be talking about today KL and I'm here with my colleague and hi I'm Daniel as you can tell by my name and probably not my accent I'm from here um I work in the tanzo team and the spring team I do Java for a living don't judge me and here are socials um you know feel free to reach out if you have questions if you have feedback we love to engage is the font size all right for the people in the back of the room yeah all right a little bit more this cool all right all right so carvo so um I guess we can really hop real quick to the website maybe so Carell started off as like a set of composable single purpose tools and they sort of come together to help you sort of manage your applications and ship them to your end user right I guess the keywords here are reliable single purpose and composable and when we say reliable we mean that it's the tools are important like they're very repeatable in nature and if we scroll down a bit we'll be taking a look at the tools you're talking about today so we'll mainly be talking about the first fight tools you see here and uh not the experimental ones so to sort of uh I guess the best way to explore the tools is to get your hands dirty right and that's exactly what we'll be doing so maybe we can hop back to the terminal all right let's get let's get rolling so what do we start with right so we'll be starting off with YT YT stands for yaml templating Tool right and that's exactly what it does the templates yaml but what sort of sets YT aside is that YT understands yaml a data structure which means that you can shape yaml in unique ways and everything that goes into YT is valid yaml and everything that comes out of it is the have valid yam so maybe you could take a quick look like we have some configuration to play around with so I want to point out that any any yaml is valid y That's valid is okay for ytt right um so if I do this I can pass it into ytt and it it works it doesn't have to be kubernetes resources so if you want to template your GitHub actions your config for I don't know what you can use ytt for that um and so we already have some basis for a kubernetes config because this is coupon right so fairly straightforward normal config service deployment and so we can use ytt and experiment on that so I'm going to open a second terminal here on the right uh and once I change any of these files I'm going to run a command and the command is going to be clear my terminal and then pass run ytt on the all the files in this directory and then pass them into yq to have some coloring right so here um I have my my file and if I go into the comy here I change the port to Fubar Capital right it updates on the right okay so we have infra to work with ytt what what should we do all right so so how we Supply YT instructions is that we use sort of special comment and let's start off with a variable maybe like let's see what it looks like to sort of replace a value with a variable so let's do a not port and I'm going to compute it dynamically right so here I'm writing ytt code that's executed and then I can use the output of that code in the in the in the program and it changes the value here mhm so now that we have like a variable pleas maybe we could try out a function so I see that we're using labels multiple places so let's sort of put together function that supplies those labels and sort of D duplicate a y rate so we could write a function in ytt that looks like this and you know it could be any function that actually looks like a function U but the reason why we use a function and not a variable is because we with functions we can do this I can take the yaml directly and this being valid yl it can be returned by the function so I can use it here labels right and then I guess SLE app right uh SLE app so I have labels here labels and then I think I have some more here labels so of course uh nothing changes if I change my label here sum label right it gets updated in all the places I think this is like a good uh good place to show how YTD is virtually incapable of producing invalid yaml right so maybe if you try to mess up the indentation just blows up right this is not valid yaml if I save it's going to tell me well you're trying to do something that's not allowed here it's not a map it has a value so I'm happy with this and I get feedback immediately I don't have to wait until I try to apply it to the cluster for it to blow up ytt already tells me this is wrong so let's try something more fun right uh so we have a list of ports over here how about we try to sort of create a fall Loop and loop over them Loop over like a few values right so so we have not ports and I could do ports manually like this um I can also do say oh my port is going to be 30,000 plus I for I in range I don't know four right something like that explodes because the node Port doesn't exist anymore and for node port in node ports right and I have to end my for Loop oops end my for Loop and it here so now I have note ports like this U that come from this list this weird list yep and so this is where you might notice that this looks a lot like python that's mainly because YT accepts instructions in starlock which is like a dialect of python right okay so we have done some funky stuff now but uh we do need our users to be able to sort of Supply some values when they're consuming our configuration right so let's look at what uh accepting values while the configuration is being consumed looks like right so for um using values that comes from outside or data that comes from outside there's a ytt module think of it as a library and so I'm going to load this data module it's called data and then from here I can reference it data of values and then I can ask for say a channel that should come that should be supplied to the program so of course it doesn't work because nothing is supplying channel here so I could run I could run the same command with yttf Dot and then data value Channel equals coupon for example right and then in that case it gets templated in from a a CLI flag so I guess this works just fine if you have one value but more often the not you'll have like a set of values so you can sort of Supply a file with your values in it so that you can replace like you can like Supply multiple values at the same time right so in in this Direct in this directory we have a a file called data values yo it could be called anything and in here I can supply the channel right so channel is going to be I don't know testing and so to to ytt this is just a yaml file so if I want to turn it into a a thing that provides data values I can annotate it and saying this is data values right and so now this is passed from here um we could be passing the note ports um you know uh I I don't know one two and three right and it's in the config so in here the node ports could be data. values. node ports and so now my node ports come from this data value file and like you probably don't want your end user to using like y ytt annotations you don't want them to know what ytt is most of the time so you can actually use like another flag which doesn't require The annotation so I'm going to copy this data values file put it one level up so it doesn't it's not included by default um and I change it uh so we said values and here I'm going to do node ports is just one channel is production and so what we say is our users don't really have to know the details of of how to work with ytt to just Supply a value file so we do this and we can do yttf Dash and then data values file it comes from this yaml file which is a normal yaml file and so now now we have our production um uh Channel and our Port being templated in um so let's do something interesting right let's change up the values file and maybe turn the port into a string and I think that'll work right now right so if I do this and I change this to a string um then I have node ports with the wrong type here right and users might try stuff like this right and you don't want them to be able to do that so YT has a concept of like value schema where you can sort of rest RCT what what values a user can supply right so I have my value schema prepared already so I don't have to type it but it's again it's a normal yaml file it has a special comment saying this is the schema um and it requires a channel that is uh empty a no Port which is an array of integers and then a namespace and if I save this then ytt complains it tells me well on line six in your data values yl you're supplying a string right and it doesn't match the expected type which is integer which I you find here in this value schema line four right and you can actually go like fancier with your validations you can have lens checks in place you can even have like a Lambda function which takes the value and sort of verifies it in certain ways right right yeah and so maybe maybe one thing we haven't shown this is happening in comments right so if I disable uh the ytt coloring this is just yaml comments um with with YTD I can still do comments this is a Comon comment right as you do need that so I guess we at the stage where we have like a way of shaping a yaml configuration but what YT also helps you do is that it sort of helps you apply overlays to large chunks of yaml files right so you can sort of shape your yl using some functions right so in here in this directory there's also an overlays file um overlays and so we can tell it change me this file change it evolve it and the way we do this is very similar to what you would be doing with customized right you're applying an overlay um and we tell ytt find all the nodes the yaml nodes that match anything and then for these I want you to change the API version to V1 somic 1 the best kubernetes version as you all know so if I do this ytt will complain to me and try and help me it says well we know by default I expect one node when you do match but you supplied two there was a service and a deployment so if I do this my deployment is now a V1 suic 1 deployment and V1 suic 1 service and since this is um this is like a bit too broad I want to scope it down and maybe do that just for the let's say for the service so we're going to only take a subset of the resources and I want a subset of type kind and change the service service right so save that so now the V1 the deployment is back to the boring apps V1 uh uh API version but the service is still V1 to MC1 and you can go crazy with any programming you want to happen in here um so for example if I oops if I take this to here and I make that into a variable so service is this so match by service and then I could say well you know what anything that's not a service I don't really care about it so here take me the opposite of service so not the not operation everything that is not a service I want you to Overlay remove it remove there we go and so now I only have a service because the other the deployment has been removed I guess it works the same way if you don't have overlay remove because it just replaces have those bits with like an mty file and you could in theory also patch in resources and what's cool is like these bits interact with each other so you can use functions uh you can use loops and you can also have data values being fed into your templates right so in in a way it's much more powerful than customized because you could write functions that read the existing data and then change it you know um patch a config that is in inside a config map or what have you yep so um I guess um you want to do a quick reap maybe yeah so quick recap ytt as our yaml templating tool um it's yaml aware it's it's a all the programming happens in comments and you can work with any yaml very useful and it's a good substitute for either Helm or customize or both and you can combine them right you can do a Helm template if you have Helm charts and then you want to apply overlays but customize is not powerful enough well you can apply overlays with ytt or on the other hand if you you can do craft your confli with ytt and apply your existing customized tools to it if you will if you want I guess what what's worth calling out is that you don't need to uproot your existing workflows to start using YTD you can start using it as like an additional layer right so now that we have like a way of dealing with a configuration I guess what comes next is how do we deploy to the cluster oh before we deploy it yes there's there's one cool thing that we haven't shown oh yeah so we're doing we're we're we're doing U you know fun stuff in the terminal uh but if you just want to try out ytt do you go to the carv website toyt for those in the back we can we can take a look at that right ytt right Carvel ytt and then down here here you have a playground which basically does what I'm doing in in my terminal so it has many examples if you want to learn how to Lo use a for Loop or a function and then you can change in here and this is prier and this is and as you may notice it changes here on the right and if I change the port to the wrong type hello right I got the output from ytt so sorry you were saying deploying this yes my bad okay so now the tool that c will use users to deploy and manage resources on top of the cluster is called CAP and how cap essentially works is that it manages resources as a group on the cluster and so cap already knows how certain resources behave and you can also use annotations to sort of tell cap to Define relationships between custom resources right so let's I guess our config has changed a bit right so we made a a more interesting confing more than just a deployment in fig map so if I run this with YT um I get you know ingresses Services config maps and at the end because we're we're we're a bit cheeky we put the name space in which everything is deployed at the end so I think that's fortunate because we can just use Cube cutle now to see how things would look different if you use Cube cutle instead right right so you know that with Cube cuttle if you're doing this um you should Define your resources in an order that makes sense so not the namespace at the end so if I try to do this it says well the name space is created but everything else fails because the Nam space got created after we tried to create the other resources so CU cutle is not really friendly with us here so the alternative is using cap so in here I'm going to zoom in again uh we can do cap deploy and then we give our app a name we're going to call it coupon it uses the file from standard in and then I'm going to say don't wait for my confirmation d d yes and so in here we have the output so cap is telling us everything that's going to be deployed so I'm going going to be creating a name space for you a deployment Services Ingress config map and everything so like when cap exits at this point you sure that all of your pods have spun up it sort of waits for your deployment to reach the desired state right so it does many things right it starts by applying things in an order that makes sense and that do not depend on how they're defined in the file so you can see it starts with creating the namespace once the namespace is created it will create the config map because the deployment wants the config map to be there and then once you know the the priority resources are created then we're going to create the deployment and then as suic said we just don't create it and let you write your own weight rules we know what a successful deployment looks like so we can wait on it and we can read the status and so you can see it takes you know a few seconds to it's actually really fast it takes three seconds to um reconcile and so once cap tells me this has succeeded it means my app is actually ready and I I can look at it once it's done deployed right so cap inspect um the app that's called coupon we called it right so in here we have all the resources that we created right we can see it as a tree and of course we can list all the apps the all the cap apps that are in the cluster so here's our coupon app but we also have some infrastructure that I created for desk talk so I installed a controller and an Ingress controller and so on as cap applications y so and you called out that the config map was created before the deployment right and I guess that's an example example of how you can sort of control certain Behavior with annotations so if you take a look at our configuration we tell cap that the config map is a version resource so cap cap already knows that config Maps might be referred in deployments so if we update this config map now what's going to happen is cap is going to create a new version of the config map and ensure that the deployment is updated as well so the deployment will be spinning up new pods which reflect the new config so we do the same thing we template the the config with ytc we reapply the same cap deploy so it's it's going to update our CAP app and I'm also passing the flag to tell it give me the diff of what you're doing here so first when we look at it it gives me a nice diff it tells you oh well here on your on your output of YT on line two I changed the text to from English to French but then it also tells me ay your deployment was using a version one of the config map I'm creating a a version two of your config map and then I'm changing the deployment to use the new version so that means my config map is created first and then my deployment rolls out and I don't have to roll it out manually um cap does that for me and of course it has custom you know you can do powerful custom rules yourself or ordering or so if you have like a bunch of custom resources you can Define groups of resources and sort of tell cap how their order amongst each other right right and so I can delete as well um so quick recap cap is cu cutle but it's friendly towards users so if you're hacking on your cluster and you're deploying without get UPS using cap is nice because you can find what you've deployed you don't need to keep track of the files um it has waiting built in and it has powerful rules for ordering so you can you know manage your own dependencies if things are not eventually consistent you say I want this first and then that and then if this succeeds give me that so I guess we at a point where we have a way of managing our configuration and we know how to deploy things right so whenever you're shipping your configuration though you want to be sure that everything's in a nice little box that your customer can consume so uh I guess where we're going to start off is uh images so more often than not your configuration is going to reference images and what you want to be sure about is that the image you were refering to while putting your configuration together is the same one that's being referred to when your users consuming your config ation and the only good way of doing this is using sham references because we not really sure if someone at hashiko pushed another version of HTTP Echo yesterday with the tag rate so for doing this we have a tool called cable and what cable does is it sort of helps you log down onto immutable references so let's take a look at what that looks like K build kbl great so uh we can take a image from the uh standard int it reads our file and then by some black magic it turns turns this image into its shave reference and gives me some annotations on on the deployment so how do how does that work how does the so CA essentially just looks for the image key and you know what your configuration might actually be using a key like container major times and you can configure cable to be aware of that so so if you like just provide any yaml with those keys in it cable is going to be able to resolve it which means you can in theory use cable with other platforms as well and if you write your custom resources and they use image it's fine you don't have to teach C how to do that okay and so you don't want so what you want to do however is sort of generate a lock of sorts so that when your users are consuming your configuration they have a reference as to which images were used when uh you were putting together your configuration so one thing we could do is like version this run ke build in version this specific version but then we kind of lose what was the tag we used and so instead we're going to tell it uh generate uh a lock file output and then we're going to put in the right place and then we'll we'll go into image package later on images. Yo right so if I run this same thing but now I have an extra file in image package images. yo and that tell me well I found and what you passed me I found htpa C1 and it resolved to this and now when I distribute my config I can distribute my config um my files with the tag in them and then my image package file with it and if cable consumes it it's immediate right I don't have to talk to dockerhub to know how to resolve this into a sha this is essentially what a user will be doing while consuming a configuration okay so now we show that our images are what they're supposed to be but we still have a configuration right what you want to be able to do is bundle your configuration into an artifact maybe an OC artifact so that you can test it sign it and like sort of ship it in the nice little box right and that's what image package does for us right so instead of doing kit Toops and pushing this to get um we can make uh immutable artifacts that we're going to be keeping here uh with image package so we do image package image package push into a bundle a bundle is a target oi image I'm going to push it to my local registry 5,000 coupon uh caral and then the tag will be demo right and then take all the files that are in the current directory so it pushes these files um so now if I take this uh artifact reference this one if my mouse works it doesn't work I'll retype it so in here I have an empty directory I can do image package pull the bundle that's called Local Host 5000 coupon uh Carl and I think the tag was demo and the output put me the output in the that's called the out directory so in my out directory here I have the files that are where on my local fight systems or in the this other directory so I think we should take like a quick look at the output that was just outputed so image package calls out that one or more images were not found in the same registry right so what happens is so image package also has this copy functionality where you can ask image package to copy a bundle and when you do that it sort of ensures that all of the images that were referenced in the lock file are also moved over to the new registry right so Carell demo and I'm going to pretend I'm going to reach another repository so to repo uh it's actually the same one but it has an alias on my machine 5,000 and then coupon Carval I don't Supply the tag the tag will be inferred by the tag of the previous artifact so it copies things over and it it finds that in my image lock file I had HTTP Echo so I have two images the bundle that has my config and HTP Echo it downloads HTTP Echo and then copies it to this other repository and so now if we pull the relocated bundle so in if here if I do pull bundle uh called demo and then two uh or output sorry and we're going to call that relocated relo recoated relocated there we go so over here image package sort of calls out that it could could find every image referred uh in the same project right and I think it'll be clearer if we take a look at the lock file uh it's in relocated uh [Music] relocated sl. image package so the HTTP Echo image is now on the same registry as um the bundle itself it's even in the same repository right it's it's not it's not referred by a tag but it's referred by its sha so if someone applies build to the config with this image package lock it means they can use the image that are hosted in the same repo as the image package bundle itself which is very useful when you're doing you know you have air gap environments or you have a a registry that you own and you want to be sure that the images come from there and not from the internet um so image package copy helps you with this this is how we distribute the tanzo application platform our customers they copy your bundle and we'll pull like I don't know 60 80 images and copy copy them to um to their platform so for bundling two things K build to take an image reference and make it immutable by using a shot and produce a lock file so it can be repeated and then image package for managing configuration so bundling configuration and and do oci ops or registry Ops whatever you want to call it and then relocate bundles across repositories and it can even be recursive like an image package bundle can reference another bundle and so image package is smart enough to copy everything your entire dependency tree from one registry to another so um now that we have a way of sort of putting everything we want to ship into a nice little box uh I guess this is when we start talking about cap controller so cap controller surfaces certain apis on your cluster and is widely divided into two parts I guess so the first bit is the app SE itself so we have like a nice flow for obtaining the desired cluster state right so we fetch our configuration using image package then we templated using BYT and c and then we deployed using cap so what the appc allows you to do is it allows you to put these steps in like a declarative form and that's essentially how you define your application right so classic GitHub are the target where do I want to deploy my things either another cluster or for the same cluster with a different service account that's scoped um where I where I fetch my config from so you can fetch it from you know uh an image package bundle but also from get or from a Helm chart repository if I want um and then how do we change it how do we modify it so we run ytt but we can run Hound template we can use cild to pin images and how we deploy them um well it's called CAP controller so we deploy it with cap yeah and with in the template section you can really see the composability bit because as we mentioned earlier like if you're already using Helm template and want to use YT after it you can actually order those steps similarly even in the app definition right okay so maybe we could take a look at our the application that we just put together but as an apps here right so I prepackaged this bundle uh just in case the demo went wrong but apparently it's all right uh so we have an app that y all here uh it's an app CR and it's going to get its conf fig from an image package bundle and then it's going to apply a ytt the ytt templating on the image taking everything that's under the config directory and I want to supply as a user I want to supply my own data values there are many ways to supply data values one of them is create a secret in my cluster use that secret I can also use a file that comes from I don't know git repositor get repository another image package bundle or something then we also apply kbuild um to resolve HTP Echo to the relocated version of HTP Echo that lives into this kind registry and then we deploy with cap so let's deploy speaking of deploying with cap I think I've deleted the coupon app yes so we can cap deploy uh and the the file is called app.yaml right uh and I have to give this an app name of course app this is going to be coupon appc so you know cap tells me I'm going to deploy this app R the secret that goes with it and then the the the permissions arback that goes with it so that when this deployment happens cap controller doesn't use its you know very powerful cluster admin service account it uses this scoped service account and so this app can only create resources that a user with this service account would be able to do so let's do this and then well this reconciles into an app right which reconciles fast and in the end we have some pods that get deployed I guess somewhere demo namespace here right so if you do like a cap LSA right now I think we'll be able to see that what the appc did at the end of the day is it created a cap app right so I have to zoom out a little bit unfortunately but here uh we created a simple app.app yeah oops uh zoom out zoom out there we go so I can now I can cap delete the app that's called uh coupon appc right so one of the the drawbacks of this and I know that because I'm an app developer I write Java I don't write yamamo for a living is that I have to be kind of very intimate with how it works right and what's this image package thing what's uh what's a bundle what's ytt Etc um so cap controller has nice utilities to do this to make this more more accessible to you know end users or your developer personas in your in your organizations so that's where we start to talk about the second part of the apis that cap controller surfaces and those are the packaging apis the packaging apis allow let's say a cluster admin kind of actor to add make certain information available on the cluster about different versions of of apps and as as someone who's consuming that cluster you can use those apis to install a specific version of an app that's been shipped so what we're going to do is we're going to sort of change personas here and look at what it looks like for someone who's using a cluster to install certain apps on it right right so we are using uh the key control command line uh and we can say well package available oh it's in it's a different name space I think install so I put everything in in a different name Suite so K control package available list right and here as a developer I'm not Interac I'm not doing yaml I'm just using my you know CLI and tells me well you have this caral demo that you can install or certain manager all right I would like to install carel demo how how does that work um get so K control package available get the the package that's called caral garer garwf right it tells me well it's a ccon caral demo app it does this it does that there's one version okay cool um can you tell me more about this well uh for version say version 0 1 1 0 0 um we can tell it well this is fine but what's the values schema for that and so here's what I need to configure my caral app I need to provide a channel I need to provide a list of domains I need to provide a namespace this a string it has a default doesn't have a default it has some open API schema that tells me what I should do with this so I prepared a values file uh in here in values. Yo and so I can K control package install the package is called carel garer WF the version is one and then I'm going to give it an install name so coupon uh package install and then a values file uh that is dat values values. yo right and like the output sort of shows you that when you do this right what essentially happens is the fetch template deploy steps it fetches the image package bundle a template set with ytn cable and at the end it's deploying things using cap so you can sort of see the same diff that we saw like earlier in the demo right right and so this is a a developer friendly workflow but of course uh under the hood what it's really doing is creating custom resources on the cluster so we have packaging resources package repository a package when I do K control package available list it's going to look up the packages when I do K control package install it's going to do a package install so it's it's still um get UPS friendly if I want and if I'm a developer I don't care about yl I can use this K control CLI like this that's sort of nice because like as as in when a usage of car matures you can sort of move to having a more G opsy workflow to manage like all of your infrastructure right okay um we're almost at time um before we we close this out um there's the demo for the the repository for this demo is on the internet on the left and then on the right hand side feedback for us take 20 seconds give us a comment so we can know what we can do better and of course join our uh slack channel on the kubernetes slack which is Carval and reach out on Twitter if you want and reach out to us after the session thank you very much thank you I think we have one minute for one question is there one question one yes hi thanks for the talk uh quick question about ytt if I want to do like compo composable stuff where I develop stuff in ytt and why I want my developers to use it uh I cannot use any remote sources version stuff like that the composition happens later in the chain is that my understanding correct y so that's actually a good question so we actually skipped over a tool called vendor and what vendor allow you allows you to do is that you can like like fetch um configuration of files any files for that matter from multiple different sources right so I've seen uh Folks at some organizations do this where they use vendor as a package manager for YT so you can Define some starlock modules and repeatable ytt that your developers can then use using V so a vendor yamel file essentially becomes something like a go mode where you can lock onto certain versions of YT packages that you're using right right is that but ytt itself just take a bunch of yaml files and outputs yaml and that's it all right thank you very much have a good weekend